diff --git a/src/Numerics/LinearAlgebra/Double/IO/DelimitedWriter.cs b/src/Numerics/LinearAlgebra/Double/IO/DelimitedWriter.cs new file mode 100644 index 00000000..d39186db --- /dev/null +++ b/src/Numerics/LinearAlgebra/Double/IO/DelimitedWriter.cs @@ -0,0 +1,167 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// Copyright (c) 2009-2010 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +namespace MathNet.Numerics.LinearAlgebra.Double.IO +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + + /// + /// Writes an to delimited text file. If the user does not + /// specify a delimiter, a tab separator is used. + /// + public class DelimitedWriter : MatrixWriter + { + /// + /// The delimiter to use. + /// + private readonly string _delimiter; + + /// + /// The to use. + /// + private CultureInfo _cultureInfo = CultureInfo.CurrentCulture; + + /// + /// Initializes a new instance of the class using + /// a comma as the delimiter. + /// + public DelimitedWriter() + { + _delimiter = ","; + } + + /// + /// Initializes a new instance of the class + /// using the given delimiter. + /// + /// + /// the delimiter to use. + /// + public DelimitedWriter(char delimiter) + { + _delimiter = new string(delimiter, 1); + } + + /// + /// Initializes a new instance of the class + /// using the given delimiter. + /// + /// + /// the delimiter to use. + /// + public DelimitedWriter(string delimiter) + { + _delimiter = delimiter; + } + + /// + /// Gets or sets the column header values. + /// + /// The column header values. + /// Will write the column headers if the list is not empty or null. + public IList ColumnHeaders + { + get; + set; + } + + /// + /// Gets or sets the to use when parsing the numbers. + /// + /// The culture info. + /// Defaults to CultureInfo.CurrentCulture. + public CultureInfo CultureInfo + { + get + { + return _cultureInfo; + } + + set + { + if (value != null) + { + _cultureInfo = value; + } + } + } + + /// + /// Writes the given to the given . + /// + /// The matrix to write. + /// The to write the matrix to. + /// The format to use on each element. + /// If either or is null. + protected override void DoWriteMatrix(Matrix matrix, TextWriter writer, string format) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + if (ColumnHeaders != null && ColumnHeaders.Count > 0) + { + for (var i = 0; i < ColumnHeaders.Count - 1; i++) + { + writer.Write(ColumnHeaders[i]); + writer.Write(_delimiter); + } + + writer.WriteLine(ColumnHeaders[ColumnHeaders.Count - 1]); + } + + var cols = matrix.ColumnCount - 1; + var rows = matrix.RowCount - 1; + for (var i = 0; i < matrix.RowCount; i++) + { + for (var j = 0; j < matrix.ColumnCount; j++) + { + writer.Write(matrix[i, j].ToString(format, _cultureInfo)); + if (j != cols) + { + writer.Write(_delimiter); + } + } + + if (i != rows) + { + writer.Write(Environment.NewLine); + } + } + } + } +} diff --git a/src/Numerics/LinearAlgebra/Double/IO/MatrixWriter.cs b/src/Numerics/LinearAlgebra/Double/IO/MatrixWriter.cs new file mode 100644 index 00000000..8fb2c744 --- /dev/null +++ b/src/Numerics/LinearAlgebra/Double/IO/MatrixWriter.cs @@ -0,0 +1,195 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// Copyright (c) 2009-2010 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; + +namespace MathNet.Numerics.LinearAlgebra.Double.IO +{ + /// + /// Base class to write a single to a file or stream. + /// + public abstract class MatrixWriter + { + /// + /// Writes the given to the given file. If the file already exists, + /// the file will be overwritten. + /// + /// The matrix to write. + /// The file to write the matrix to. + /// If either or is null. + public void WriteMatrix(Matrix matrix, string file) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (file == null) + { + throw new ArgumentNullException("file"); + } + + using (var writer = new StreamWriter(file)) + { + DoWriteMatrix(matrix, writer, null); + } + } + + /// + /// Writes the given to the given file. If the file already exists, + /// the file will be overwritten. + /// + /// the matrix to write. + /// The file to write the matrix to. + /// The format to use on each element. + /// If either or is null. + public void WriteMatrix(Matrix matrix, string file, string format) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (file == null) + { + throw new ArgumentNullException("file"); + } + + if (File.Exists(file)) + { + File.Delete(file); + } + + using (var writer = new StreamWriter(file)) + { + DoWriteMatrix(matrix, writer, format); + } + } + + /// + /// Writes the given to the given stream. + /// + /// The matrix to write. + /// The to write the matrix to. + /// If either or is null. + public void WriteMatrix(Matrix matrix, Stream stream) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + using (var writer = new StreamWriter(stream)) + { + DoWriteMatrix(matrix, writer, null); + } + } + + /// + /// Writes the given to the given stream. + /// + /// The to write. + /// The to write the matrix to. + /// The format to use on each element. + /// If either or is null. + public void WriteMatrix(Matrix matrix, Stream stream, string format) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + using (var writer = new StreamWriter(stream)) + { + DoWriteMatrix(matrix, writer, format); + } + } + + /// + /// Writes the given to the given . + /// + /// The matrix to write. + /// The to write the matrix to. + /// If either or is null. + public void WriteMatrix(Matrix matrix, TextWriter writer) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + DoWriteMatrix(matrix, writer, null); + } + + /// + /// Writes the given to the given . + /// + /// The matrix to write. + /// The to write the matrix to. + /// The format to use on each element. + /// If either or is null. + public void WriteMatrix(Matrix matrix, TextWriter writer, string format) + { + if (matrix == null) + { + throw new ArgumentNullException("matrix"); + } + + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + DoWriteMatrix(matrix, writer, format); + } + + /// + /// Subclasses must implement this method to do the actually writing. + /// + /// The matrix to serialize. + /// The to write the matrix to. + /// The format for the new matrix. + protected abstract void DoWriteMatrix(Matrix matrix, TextWriter writer, string format); + } +} diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index f3d49068..590991ef 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -108,7 +108,9 @@ + + diff --git a/src/Silverlight/Silverlight.csproj b/src/Silverlight/Silverlight.csproj index 799928f7..7a5771eb 100644 --- a/src/Silverlight/Silverlight.csproj +++ b/src/Silverlight/Silverlight.csproj @@ -263,9 +263,15 @@ LinearAlgebra\Double\IO\DelimitedReader.cs + + LinearAlgebra\Double\IO\DelimitedWriter.cs + LinearAlgebra\Double\IO\MatrixReader.cs + + LinearAlgebra\Double\IO\MatrixWriter.cs + LinearAlgebra\Double\ISolver.cs diff --git a/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedReaderTests.cs b/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedReaderTests.cs index aeb92213..b4abab62 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedReaderTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedReaderTests.cs @@ -49,7 +49,7 @@ + Environment.NewLine + "'4'\t5\t6"; - var reader = new DelimitedReader('\t'); + var reader = new DelimitedReader('\t'); var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); Assert.AreEqual(3, matrix.RowCount); Assert.AreEqual(3, matrix.ColumnCount); @@ -73,7 +73,7 @@ ""2.2"" 0.3e1 '4' 5 6 "; - var reader = new DelimitedReader(); + var reader = new DelimitedReader(); var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); Assert.AreEqual(3, matrix.RowCount); Assert.AreEqual(3, matrix.ColumnCount); diff --git a/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedWriterTests.cs b/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedWriterTests.cs new file mode 100644 index 00000000..1dc493c6 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Double/IO/DelimitedWriterTests.cs @@ -0,0 +1,90 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.IO +{ + using System; + using System.Globalization; + using System.IO; + using System.Text; + using LinearAlgebra.Double; + using LinearAlgebra.Double.IO; + using MbUnit.Framework; + + [TestFixture] + public class DelimitedWriterTests + { + [Test] + public void CanWriteCommaDelimitedData() + { + var matrix = new DenseMatrix(new[,] { { 1.1, 2.2, 3.3 }, { 4.4, 5.5, 6.6 }, { 7.7, 8.8, 9.9 } }); + var writer = new DelimitedWriter(','); + var stream = new MemoryStream(); + writer.WriteMatrix(matrix, stream); + var data = stream.ToArray(); + var reader = new StreamReader(new MemoryStream(data)); + var text = reader.ReadToEnd(); + const string expected = @"1.1,2.2,3.3 +4.4,5.5,6.6 +7.7,8.8,9.9"; + Assert.AreEqual(expected, text); + } + + [Test] + public void CanWritePeriodDelimitedData() + { + var matrix = new DenseMatrix(new[,] { { 1.1, 2.2, 3.3 }, { 4.4, 5.5, 6.6 }, { 7.7, 8.8, 9.9 } }); + var culture = new CultureInfo("tr-TR"); + var writer = new DelimitedWriter('.') + { + CultureInfo = culture + }; + var stream = new MemoryStream(); + writer.WriteMatrix(matrix, stream); + var data = stream.ToArray(); + var reader = new StreamReader(new MemoryStream(data)); + var text = reader.ReadToEnd(); + const string expected = @"1,1.2,2.3,3 +4,4.5,5.6,6 +7,7.8,8.9,9"; + Assert.AreEqual(expected, text); + } + + [Test] + public void CanWriteSpaceDelimitedData() + { + var matrix = new SparseMatrix(new[,] { { 1.1, 0, 0 }, { 0, 5.5, 0 }, { 0, 0, 9.9 } }); + var writer = new DelimitedWriter(' '); + var stream = new MemoryStream(); + writer.WriteMatrix(matrix, stream); + var data = stream.ToArray(); + var reader = new StreamReader(new MemoryStream(data)); + var text = reader.ReadToEnd(); + const string expected = @"1.1 0 0 +0 5.5 0 +0 0 9.9"; + Assert.AreEqual(expected, text); + } + + [Test] + public void CanWriteTabDelimitedData() + { + var matrix = new UserDefinedMatrix(new[,] { { 1.1, 2.2, 3.3 }, { 4.4, 5.5, 6.6 }, { 7.7, 8.8, 9.9 } }); + var headers = new[] { "a", "b", "c" }; + var writer = new DelimitedWriter('\t') + { + ColumnHeaders = headers + }; + var stream = new MemoryStream(); + writer.WriteMatrix(matrix, stream); + var data = stream.ToArray(); + var reader = new StreamReader(new MemoryStream(data)); + var text = reader.ReadToEnd(); + var expected = "a\tb\tc" + + Environment.NewLine + + "1.1\t2.2\t3.3" + + Environment.NewLine + + "4.4\t5.5\t6.6" + + Environment.NewLine + + "7.7\t8.8\t9.9"; + Assert.AreEqual(expected, text); + } + } +} diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index e25bc83d..d266f694 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -96,6 +96,7 @@ +