diff --git a/src/Data/Matlab/Formatter.cs b/src/Data/Matlab/Formatter.cs index e1cfd0ac..b62637de 100644 --- a/src/Data/Matlab/Formatter.cs +++ b/src/Data/Matlab/Formatter.cs @@ -50,6 +50,54 @@ namespace MathNet.Numerics.Data.Matlab /// const string HeaderText = "MATLAB 5.0 MAT-file, Platform: .NET 4 - Math.NET Numerics, Created on: "; + /// + /// Small Block Size + /// + const int SmallBlockSize = 4; + + /// + /// Large Block Size + /// + const int LargeBlockSize = 8; + + /// + /// Writes all matrix blocks to a stream. + /// + internal static void FormatFile(Stream stream, IEnumerable matrices) + { + using (var buffer = new BufferedStream(stream)) + using (var writer = new BinaryWriter(buffer)) + { + // write header and subsystem data offset (116+8 bytes) + var header = Encoding.ASCII.GetBytes(HeaderText + DateTime.Now.ToString(Resources.MatlabDateHeaderFormat)); + writer.Write(header); + Pad(writer, 116 - header.Length + 8, 32); + + // write version (2 bytes) + writer.Write((short)0x100); + + // write little endian indicator (2 bytes) + writer.Write((byte)0x49); + writer.Write((byte)0x4D); + + foreach (var matrix in matrices) + { + // write data type + writer.Write((int)DataType.Compressed); + + // compress data + var compressedData = PackCompressedBlock(matrix.Data, DataType.Matrix); + + // write compressed data to file + writer.Write(compressedData.Length); + writer.Write(compressedData); + } + + writer.Flush(); + writer.Close(); + } + } + /// /// Format a matrix block byte array /// @@ -71,10 +119,36 @@ namespace MathNet.Numerics.Data.Matlab throw new ArgumentException(string.Format(Resources.NameCannotContainASpace, name), "name"); } - var typeT = typeof (T); - bool sparse = matrix.Storage.GetType().GetGenericTypeDefinition() == typeof (SparseCompressedRowMatrixStorage<>); - bool doublePrecision = typeT == typeof (double) || typeT == typeof (Complex); - bool complex = typeT == typeof (Complex) || typeT == typeof (Complex32); + var dataType = typeof(T); + bool doublePrecision = dataType == typeof(double) || dataType == typeof(Complex); + bool complex = dataType == typeof(Complex) || dataType == typeof(Complex32); + + bool sparse; + Type storageType = matrix.Storage.GetType().GetGenericTypeDefinition(); + if (storageType == typeof (DenseColumnMajorMatrixStorage<>)) + { + sparse = false; + } + else if (storageType == typeof (SparseCompressedRowMatrixStorage<>)) + { + sparse = true; + } + else if (storageType == typeof (DiagonalMatrixStorage<>)) + { + // convert diagonal matrices to sparse + sparse = true; + var sparseMatrix = Matrix.Build.Sparse(matrix.RowCount, matrix.ColumnCount); + matrix.CopyTo(sparseMatrix); + matrix = sparseMatrix; + } + else + { + // convert unknown matrices to dense + sparse = false; + var denseMatrix = Matrix.Build.Dense(matrix.RowCount, matrix.ColumnCount); + matrix.CopyTo(denseMatrix); + matrix = denseMatrix; + } int sparseNonZeroValues = 0; if (sparse) @@ -105,71 +179,19 @@ namespace MathNet.Numerics.Data.Matlab writer.Write(matrix.ColumnCount); // Array Name: + bool smallBlock; var nameBytes = Encoding.ASCII.GetBytes(name); - if (nameBytes.Length > 4) - { - // long format - writer.Write((int)DataType.Int8); - writer.Write(nameBytes.Length); - writer.Write(nameBytes); - PadData(writer, 8 - (nameBytes.Length%8)); - } - else - { - // small format - writer.Write((short)DataType.Int8); - writer.Write((short)nameBytes.Length); - writer.Write(nameBytes); - PadData(writer, 4 - nameBytes.Length); - } + WriteElementTag(writer, DataType.Int8, nameBytes.Length, out smallBlock); + writer.Write(nameBytes); + PadElement(writer, nameBytes.Length, smallBlock); - if (doublePrecision && !complex) + if (sparse) { - var sparseMatrix = matrix as LinearAlgebra.Double.SparseMatrix; - if (sparseMatrix != null) - { - SparseArrayFormatter.Write(writer, sparseMatrix); - } - else - { - NumericArrayFormatter.Write(writer, (LinearAlgebra.Double.Matrix)(object)matrix); - } - } - else if (!doublePrecision && !complex) - { - var sparseMatrix = matrix as LinearAlgebra.Single.SparseMatrix; - if (sparseMatrix != null) - { - SparseArrayFormatter.Write(writer, sparseMatrix); - } - else - { - NumericArrayFormatter.Write(writer, (LinearAlgebra.Single.Matrix)(object)matrix); - } - } - else if (doublePrecision) - { - var sparseMatrix = matrix as LinearAlgebra.Complex.SparseMatrix; - if (sparseMatrix != null) - { - SparseArrayFormatter.Write(writer, sparseMatrix); - } - else - { - NumericArrayFormatter.Write(writer, (LinearAlgebra.Complex.Matrix)(object)matrix); - } + WriteSparseMatrix(writer, matrix, complex, doublePrecision); } else { - var sparseMatrix = matrix as LinearAlgebra.Complex32.SparseMatrix; - if (sparseMatrix != null) - { - SparseArrayFormatter.Write(writer, sparseMatrix); - } - else - { - NumericArrayFormatter.Write(writer, (LinearAlgebra.Complex32.Matrix)(object)matrix); - } + WriteDenseMatrix(writer, matrix, complex, doublePrecision); } writer.Flush(); @@ -177,55 +199,177 @@ namespace MathNet.Numerics.Data.Matlab } } - /// - /// Writes all matrix blocks to a stream. - /// - internal static void FormatFile(Stream stream, IEnumerable matrices) + static void WriteDenseMatrix(BinaryWriter writer, Matrix matrix, bool complex, bool doublePrecision) + where T : struct, IEquatable, IFormattable { - using (var buffer = new BufferedStream(stream)) - using (var writer = new BinaryWriter(buffer)) + int count = matrix.RowCount*matrix.ColumnCount; + + bool smallBlock; + int size = doublePrecision ? count*8 : count*4; + WriteElementTag(writer, doublePrecision ? DataType.Double : DataType.Single, size, out smallBlock); + + var data = ((DenseColumnMajorMatrixStorage)matrix.Storage).Data; + + if (doublePrecision && !complex) { - // write header and subsystem data offset (all space) - var header = Encoding.ASCII.GetBytes(HeaderText + DateTime.Now.ToString(Resources.MatlabDateHeaderFormat)); - writer.Write(header); - PadData(writer, 116 - header.Length + 8, 32); + WriteDoubleArray(writer, (double[])(object)data, data.Length); + } + else if (!doublePrecision && !complex) + { + WriteSingleArray(writer, (float[])(object)data, data.Length); + } + else if (doublePrecision) + { + WriteComplexArray(writer, (Complex[])(object)data, data.Length, size, ref smallBlock); + } + else + { + WriteComplex32Array(writer, (Complex32[])(object)data, data.Length, size, ref smallBlock); + } - // write version - writer.Write((short)0x100); + PadElement(writer, size, smallBlock); + } - // write little endian indicator - writer.Write((byte)0x49); - writer.Write((byte)0x4D); + static void WriteSparseMatrix(BinaryWriter writer, Matrix matrix, bool complex, bool doublePrecision) + where T : struct, IEquatable, IFormattable + { + var transposed = matrix.Transpose(); + var storage = ((SparseCompressedRowMatrixStorage)transposed.Storage); - foreach (var matrix in matrices) - { - // write data type - writer.Write((int)DataType.Compressed); + bool smallBlock; + int nzcount = storage.ValueCount; - // compress data - var compressedData = PackCompressedBlock(matrix.Data, DataType.Matrix); + // row data array + var ir = storage.ColumnIndices; + WriteElementTag(writer, DataType.Int32, nzcount*4, out smallBlock); + for (var i = 0; i < nzcount; i++) + { + writer.Write(ir[i]); + } - // write compressed data to file - writer.Write(compressedData.Length); - writer.Write(compressedData); - } + PadElement(writer, nzcount*4, smallBlock); - writer.Flush(); - writer.Close(); + // column data array + var jc = storage.RowPointers; + WriteElementTag(writer, DataType.Int32, jc.Length*4, out smallBlock); + for (var i = 0; i < jc.Length; i++) + { + writer.Write(jc[i]); } + + PadElement(writer, jc.Length*4, smallBlock); + + // values + int size = doublePrecision ? nzcount*8 : nzcount*4; + WriteElementTag(writer, doublePrecision ? DataType.Double : DataType.Single, size, out smallBlock); + + if (doublePrecision && !complex) + { + WriteDoubleArray(writer, (double[])(object)storage.Values, nzcount); + } + else if (!doublePrecision && !complex) + { + WriteSingleArray(writer, (float[])(object)storage.Values, nzcount); + } + else if (doublePrecision) + { + WriteComplexArray(writer, (Complex[])(object)storage.Values, nzcount, size, ref smallBlock); + } + else + { + WriteComplex32Array(writer, (Complex32[])(object)storage.Values, nzcount, size, ref smallBlock); + } + + PadElement(writer, size, smallBlock); } - /// - /// Pads the data with the given byte. - /// - /// Where to write the pad values. - /// The number of bytes to pad. - /// What value to pad with. - static void PadData(BinaryWriter writer, int bytes, byte pad = (byte)0) + static void WriteDoubleArray(BinaryWriter writer, double[] data, int count) + { + for (int i = 0; i < count; i++) + { + writer.Write(data[i]); + } + } + + static void WriteSingleArray(BinaryWriter writer, float[] data, int count) + { + for (int i = 0; i < count; i++) + { + writer.Write(data[i]); + } + } + + static void WriteComplexArray(BinaryWriter writer, Complex[] data, int count, int size, ref bool smallBlock) + { + for (int i = 0; i < count; i++) + { + writer.Write(data[i].Real); + } + + PadElement(writer, size, smallBlock); + WriteElementTag(writer, DataType.Double, size, out smallBlock); + + for (int i = 0; i < count; i++) + { + writer.Write(data[i].Imaginary); + } + } + + static void WriteComplex32Array(BinaryWriter writer, Complex32[] data, int count, int size, ref bool smallBlock) + { + for (int i = 0; i < count; i++) + { + writer.Write(data[i].Real); + } + + PadElement(writer, size, smallBlock); + WriteElementTag(writer, DataType.Single, size, out smallBlock); + + for (int i = 0; i < count; i++) + { + writer.Write(data[i].Imaginary); + } + } + + static void WriteElementTag(BinaryWriter writer, DataType dataType, int size, out bool smallBlock) + { + if (size > 4) + { + // long format + smallBlock = false; + writer.Write((int)dataType); + writer.Write(size); + } + else + { + // small format + smallBlock = true; + writer.Write((short)dataType); + writer.Write((short)size); + } + } + + static void PadElement(BinaryWriter writer, int size, bool smallBlock, byte padValue = (byte)0) + { + var blockSize = smallBlock ? SmallBlockSize : LargeBlockSize; + var offset = 0; + var mod = size%blockSize; + if (mod != 0) + { + offset = blockSize - mod; + } + + for (var i = 0; i < offset; i++) + { + writer.Write(padValue); + } + } + + static void Pad(BinaryWriter writer, int count, byte padValue = (byte)0) { - for (var i = 0; i < bytes; i++) + for (var i = 0; i < count; i++) { - writer.Write(pad); + writer.Write(padValue); } } diff --git a/src/Data/Matlab/Matlab.csproj b/src/Data/Matlab/Matlab.csproj index df786a5c..234f9a7d 100644 --- a/src/Data/Matlab/Matlab.csproj +++ b/src/Data/Matlab/Matlab.csproj @@ -53,13 +53,11 @@ - - diff --git a/src/Data/Matlab/NumericArrayFormatter.cs b/src/Data/Matlab/NumericArrayFormatter.cs deleted file mode 100644 index 143e8f21..00000000 --- a/src/Data/Matlab/NumericArrayFormatter.cs +++ /dev/null @@ -1,150 +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-2014 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.IO; -using System.Numerics; -using MathNet.Numerics.LinearAlgebra; - -namespace MathNet.Numerics.Data.Matlab -{ - internal static class NumericArrayFormatter - { - internal static void Write(BinaryWriter writer, Matrix matrix) - { - // write data - writer.Write((int)DataType.Double); - writer.Write(matrix.RowCount*matrix.ColumnCount*8); - - for (var j = 0; j < matrix.ColumnCount; j++) - { - var column = matrix.Column(j); - foreach (var value in column) - { - writer.Write(value); - } - } - } - - internal static void Write(BinaryWriter writer, Matrix matrix) - { - // write data - int size = matrix.RowCount*matrix.ColumnCount*4; - writer.Write((int)DataType.Single); - writer.Write(size); - - for (var j = 0; j < matrix.ColumnCount; j++) - { - var column = matrix.Column(j); - foreach (var value in column) - { - writer.Write(value); - } - } - - PadData(writer, size%8); - } - - internal static void Write(BinaryWriter writer, Matrix matrix) - { - // write data - int size = matrix.RowCount*matrix.ColumnCount*8; - writer.Write((int)DataType.Double); - writer.Write(size); - - for (var j = 0; j < matrix.ColumnCount; j++) - { - var column = matrix.Column(j); - foreach (var value in column) - { - writer.Write(value.Real); - } - } - - writer.Write((int)DataType.Double); - writer.Write(size); - - for (var j = 0; j < matrix.ColumnCount; j++) - { - var column = matrix.Column(j); - foreach (var value in column) - { - writer.Write(value.Imaginary); - } - } - } - - internal static void Write(BinaryWriter writer, Matrix matrix) - { - // write data - int size = matrix.RowCount*matrix.ColumnCount*4; - writer.Write((int)DataType.Single); - writer.Write(size); - - for (var j = 0; j < matrix.ColumnCount; j++) - { - var column = matrix.Column(j); - foreach (var value in column) - { - writer.Write(value.Real); - } - } - - PadData(writer, size%8); - - writer.Write((int)DataType.Single); - writer.Write(size); - - for (var j = 0; j < matrix.ColumnCount; j++) - { - var column = matrix.Column(j); - foreach (var value in column) - { - writer.Write(value.Real); - } - } - - PadData(writer, size%8); - } - - /// - /// Pads the data with the given byte. - /// - /// Where to write the pad values. - /// The number of bytes to pad. - /// What value to pad with. - static void PadData(BinaryWriter writer, int bytes, byte pad = (byte)0) - { - for (var i = 0; i < bytes; i++) - { - writer.Write(pad); - } - } - } -} diff --git a/src/Data/Matlab/Parser.cs b/src/Data/Matlab/Parser.cs index 8bdf9d31..909f4dba 100644 --- a/src/Data/Matlab/Parser.cs +++ b/src/Data/Matlab/Parser.cs @@ -106,7 +106,7 @@ namespace MathNet.Numerics.Data.Matlab { data = new byte[size]; reader.Read(data, 0, size); - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); } if (type == DataType.Matrix) @@ -175,14 +175,13 @@ namespace MathNet.Numerics.Data.Matlab bool smallBlock; ReadElementTag(reader, out type, out size, out smallBlock); reader.BaseStream.Seek(size, SeekOrigin.Current); - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); - Matrix matrix; + // Data switch (arrayClass) { case ArrayClass.Sparse: - matrix = PopulateSparseMatrix(reader, complex, rows, columns); - break; + return PopulateSparseMatrix(reader, complex, rows, columns); case ArrayClass.Function: case ArrayClass.Character: case ArrayClass.Object: @@ -191,11 +190,8 @@ namespace MathNet.Numerics.Data.Matlab case ArrayClass.Unknown: throw new NotSupportedException(); default: - matrix = PopulateDenseMatrix(reader, complex, rows, columns); - break; + return PopulateDenseMatrix(reader, complex, rows, columns); } - - return matrix; } } @@ -257,7 +253,7 @@ namespace MathNet.Numerics.Data.Matlab throw new NotSupportedException(); } - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); return Matrix.Build.Dense(rows, columns, data); } @@ -290,7 +286,7 @@ namespace MathNet.Numerics.Data.Matlab ir[i] = reader.ReadInt32(); } - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); // populate the column data array ReadElementTag(reader, out type, out size, out smallBlock); @@ -305,7 +301,7 @@ namespace MathNet.Numerics.Data.Matlab jc[j] = reader.ReadInt32(); } - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); // populate the values ReadElementTag(reader, out type, out size, out smallBlock); @@ -343,7 +339,7 @@ namespace MathNet.Numerics.Data.Matlab throw new NotSupportedException(); } - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); return matrix.Transpose(); } @@ -381,7 +377,7 @@ namespace MathNet.Numerics.Data.Matlab if (complex) { - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); ReadElementTag(reader, out type, out size, out smallBlock); for (int i = 0; i < data.Length; i++) @@ -403,7 +399,7 @@ namespace MathNet.Numerics.Data.Matlab if (complex) { - SkipElementPadding(reader.BaseStream, size, smallBlock); + SkipElementPadding(reader, size, smallBlock); ReadElementTag(reader, out type, out size, out smallBlock); for (int i = 0; i < data.Length; i++) @@ -463,7 +459,7 @@ namespace MathNet.Numerics.Data.Matlab } } - static void SkipElementPadding(Stream stream, int size, bool smallBlock) + static void SkipElementPadding(BinaryReader reader, int size, bool smallBlock) { var blockSize = smallBlock ? SmallBlockSize : LargeBlockSize; var offset = 0; @@ -473,7 +469,7 @@ namespace MathNet.Numerics.Data.Matlab offset = blockSize - mod; } - stream.Seek(offset, SeekOrigin.Current); + reader.BaseStream.Seek(offset, SeekOrigin.Current); } /// diff --git a/src/Data/Matlab/SparseArrayFormatter.cs b/src/Data/Matlab/SparseArrayFormatter.cs deleted file mode 100644 index b836081c..00000000 --- a/src/Data/Matlab/SparseArrayFormatter.cs +++ /dev/null @@ -1,301 +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-2014 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.IO; -using System.Numerics; -using MathNet.Numerics.LinearAlgebra.Storage; - -namespace MathNet.Numerics.Data.Matlab -{ - internal static class SparseArrayFormatter - { - //public static void FormatSparseMatrix(BinaryWriter writer, Matrix matrix, string name, bool isComplex, int rows, int columns, int size) - // where T : struct, IEquatable, IFormattable - //{ - // var transposed = matrix.Transpose(); - // var storage = (SparseCompressedRowMatrixStorage)transposed.Storage; - - // WriteMatrixTagAndName(writer, ArrayClass.Sparse, isComplex, name, storage); - //} - - - internal static void Write(BinaryWriter writer, LinearAlgebra.Double.SparseMatrix matrix) - { - var nzmax = matrix.NonZerosCount; - - // write ir - writer.Write((int)DataType.Int32); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item1); - } - } - - // add pad if needed - if (nzmax%2 == 1) - { - writer.Write(0); - } - - // write jc - writer.Write((int)DataType.Int32); - writer.Write((matrix.ColumnCount + 1)*4); - writer.Write(0); - var count = 0; - foreach (var column in matrix.EnumerateColumns()) - { - count += ((SparseVectorStorage)column.Storage).ValueCount; - writer.Write(count); - } - - // add pad if needed - if (matrix.ColumnCount%2 == 0) - { - writer.Write(0); - } - - // write data - writer.Write((int)DataType.Double); - writer.Write(nzmax*8); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item2); - } - } - } - - internal static void Write(BinaryWriter writer, LinearAlgebra.Single.SparseMatrix matrix) - { - var nzmax = matrix.NonZerosCount; - - // write ir - writer.Write((int)DataType.Int32); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item1); - } - } - - // add pad if needed - if (nzmax%2 == 1) - { - writer.Write(0); - } - - // write jc - writer.Write((int)DataType.Int32); - writer.Write((matrix.ColumnCount + 1)*4); - writer.Write(0); - var count = 0; - foreach (var column in matrix.EnumerateColumns()) - { - count += ((SparseVectorStorage)column.Storage).ValueCount; - writer.Write(count); - } - - // add pad if needed - if (matrix.ColumnCount%2 == 0) - { - writer.Write(0); - } - - // write data - writer.Write((int)DataType.Single); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item2); - } - } - - var pad = nzmax*4%8; - PadData(writer, pad); - } - - internal static void Write(BinaryWriter writer, LinearAlgebra.Complex.SparseMatrix matrix) - { - var nzmax = matrix.NonZerosCount; - - // write ir - writer.Write((int)DataType.Int32); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item1); - } - } - - // add pad if needed - if (nzmax%2 == 1) - { - writer.Write(0); - } - - // write jc - writer.Write((int)DataType.Int32); - writer.Write((matrix.ColumnCount + 1)*4); - writer.Write(0); - var count = 0; - foreach (var column in matrix.EnumerateColumns()) - { - count += ((SparseVectorStorage)column.Storage).ValueCount; - writer.Write(count); - } - - // add pad if needed - if (matrix.ColumnCount%2 == 0) - { - writer.Write(0); - } - - // write data - writer.Write((int)DataType.Double); - writer.Write(nzmax*8); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item2.Real); - } - } - - writer.Write((int)DataType.Double); - writer.Write(nzmax*8); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item2.Imaginary); - } - } - } - - internal static void Write(BinaryWriter writer, LinearAlgebra.Complex32.SparseMatrix matrix) - { - var nzmax = matrix.NonZerosCount; - - // write ir - writer.Write((int)DataType.Int32); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item1); - } - } - - // add pad if needed - if (nzmax%2 == 1) - { - writer.Write(0); - } - - // write jc - writer.Write((int)DataType.Int32); - writer.Write((matrix.ColumnCount + 1)*4); - writer.Write(0); - var count = 0; - foreach (var column in matrix.EnumerateColumns()) - { - count += ((SparseVectorStorage)column.Storage).ValueCount; - writer.Write(count); - } - - // add pad if needed - if (matrix.ColumnCount%2 == 0) - { - writer.Write(0); - } - - // write data - writer.Write((int)DataType.Single); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item2.Real); - } - } - - var pad = nzmax*4%8; - PadData(writer, pad); - - writer.Write((int)DataType.Single); - writer.Write(nzmax*4); - - foreach (var column in matrix.EnumerateColumns()) - { - foreach (var row in column.EnumerateNonZeroIndexed()) - { - writer.Write(row.Item2.Imaginary); - } - } - - PadData(writer, pad); - } - - /// - /// Pads the data with the given byte. - /// - /// Where to write the pad values. - /// The number of bytes to pad. - /// What value to pad with. - static void PadData(BinaryWriter writer, int bytes, byte pad = (byte)0) - { - for (var i = 0; i < bytes; i++) - { - writer.Write(pad); - } - } - } -}