From fba4784a1f45457266fb08c18bcc8069b4657ddc Mon Sep 17 00:00:00 2001 From: Marcus Cuda Date: Wed, 3 Nov 2010 23:30:04 +0800 Subject: [PATCH] matlab: added complex support --- .../ManagedLinearAlgebraProvider.cs | 1 + .../LinearAlgebra/IO/Matlab/MatlabParser.cs | 57 +++++++---- src/Numerics/LinearAlgebra/IO/MatlabWriter.cs | 95 ++++++++++++++++--- .../Double/IO/MatlabWriterTests.cs | 12 +-- .../Single/IO/MatlabWriterTests.cs | 12 +-- src/UnitTests/UnitTests.csproj | 2 + 6 files changed, 135 insertions(+), 44 deletions(-) diff --git a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs index 886c595c..0776a7e5 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs @@ -288,6 +288,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra case Norm.FrobeniusNorm: break; } + throw new NotImplementedException(); } diff --git a/src/Numerics/LinearAlgebra/IO/Matlab/MatlabParser.cs b/src/Numerics/LinearAlgebra/IO/Matlab/MatlabParser.cs index 302e2f7a..288228f2 100644 --- a/src/Numerics/LinearAlgebra/IO/Matlab/MatlabParser.cs +++ b/src/Numerics/LinearAlgebra/IO/Matlab/MatlabParser.cs @@ -310,7 +310,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab case ArrayClass.Unknown: throw new NotSupportedException(); default: - matrix = PopulateDenseMatrix(type, reader, isComplex, rows, columns); + matrix = PopulateDenseMatrix(type, reader, isComplex, rows, columns, size); break; } @@ -357,9 +357,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab AlignData(reader.BaseStream, jcsize, false); var type = (DataType)reader.ReadInt32(); - - // skip length since we already no it for the number of rows - reader.BaseStream.Seek(4, SeekOrigin.Current); + var dataSize = reader.ReadInt32(); var matrix = CreateMatrix(true, rows, columns); var dataType = typeof(TDataType); @@ -384,11 +382,11 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab } else if (dataType == typeof(Complex)) { - PopulateComplexSparseMatrix((Matrix)(object)matrix, type, isComplex, ir, jc, reader); + PopulateComplexSparseMatrix((Matrix)(object)matrix, type, isComplex, ir, jc, reader, dataSize); } else if (dataType == typeof(Complex32)) { - PopulateComplex32SparseMatrix((Matrix)(object)matrix, type, isComplex, ir, jc, reader); + PopulateComplex32SparseMatrix((Matrix)(object)matrix, type, isComplex, ir, jc, reader, dataSize); } else { @@ -521,7 +519,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab /// The row indices. /// The column indices. /// The reader to read from. - private static void PopulateComplexSparseMatrix(Matrix matrix, DataType type, bool isComplex, IList ir, IList jc, BinaryReader reader) + private static void PopulateComplexSparseMatrix(Matrix matrix, DataType type, bool isComplex, IList ir, IList jc, BinaryReader reader, int dataSize) { var col = 0; for (var i = 0; i < ir.Count; i++) @@ -571,8 +569,14 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab if (isComplex) { + var skip = dataSize % 8; + + // skip pad + reader.ReadBytes(skip); + // skip header - reader.ReadBytes(8); + type = (DataType)reader.ReadInt32(); + reader.ReadInt32(); col = 0; for (var i = 0; i < ir.Count; i++) { @@ -631,7 +635,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab /// The row indices. /// The column indices. /// The reader to read from. - private static void PopulateComplex32SparseMatrix(Matrix matrix, DataType type, bool isComplex, IList ir, IList jc, BinaryReader reader) + private static void PopulateComplex32SparseMatrix(Matrix matrix, DataType type, bool isComplex, IList ir, IList jc, BinaryReader reader, int dataSize) { var col = 0; for (var i = 0; i < ir.Count; i++) @@ -681,8 +685,15 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab if (isComplex) { + var skip = dataSize % 8; + + // skip pad + reader.ReadBytes(skip); + // skip header - reader.ReadBytes(8); + type = (DataType)reader.ReadInt32(); + reader.ReadInt32(); + col = 0; for (var i = 0; i < ir.Count; i++) { @@ -741,7 +752,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab /// The number of rows. /// The number of columns. /// Returns a populated dense matrix. - private static Matrix PopulateDenseMatrix(DataType type, BinaryReader reader, bool isComplex, int rows, int columns) + private static Matrix PopulateDenseMatrix(DataType type, BinaryReader reader, bool isComplex, int rows, int columns, int size) { var matrix = CreateMatrix(false, rows, columns); @@ -767,11 +778,11 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab } else if (dataType == typeof(Complex)) { - PopulateComplexDenseMatrix((Matrix)(object)matrix, type, isComplex, reader, rows, columns); + PopulateComplexDenseMatrix((Matrix)(object)matrix, type, isComplex, reader, rows, columns, size); } else if (dataType == typeof(Complex32)) { - PopulateComplex32DenseMatrix((Matrix)(object)matrix, type, isComplex, reader, rows, columns); + PopulateComplex32DenseMatrix((Matrix)(object)matrix, type, isComplex, reader, rows, columns, size); } else { @@ -907,7 +918,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab /// The reader to read from. /// The number of rows. /// The number of columns. - public static void PopulateComplexDenseMatrix(Matrix matrix, DataType type, bool isComplex, BinaryReader reader, int rows, int columns) + public static void PopulateComplexDenseMatrix(Matrix matrix, DataType type, bool isComplex, BinaryReader reader, int rows, int columns, int dataSize) { switch (type) { @@ -1017,8 +1028,14 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab if (isComplex) { + var skip = dataSize % 8; + + // skip pad + reader.ReadBytes(skip); + // skip header - reader.ReadBytes(8); + type = (DataType)reader.ReadInt32(); + reader.ReadInt32(); switch (type) { @@ -1137,7 +1154,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab /// The reader to read from. /// The number of rows. /// The number of columns. - public static void PopulateComplex32DenseMatrix(Matrix matrix, DataType type, bool isComplex, BinaryReader reader, int rows, int columns) + public static void PopulateComplex32DenseMatrix(Matrix matrix, DataType type, bool isComplex, BinaryReader reader, int rows, int columns, int dataSize) { switch (type) { @@ -1247,8 +1264,14 @@ namespace MathNet.Numerics.LinearAlgebra.IO.Matlab if (isComplex) { + var skip = dataSize % 8; + + // skip pad + reader.ReadBytes(skip); + // skip header - reader.ReadBytes(8); + type = (DataType)reader.ReadInt32(); + reader.ReadInt32(); switch (type) { diff --git a/src/Numerics/LinearAlgebra/IO/MatlabWriter.cs b/src/Numerics/LinearAlgebra/IO/MatlabWriter.cs index c1232f09..f3de218f 100644 --- a/src/Numerics/LinearAlgebra/IO/MatlabWriter.cs +++ b/src/Numerics/LinearAlgebra/IO/MatlabWriter.cs @@ -221,11 +221,12 @@ namespace MathNet.Numerics.LinearAlgebra.IO /// /// The writer we are using. /// The array class we are writing. + /// if set to true if this a complex matrix. /// The name name of the matrix. /// The number of rows. /// The columns of columns. /// The maximum number of non-zero elements. - private static void WriteMatrixTagAndName(BinaryWriter writer, ArrayClass arrayClass, string name, int rows, int columns, int nzmax) + private static void WriteMatrixTagAndName(BinaryWriter writer, ArrayClass arrayClass, bool isComplex, string name, int rows, int columns, int nzmax) { writer.Write((int)DataType.Matrix); @@ -238,7 +239,14 @@ namespace MathNet.Numerics.LinearAlgebra.IO // write array class and flags writer.Write((byte)arrayClass); - writer.Write((byte)0); + if (isComplex) + { + writer.Write((byte)ArrayFlags.Complex); + } + else + { + writer.Write((byte)0); + } writer.Write((short)0); writer.Write(nzmax); @@ -299,7 +307,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataMemoryStream = new MemoryStream()) using (var dataWriter = new BinaryWriter(dataMemoryStream)) { - WriteMatrixTagAndName(dataWriter, ArrayClass.Double, name, matrix.RowCount, matrix.ColumnCount, 0); + WriteMatrixTagAndName(dataWriter, ArrayClass.Double, false, name, matrix.RowCount, matrix.ColumnCount, 0); // write data dataWriter.Write((int)DataType.Double); @@ -332,10 +340,11 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataMemoryStream = new MemoryStream()) using (var dataWriter = new BinaryWriter(dataMemoryStream)) { - WriteMatrixTagAndName(dataWriter, ArrayClass.Single, name, matrix.RowCount, matrix.ColumnCount, 0); + WriteMatrixTagAndName(dataWriter, ArrayClass.Single, false, name, matrix.RowCount, matrix.ColumnCount, 0); // write data dataWriter.Write((int)DataType.Single); + dataWriter.Write(matrix.RowCount * matrix.ColumnCount * 4); for (var j = 0; j < matrix.ColumnCount; j++) @@ -347,6 +356,9 @@ namespace MathNet.Numerics.LinearAlgebra.IO } } + var pad = (matrix.RowCount * matrix.ColumnCount * 4) % 8; + PadData(dataWriter, pad); + data = dataMemoryStream.ToArray(); } @@ -365,7 +377,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataMemoryStream = new MemoryStream()) using (var dataWriter = new BinaryWriter(dataMemoryStream)) { - WriteMatrixTagAndName(dataWriter, ArrayClass.Double, name, matrix.RowCount, matrix.ColumnCount, 0); + WriteMatrixTagAndName(dataWriter, ArrayClass.Double, true, name, matrix.RowCount, matrix.ColumnCount, 0); // write data dataWriter.Write((int)DataType.Double); @@ -379,8 +391,18 @@ namespace MathNet.Numerics.LinearAlgebra.IO dataWriter.Write(value.Real); } } - - throw new NotImplementedException(); + + dataWriter.Write((int)DataType.Double); + dataWriter.Write(matrix.RowCount * matrix.ColumnCount * 8); + + for (var j = 0; j < matrix.ColumnCount; j++) + { + var column = matrix.Column(j); + foreach (var value in column) + { + dataWriter.Write(value.Imaginary); + } + } data = dataMemoryStream.ToArray(); } @@ -400,7 +422,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataMemoryStream = new MemoryStream()) using (var dataWriter = new BinaryWriter(dataMemoryStream)) { - WriteMatrixTagAndName(dataWriter, ArrayClass.Single, name, matrix.RowCount, matrix.ColumnCount, 0); + WriteMatrixTagAndName(dataWriter, ArrayClass.Single, true, name, matrix.RowCount, matrix.ColumnCount, 0); // write data dataWriter.Write((int)DataType.Single); @@ -415,7 +437,22 @@ namespace MathNet.Numerics.LinearAlgebra.IO } } - throw new NotImplementedException(); + var pad = (matrix.RowCount * matrix.ColumnCount * 4) % 8; + PadData(dataWriter, pad); + + dataWriter.Write((int)DataType.Single); + dataWriter.Write(matrix.RowCount * matrix.ColumnCount * 4); + + for (var j = 0; j < matrix.ColumnCount; j++) + { + var column = matrix.Column(j); + foreach (var value in column) + { + dataWriter.Write(value.Real); + } + } + + PadData(dataWriter, pad); data = dataMemoryStream.ToArray(); } @@ -436,7 +473,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataWriter = new BinaryWriter(dataMemoryStream)) { var nzmax = matrix.NonZerosCount; - WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); + WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, false, name, matrix.RowCount, matrix.ColumnCount, nzmax); // write ir dataWriter.Write((int)DataType.Int32); @@ -504,7 +541,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataWriter = new BinaryWriter(dataMemoryStream)) { var nzmax = matrix.NonZerosCount; - WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); + WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, false, name, matrix.RowCount, matrix.ColumnCount, nzmax); // write ir dataWriter.Write((int)DataType.Int32); @@ -553,6 +590,9 @@ namespace MathNet.Numerics.LinearAlgebra.IO } } + var pad = (nzmax * 4) % 8; + PadData(dataWriter, pad); + data = dataMemoryStream.ToArray(); } @@ -572,7 +612,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataWriter = new BinaryWriter(dataMemoryStream)) { var nzmax = matrix.NonZerosCount; - WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); + WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, true, name, matrix.RowCount, matrix.ColumnCount, nzmax); // write ir dataWriter.Write((int)DataType.Int32); @@ -621,7 +661,17 @@ namespace MathNet.Numerics.LinearAlgebra.IO } } - throw new NotImplementedException(); + dataWriter.Write((int)DataType.Double); + dataWriter.Write(nzmax * 8); + + foreach (var column in matrix.ColumnEnumerator()) + { + foreach (var row in column.Value.GetIndexedEnumerator()) + { + dataWriter.Write(row.Value.Real); + } + } + data = dataMemoryStream.ToArray(); } @@ -641,7 +691,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO using (var dataWriter = new BinaryWriter(dataMemoryStream)) { var nzmax = matrix.NonZerosCount; - WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); + WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, true, name, matrix.RowCount, matrix.ColumnCount, nzmax); // write ir dataWriter.Write((int)DataType.Int32); @@ -690,7 +740,22 @@ namespace MathNet.Numerics.LinearAlgebra.IO } } - throw new NotImplementedException(); + var pad = (nzmax * 4) % 8; + PadData(dataWriter, pad); + + dataWriter.Write((int)DataType.Single); + dataWriter.Write(nzmax * 4); + + foreach (var column in matrix.ColumnEnumerator()) + { + foreach (var row in column.Value.GetIndexedEnumerator()) + { + dataWriter.Write(row.Value.Real); + } + } + + PadData(dataWriter, pad); + data = dataMemoryStream.ToArray(); } diff --git a/src/UnitTests/LinearAlgebraTests/Double/IO/MatlabWriterTests.cs b/src/UnitTests/LinearAlgebraTests/Double/IO/MatlabWriterTests.cs index 17e96758..f5f4bb7f 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/IO/MatlabWriterTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/IO/MatlabWriterTests.cs @@ -42,28 +42,28 @@ [Test] public void WriteMatricesTest() { - Matrix mat1 = new DenseMatrix(5, 4); + Matrix mat1 = new DenseMatrix(5, 3); for (var i = 0; i < mat1.ColumnCount; i++) { - mat1[i, i] = i + 1; + mat1[i, i] = i + .1; } Matrix mat2 = new DenseMatrix(4, 5); for (var i = 0; i < mat2.RowCount; i++) { - mat2[i, i] = i + 1; + mat2[i, i] = i + .1; } Matrix mat3 = new SparseMatrix(5, 4); for (var i = 0; i < mat3.ColumnCount; i++) { - mat3[i, i] = i + 1; + mat3[i, i] = i + .1; } - Matrix mat4 = new SparseMatrix(4, 5); + Matrix mat4 = new SparseMatrix(3, 5); for (var i = 0; i < mat4.RowCount; i++) { - mat4[i, i] = i + 1; + mat4[i, i] = i + .1; } var write = new[] { mat1, mat2, mat3, mat4 }; diff --git a/src/UnitTests/LinearAlgebraTests/Single/IO/MatlabWriterTests.cs b/src/UnitTests/LinearAlgebraTests/Single/IO/MatlabWriterTests.cs index db355e21..19cb0f84 100644 --- a/src/UnitTests/LinearAlgebraTests/Single/IO/MatlabWriterTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Single/IO/MatlabWriterTests.cs @@ -42,28 +42,28 @@ [Test] public void WriteMatricesTest() { - Matrix mat1 = new DenseMatrix(5, 4); + Matrix mat1 = new DenseMatrix(5, 3); for (var i = 0; i < mat1.ColumnCount; i++) { - mat1[i, i] = i + 1; + mat1[i, i] = i + .1f; } Matrix mat2 = new DenseMatrix(4, 5); for (var i = 0; i < mat2.RowCount; i++) { - mat2[i, i] = i + 1; + mat2[i, i] = i + .1f; } Matrix mat3 = new SparseMatrix(5, 4); for (var i = 0; i < mat3.ColumnCount; i++) { - mat3[i, i] = i + 1; + mat3[i, i] = i + .1f; } - Matrix mat4 = new SparseMatrix(4, 5); + Matrix mat4 = new SparseMatrix(3, 5); for (var i = 0; i < mat4.RowCount; i++) { - mat4[i, i] = i + 1; + mat4[i, i] = i + .1f; } var write = new[] { mat1, mat2, mat3, mat4 }; diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 58cfe4e1..8e512ca5 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -139,6 +139,7 @@ + @@ -184,6 +185,7 @@ +