diff --git a/src/Numerics/LinearAlgebra/Complex/IO/DelimitedReader.cs b/src/Numerics/LinearAlgebra/Complex/IO/DelimitedReader.cs new file mode 100644 index 00000000..03f108d0 --- /dev/null +++ b/src/Numerics/LinearAlgebra/Complex/IO/DelimitedReader.cs @@ -0,0 +1,71 @@ +// +// 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.Complex.IO +{ + using System; + using System.Numerics; + using Generic; + using LinearAlgebra.IO; + + /// + /// Creates a from a delimited text file. If the user does not + /// specify a delimiter, then any whitespace is used. + /// + /// The type of the matrix to return. + public class DelimitedReader : DelimitedReader + where TMatrix : Matrix + { + /// + /// Initializes a new instance of the class using + /// any whitespace as the delimiter. + /// + public DelimitedReader() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The delimiter to use. + public DelimitedReader(char delimiter) : base(delimiter) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The delimiter to use. + /// + /// + /// If is . + /// + public DelimitedReader(string delimiter) : base(delimiter) + { + } + } +} diff --git a/src/Numerics/LinearAlgebra/Complex32/IO/DelimitedReader.cs b/src/Numerics/LinearAlgebra/Complex32/IO/DelimitedReader.cs new file mode 100644 index 00000000..b29cc993 --- /dev/null +++ b/src/Numerics/LinearAlgebra/Complex32/IO/DelimitedReader.cs @@ -0,0 +1,71 @@ +// +// 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.Complex32.IO +{ + using System; + using Generic; + using LinearAlgebra.IO; + using Numerics; + + /// + /// Creates a from a delimited text file. If the user does not + /// specify a delimiter, then any whitespace is used. + /// + /// The type of the matrix to return. + public class DelimitedReader : DelimitedReader + where TMatrix : Matrix + { + /// + /// Initializes a new instance of the class using + /// any whitespace as the delimiter. + /// + public DelimitedReader() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The delimiter to use. + public DelimitedReader(char delimiter) : base(delimiter) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The delimiter to use. + /// + /// + /// If is . + /// + public DelimitedReader(string delimiter) : base(delimiter) + { + } + } +} diff --git a/src/Numerics/LinearAlgebra/Double/IO/DelimitedReader.cs b/src/Numerics/LinearAlgebra/Double/IO/DelimitedReader.cs index bcaf9b66..13cb5605 100644 --- a/src/Numerics/LinearAlgebra/Double/IO/DelimitedReader.cs +++ b/src/Numerics/LinearAlgebra/Double/IO/DelimitedReader.cs @@ -27,57 +27,31 @@ namespace MathNet.Numerics.LinearAlgebra.Double.IO { using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Reflection; - using System.Text.RegularExpressions; using Generic; + using LinearAlgebra.IO; /// /// Creates a from a delimited text file. If the user does not /// specify a delimiter, then any whitespace is used. /// /// The type of the matrix to return. - public class DelimitedReader : MatrixReader + public class DelimitedReader : DelimitedReader where TMatrix : Matrix { - /// - /// Constructor to create matrix instance. - /// - private static readonly ConstructorInfo Constructor = typeof(TMatrix).GetConstructor(new[] { typeof(int), typeof(int) }); - - /// - /// Whitespace regular expression. - /// - private static readonly Regex WhiteSpace = new Regex(@"[\s]+"); - - /// - /// The delimiter to use. - /// - private readonly Regex _delimiter; - - /// - /// The to use. - /// - private CultureInfo _cultureInfo = CultureInfo.CurrentCulture; - /// /// Initializes a new instance of the class using /// any whitespace as the delimiter. /// - public DelimitedReader() + public DelimitedReader() { - _delimiter = WhiteSpace; } /// /// Initializes a new instance of the class. /// /// The delimiter to use. - public DelimitedReader(char delimiter) + public DelimitedReader(char delimiter) : base(delimiter) { - _delimiter = new Regex("[" + new string(delimiter, 1) + "]+"); } /// @@ -89,109 +63,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double.IO /// /// If is . /// - public DelimitedReader(string delimiter) + public DelimitedReader(string delimiter) : base(delimiter) { - if (delimiter == null) - { - throw new ArgumentNullException("delimiter"); - } - - _delimiter = new Regex("[" + delimiter + "]+"); - } - - /// - /// 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; - } - } - } - - /// - /// Gets or sets a value indicating whether the files has a header row. - /// - /// - /// true if this instance has a header row; otherwise, false. - /// - /// Defaults to . - public bool HasHeaderRow - { - get; - set; - } - - /// - /// Performs the actual reading. - /// - /// The to read the matrix from. - /// - /// A matrix containing the data from the . is returned if the is empty. - /// - protected override TMatrix DoReadMatrix(Stream stream) - { - var data = new List(); - - // max is used to supports files like: - // 1,2 - // 3,4,5,6 - // 7 - // this creates a 3x4 matrix: - // 1, 2, 0 ,0 - // 3, 4, 5, 6 - // 7, 0, 0, 0 - var max = -1; - var reader = new StreamReader(stream); - var line = reader.ReadLine(); - if (HasHeaderRow) - { - line = reader.ReadLine(); - } - - while (line != null) - { - line = line.Trim(); - if (line.Length > 0) - { - var row = _delimiter.Split(line); - max = Math.Max(max, row.Length); - data.Add(row); - } - - line = reader.ReadLine(); - } - - var ret = (TMatrix)Constructor.Invoke(new object[] { data.Count, max }); - - if (data.Count != 0) - { - for (var i = 0; i < data.Count; i++) - { - var row = data[i]; - for (var j = 0; j < row.Length; j++) - { - // strip off quotes - var value = row[j].Replace("'", string.Empty).Replace("\"", string.Empty); - ret[i, j] = double.Parse(value, NumberStyles.Any, _cultureInfo); - } - } - } - - reader.Close(); - reader.Dispose(); - return ret; } } } diff --git a/src/Numerics/LinearAlgebra/IO/DelimitedReader.cs b/src/Numerics/LinearAlgebra/IO/DelimitedReader.cs new file mode 100644 index 00000000..3540d48f --- /dev/null +++ b/src/Numerics/LinearAlgebra/IO/DelimitedReader.cs @@ -0,0 +1,290 @@ +// +// 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.IO +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Numerics; + using System.Reflection; + using System.Text.RegularExpressions; + using Generic; + using Numerics; + + /// + /// Creates a from a delimited text file. If the user does not + /// specify a delimiter, then any whitespace is used. + /// + /// The type of the matrix to return. + /// The data type of the Matrix. It can be either: double, float, Complex, or Complex32. + public class DelimitedReader : MatrixReader + where TMatrix : Matrix + where TDataType : struct, IEquatable, IFormattable + { + /// + /// Converts a string into the given data type. + /// + /// + /// The number as a string to convert. + /// + /// The converted number. + private delegate object ParseNumber(string number); + + /// + /// The function that will do the conversion for a given type. + /// + private ParseNumber _parseFunction; + + /// + /// Initializes static members of the class. + /// + private void SetParser() + { + var type = typeof(TDataType); + if (type == typeof(double)) + { + _parseFunction = ConvertDouble; + } + else if (type == typeof(float)) + { + _parseFunction = ConvertFloat; + } + else if (type == typeof(Complex)) + { + _parseFunction = ConvertComplex; + } + else if (type == typeof(Complex32)) + { + _parseFunction = ConvertComplex32; + } + else + { + throw new NotSupportedException(); + } + } + + /// + /// Converts the string into a Complex32. + /// + /// The number to convert. + /// The converted number. + private object ConvertComplex32(string number) + { + return number.ToComplex32(_cultureInfo); + } + + /// + /// Converts the string into a Complex. + /// + /// The number to convert. + /// The converted number. + private object ConvertComplex(string number) + { + return number.ToComplex(_cultureInfo); + } + + /// + /// Converts the string into a double. + /// + /// The number to convert. + /// The converted number. + private object ConvertDouble(string number) + { + return double.Parse(number, NumberStyles.Any, _cultureInfo); + } + + /// + /// Converts the string into a float. + /// + /// The number to convert. + /// The converted number. + private object ConvertFloat(string number) + { + return float.Parse(number, NumberStyles.Any, _cultureInfo); + } + + /// + /// Constructor to create matrix instance. + /// + private static readonly ConstructorInfo Constructor = typeof(TMatrix).GetConstructor(new[] { typeof(int), typeof(int) }); + + /// + /// The base regular expression. + /// + private static readonly string Base = "\\([^\\)]*\\)|'[^']*'|\"[^\"]*\"|[^{0}]*"; + + /// + /// The regular expression to use. + /// + private readonly Regex _regex; + + /// + /// The to use. + /// + private CultureInfo _cultureInfo = CultureInfo.CurrentCulture; + + /// + /// Initializes a new instance of the class using + /// any whitespace as the delimiter. + /// + public DelimitedReader() + { + _regex = new Regex(string.Format(Base, @"\s", RegexOptions.Compiled)); + SetParser(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The delimiter to use. + public DelimitedReader(char delimiter) + { + _regex = new Regex(string.Format(Base, delimiter), RegexOptions.Compiled); + SetParser(); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The delimiter to use. + /// + /// + /// If is . + /// + public DelimitedReader(string delimiter) + { + if (delimiter == null) + { + throw new ArgumentNullException("delimiter"); + } + + _regex = new Regex(string.Format(Base, delimiter, RegexOptions.Compiled)); + SetParser(); + } + + /// + /// 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; + } + } + } + + /// + /// Gets or sets a value indicating whether the files has a header row. + /// + /// + /// true if this instance has a header row; otherwise, false. + /// + /// Defaults to . + public bool HasHeaderRow + { + get; + set; + } + + /// + /// Performs the actual reading. + /// + /// The to read the matrix from. + /// + /// A matrix containing the data from the . is returned if the is empty. + /// + protected override TMatrix DoReadMatrix(Stream stream) + { + var data = new List(); + + // max is used to supports files like: + // 1,2 + // 3,4,5,6 + // 7 + // this creates a 3x4 matrix: + // 1, 2, 0 ,0 + // 3, 4, 5, 6 + // 7, 0, 0, 0 + var max = -1; + + var reader = new StreamReader(stream); + var line = reader.ReadLine(); + if (HasHeaderRow) + { + line = reader.ReadLine(); + } + + var dataType = typeof(TDataType); + while (line != null) + { + line = line.Trim(); + if (line.Length > 0) + { + var matches = _regex.Matches(line); + var row = (from Match match in matches where match.Length > 0 select match.Value).ToArray(); + max = Math.Max(max, row.Length); + data.Add(row); + } + + line = reader.ReadLine(); + } + + var ret = (TMatrix)Constructor.Invoke(new object[] { data.Count, max }); + + if (data.Count != 0) + { + for (var i = 0; i < data.Count; i++) + { + var row = data[i]; + for (var j = 0; j < row.Length; j++) + { + // strip off quotes + var value = row[j].Replace("'", string.Empty).Replace("\"", string.Empty); + ret[i, j] = (TDataType)_parseFunction(value); + } + } + } + + reader.Close(); + reader.Dispose(); + return ret; + } + } +} diff --git a/src/Numerics/LinearAlgebra/Double/IO/MatrixReader.cs b/src/Numerics/LinearAlgebra/IO/MatrixReader.cs similarity index 91% rename from src/Numerics/LinearAlgebra/Double/IO/MatrixReader.cs rename to src/Numerics/LinearAlgebra/IO/MatrixReader.cs index 72c78a26..25001bc2 100644 --- a/src/Numerics/LinearAlgebra/Double/IO/MatrixReader.cs +++ b/src/Numerics/LinearAlgebra/IO/MatrixReader.cs @@ -24,7 +24,7 @@ // OTHER DEALINGS IN THE SOFTWARE. // -namespace MathNet.Numerics.LinearAlgebra.Double.IO +namespace MathNet.Numerics.LinearAlgebra.IO { using System; using System.IO; @@ -35,7 +35,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.IO /// Base class to read a single from a file or stream. /// /// The type of Matrix to return. - public abstract class MatrixReader where TMatrix : Matrix + /// The data type of the Matrix. It can be either: double, float, Complex, or Complex32. + public abstract class MatrixReader + where TMatrix : Matrix + where TDataType : struct, IEquatable, IFormattable { /// /// Reads a from a file. @@ -46,7 +49,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.IO /// If the file doesn't exist. /// If a value is not a number or not in a valid format. /// If a value represents a number less than or greater than . - public Matrix ReadMatrix(string file) + public TMatrix ReadMatrix(string file) { if (file == null) { diff --git a/src/Numerics/LinearAlgebra/IO/MatrixWriter.cs b/src/Numerics/LinearAlgebra/IO/MatrixWriter.cs index e955034b..1eec21bf 100644 --- a/src/Numerics/LinearAlgebra/IO/MatrixWriter.cs +++ b/src/Numerics/LinearAlgebra/IO/MatrixWriter.cs @@ -36,7 +36,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO /// /// Base class to write a single to a file or stream. /// - /// The data type of the matrix. + /// The data type of the Matrix. It can be either: double, float, Complex, or Complex32. public abstract class MatrixWriter where TDataType : struct, IEquatable, IFormattable { /// diff --git a/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs b/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs index 8ffed659..8f689c04 100644 --- a/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs +++ b/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs @@ -27,57 +27,31 @@ namespace MathNet.Numerics.LinearAlgebra.Single.IO { using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Reflection; - using System.Text.RegularExpressions; using Generic; + using LinearAlgebra.IO; /// /// Creates a from a delimited text file. If the user does not /// specify a delimiter, then any whitespace is used. /// /// The type of the matrix to return. - public class DelimitedReader : MatrixReader + public class DelimitedReader : DelimitedReader where TMatrix : Matrix { - /// - /// Constructor to create matrix instance. - /// - private static readonly ConstructorInfo Constructor = typeof(TMatrix).GetConstructor(new[] { typeof(int), typeof(int) }); - - /// - /// Whitespace regular expression. - /// - private static readonly Regex WhiteSpace = new Regex(@"[\s]+"); - - /// - /// The delimiter to use. - /// - private readonly Regex _delimiter; - - /// - /// The to use. - /// - private CultureInfo _cultureInfo = CultureInfo.CurrentCulture; - /// /// Initializes a new instance of the class using /// any whitespace as the delimiter. /// - public DelimitedReader() + public DelimitedReader() { - _delimiter = WhiteSpace; } /// /// Initializes a new instance of the class. /// /// The delimiter to use. - public DelimitedReader(char delimiter) + public DelimitedReader(char delimiter) : base(delimiter) { - _delimiter = new Regex("[" + new string(delimiter, 1) + "]+"); } /// @@ -89,109 +63,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single.IO /// /// If is . /// - public DelimitedReader(string delimiter) + public DelimitedReader(string delimiter) : base(delimiter) { - if (delimiter == null) - { - throw new ArgumentNullException("delimiter"); - } - - _delimiter = new Regex("[" + delimiter + "]+"); - } - - /// - /// 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; - } - } - } - - /// - /// Gets or sets a value indicating whether the files has a header row. - /// - /// - /// true if this instance has a header row; otherwise, false. - /// - /// Defaults to . - public bool HasHeaderRow - { - get; - set; - } - - /// - /// Performs the actual reading. - /// - /// The to read the matrix from. - /// - /// A matrix containing the data from the . is returned if the is empty. - /// - protected override TMatrix DoReadMatrix(Stream stream) - { - var data = new List(); - - // max is used to supports files like: - // 1,2 - // 3,4,5,6 - // 7 - // this creates a 3x4 matrix: - // 1, 2, 0 ,0 - // 3, 4, 5, 6 - // 7, 0, 0, 0 - var max = -1; - var reader = new StreamReader(stream); - var line = reader.ReadLine(); - if (HasHeaderRow) - { - line = reader.ReadLine(); - } - - while (line != null) - { - line = line.Trim(); - if (line.Length > 0) - { - var row = _delimiter.Split(line); - max = Math.Max(max, row.Length); - data.Add(row); - } - - line = reader.ReadLine(); - } - - var ret = (TMatrix)Constructor.Invoke(new object[] { data.Count, max }); - - if (data.Count != 0) - { - for (var i = 0; i < data.Count; i++) - { - var row = data[i]; - for (var j = 0; j < row.Length; j++) - { - // strip off quotes - var value = row[j].Replace("'", string.Empty).Replace("\"", string.Empty); - ret[i, j] = float.Parse(value, NumberStyles.Any, _cultureInfo); - } - } - } - - reader.Close(); - reader.Dispose(); - return ret; } } } diff --git a/src/Numerics/LinearAlgebra/Single/IO/MatrixReader.cs b/src/Numerics/LinearAlgebra/Single/IO/MatrixReader.cs deleted file mode 100644 index 8f6364d0..00000000 --- a/src/Numerics/LinearAlgebra/Single/IO/MatrixReader.cs +++ /dev/null @@ -1,84 +0,0 @@ -// -// 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.Single.IO -{ - using System; - using System.IO; - using Generic; - using Properties; - - /// - /// Base class to read a single from a file or stream. - /// - /// The type of Matrix to return. - public abstract class MatrixReader where TMatrix : Matrix - { - /// - /// Reads a from a file. - /// - /// The file to read the matrix from. - /// A containing the data from the file. is returned if the file is empty. - /// If is . - /// If the file doesn't exist. - /// If a value is not a number or not in a valid format. - /// If a value represents a number less than or greater than . - public Matrix ReadMatrix(string file) - { - if (file == null) - { - throw new ArgumentNullException("file", Resources.StringNullOrEmpty); - } - - return ReadMatrix(File.OpenRead(file)); - } - - /// - /// Reads a from a . - /// - /// The to read the matrix from. - /// A matrix containing the data from the . is returned if the is empty. - /// If is . - /// If a value is not a number or not in a valid format. - /// If a value represents a number less than or greater than . - public TMatrix ReadMatrix(Stream stream) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - return DoReadMatrix(stream); - } - - /// - /// Subclasses override this method to do the actual reading. - /// - /// The to read the matrix from. - /// A matrix containing the data from the . is returned if the is empty. - protected abstract TMatrix DoReadMatrix(Stream stream); - } -} diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 2817748f..b40e4363 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -142,6 +142,7 @@ + @@ -174,6 +175,7 @@ + @@ -197,9 +199,12 @@ + + + @@ -220,7 +225,6 @@ - @@ -256,11 +260,9 @@ - - diff --git a/src/UnitTests/LinearAlgebraTests/Complex/IO/DelimitedReaderTests.cs b/src/UnitTests/LinearAlgebraTests/Complex/IO/DelimitedReaderTests.cs new file mode 100644 index 00000000..3853a967 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Complex/IO/DelimitedReaderTests.cs @@ -0,0 +1,125 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.IO +{ + using System; + using System.Globalization; + using System.IO; + using System.Text; + using LinearAlgebra.Complex; + using LinearAlgebra.Complex.IO; + using MbUnit.Framework; + + [TestFixture] + public class DelimitedReaderTests + { + [Test] + [MultipleAsserts] + public void CanParseCommaDelimitedData() + { + const string data = + @"a,b,c +(1,2) +""2.2"",0.3e1 +'(4,-5)',5,6 +"; + var reader = new DelimitedReader(',') + { + HasHeaderRow = true + }; + var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); + Assert.AreEqual(3, matrix.RowCount); + Assert.AreEqual(3, matrix.ColumnCount); + Assert.AreEqual(1.0, matrix[0, 0].Real); + Assert.AreEqual(2.0, matrix[0, 0].Imaginary); + Assert.AreEqual(0.0, matrix[0, 1]); + Assert.AreEqual(0.0, matrix[0, 2]); + Assert.AreEqual(2.2, matrix[1, 0]); + Assert.AreEqual(3.0, matrix[1, 1]); + Assert.AreEqual(0.0, matrix[1, 2]); + Assert.AreEqual(4.0, matrix[2, 0].Real); + Assert.AreEqual(-5.0, matrix[2, 0].Imaginary); + Assert.AreEqual(5.0, matrix[2, 1]); + Assert.AreEqual(6.0, matrix[2, 2]); + } + + [Test] + [MultipleAsserts] + public void CanParseTabDelimtedData() + { + var data = "1" + + Environment.NewLine + + "\"2.2\"\t\t0.3e1" + + Environment.NewLine + + "'4'\t5\t6"; + + 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); + Assert.AreEqual(1.0, matrix[0, 0]); + Assert.AreEqual(0.0, matrix[0, 1]); + Assert.AreEqual(0.0, matrix[0, 2]); + Assert.AreEqual(2.2, matrix[1, 0]); + Assert.AreEqual(3.0, matrix[1, 1]); + Assert.AreEqual(0.0, matrix[1, 2]); + Assert.AreEqual(4.0, matrix[2, 0]); + Assert.AreEqual(5.0, matrix[2, 1]); + Assert.AreEqual(6.0, matrix[2, 2]); + } + + [Test] + [MultipleAsserts] + public void CanParseWhiteSpaceDelimitedData() + { + const string data = + @"1 +""(2.2,3.3)"" 0.3e1 +'4' 5 6 +"; + var reader = new DelimitedReader(); + var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); + Assert.AreEqual(3, matrix.RowCount); + Assert.AreEqual(3, matrix.ColumnCount); + Assert.AreEqual(1.0, matrix[0, 0]); + Assert.AreEqual(0.0, matrix[0, 1]); + Assert.AreEqual(0.0, matrix[0, 2]); + Assert.AreEqual(2.2, matrix[1, 0].Real); + Assert.AreEqual(3.3, matrix[1, 0].Imaginary); + Assert.AreEqual(3.0, matrix[1, 1]); + Assert.AreEqual(0.0, matrix[1, 2]); + Assert.AreEqual(4.0, matrix[2, 0]); + Assert.AreEqual(5.0, matrix[2, 1]); + Assert.AreEqual(6.0, matrix[2, 2]); + } + + [Test] + [MultipleAsserts] + public void CanParsePeriodDelimitedData() + { + const string data = + @"a.b.c +1 +""2,2"".0,3e1+0,2e1i +'4,0'.5,0.6,0 +"; + var reader = new DelimitedReader('.') + { + HasHeaderRow = true, + CultureInfo = new CultureInfo("tr-TR") + }; + + var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); + Assert.AreEqual(3, matrix.RowCount); + Assert.AreEqual(3, matrix.ColumnCount); + Assert.AreEqual(1.0, matrix[0, 0]); + Assert.AreEqual(0.0, matrix[0, 1]); + Assert.AreEqual(0.0, matrix[0, 2]); + Assert.AreEqual(2.2, matrix[1, 0]); + Assert.AreEqual(3.0, matrix[1, 1].Real); + Assert.AreEqual(2.0, matrix[1, 1].Imaginary); + Assert.AreEqual(0.0, matrix[1, 2]); + Assert.AreEqual(4.0, matrix[2, 0]); + Assert.AreEqual(5.0, matrix[2, 1]); + Assert.AreEqual(6.0, matrix[2, 2]); + } + } +} diff --git a/src/UnitTests/LinearAlgebraTests/Complex32/IO/DelimitedReaderTests.cs b/src/UnitTests/LinearAlgebraTests/Complex32/IO/DelimitedReaderTests.cs new file mode 100644 index 00000000..e8483415 --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/Complex32/IO/DelimitedReaderTests.cs @@ -0,0 +1,126 @@ +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.IO +{ + using System; + using System.Globalization; + using System.IO; + using System.Text; + using LinearAlgebra.Complex32; + using LinearAlgebra.Complex32.IO; + using MbUnit.Framework; + using Numerics; + + [TestFixture] + public class DelimitedReaderTests + { + [Test] + [MultipleAsserts] + public void CanParseCommaDelimitedData() + { + const string data = + @"a,b,c +(1,2) +""2.2"",0.3e1 +'(4,-5)',5,6 +"; + var reader = new DelimitedReader(',') + { + HasHeaderRow = true + }; + var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); + Assert.AreEqual(3, matrix.RowCount); + Assert.AreEqual(3, matrix.ColumnCount); + Assert.AreEqual(1.0f, matrix[0, 0].Real); + Assert.AreEqual(2.0f, matrix[0, 0].Imaginary); + Assert.AreEqual(0.0f, matrix[0, 1]); + Assert.AreEqual(0.0f, matrix[0, 2]); + Assert.AreEqual(2.2f, matrix[1, 0]); + Assert.AreEqual(3.0f, matrix[1, 1]); + Assert.AreEqual(0.0f, matrix[1, 2]); + Assert.AreEqual(4.0f, matrix[2, 0].Real); + Assert.AreEqual(-5.0f, matrix[2, 0].Imaginary); + Assert.AreEqual(5.0f, matrix[2, 1]); + Assert.AreEqual(6.0f, matrix[2, 2]); + } + + [Test] + [MultipleAsserts] + public void CanParseTabDelimtedData() + { + var data = "1" + + Environment.NewLine + + "\"2.2\"\t\t0.3e1" + + Environment.NewLine + + "'4'\t5\t6"; + + 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); + Assert.AreEqual(1.0f, matrix[0, 0]); + Assert.AreEqual(0.0f, matrix[0, 1]); + Assert.AreEqual(0.0f, matrix[0, 2]); + Assert.AreEqual(2.2f, matrix[1, 0]); + Assert.AreEqual(3.0f, matrix[1, 1]); + Assert.AreEqual(0.0f, matrix[1, 2]); + Assert.AreEqual(4.0f, matrix[2, 0]); + Assert.AreEqual(5.0f, matrix[2, 1]); + Assert.AreEqual(6.0f, matrix[2, 2]); + } + + [Test] + [MultipleAsserts] + public void CanParseWhiteSpaceDelimitedData() + { + const string data = + @"1 +""(2.2,3.3)"" 0.3e1 +'4' 5 6 +"; + var reader = new DelimitedReader(); + var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); + Assert.AreEqual(3, matrix.RowCount); + Assert.AreEqual(3, matrix.ColumnCount); + Assert.AreEqual(1.0f, matrix[0, 0]); + Assert.AreEqual(0.0f, matrix[0, 1]); + Assert.AreEqual(0.0f, matrix[0, 2]); + Assert.AreEqual(2.2f, matrix[1, 0].Real); + Assert.AreEqual(3.3f, matrix[1, 0].Imaginary); + Assert.AreEqual(3.0f, matrix[1, 1]); + Assert.AreEqual(0.0f, matrix[1, 2]); + Assert.AreEqual(4.0f, matrix[2, 0]); + Assert.AreEqual(5.0f, matrix[2, 1]); + Assert.AreEqual(6.0f, matrix[2, 2]); + } + + [Test] + [MultipleAsserts] + public void CanParsePeriodDelimitedData() + { + const string data = + @"a.b.c +1 +""2,2"".0,3e1+0,2e1i +'4,0'.5,0.6,0 +"; + var reader = new DelimitedReader('.') + { + HasHeaderRow = true, + CultureInfo = new CultureInfo("tr-TR") + }; + + var matrix = reader.ReadMatrix(new MemoryStream(Encoding.UTF8.GetBytes(data))); + Assert.AreEqual(3, matrix.RowCount); + Assert.AreEqual(3, matrix.ColumnCount); + Assert.AreEqual(1.0f, matrix[0, 0]); + Assert.AreEqual(0.0f, matrix[0, 1]); + Assert.AreEqual(0.0f, matrix[0, 2]); + Assert.AreEqual(2.2f, matrix[1, 0]); + Assert.AreEqual(3.0f, matrix[1, 1].Real); + Assert.AreEqual(2.0f, matrix[1, 1].Imaginary); + Assert.AreEqual(0.0f, matrix[1, 2]); + Assert.AreEqual(4.0f, matrix[2, 0]); + Assert.AreEqual(5.0f, matrix[2, 1]); + Assert.AreEqual(6.0f, matrix[2, 2]); + } + } +} diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 8968a933..57a8d2ac 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -136,6 +136,7 @@ + @@ -179,6 +180,7 @@ +