Browse Source

Data: Matlab: adapt parsing changes to formatting side as well

provider
Christoph Ruegg 12 years ago
parent
commit
b908592109
  1. 342
      src/Data/Matlab/Formatter.cs
  2. 2
      src/Data/Matlab/Matlab.csproj
  3. 150
      src/Data/Matlab/NumericArrayFormatter.cs
  4. 30
      src/Data/Matlab/Parser.cs
  5. 301
      src/Data/Matlab/SparseArrayFormatter.cs

342
src/Data/Matlab/Formatter.cs

@ -50,6 +50,54 @@ namespace MathNet.Numerics.Data.Matlab
/// </summary>
const string HeaderText = "MATLAB 5.0 MAT-file, Platform: .NET 4 - Math.NET Numerics, Created on: ";
/// <summary>
/// Small Block Size
/// </summary>
const int SmallBlockSize = 4;
/// <summary>
/// Large Block Size
/// </summary>
const int LargeBlockSize = 8;
/// <summary>
/// Writes all matrix blocks to a stream.
/// </summary>
internal static void FormatFile(Stream stream, IEnumerable<MatlabMatrix> 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();
}
}
/// <summary>
/// Format a matrix block byte array
/// </summary>
@ -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<T>.Build.Sparse(matrix.RowCount, matrix.ColumnCount);
matrix.CopyTo(sparseMatrix);
matrix = sparseMatrix;
}
else
{
// convert unknown matrices to dense
sparse = false;
var denseMatrix = Matrix<T>.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
}
}
/// <summary>
/// Writes all matrix blocks to a stream.
/// </summary>
internal static void FormatFile(Stream stream, IEnumerable<MatlabMatrix> matrices)
static void WriteDenseMatrix<T>(BinaryWriter writer, Matrix<T> matrix, bool complex, bool doublePrecision)
where T : struct, IEquatable<T>, 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<T>)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<T>(BinaryWriter writer, Matrix<T> matrix, bool complex, bool doublePrecision)
where T : struct, IEquatable<T>, IFormattable
{
var transposed = matrix.Transpose();
var storage = ((SparseCompressedRowMatrixStorage<T>)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);
}
/// <summary>
/// Pads the data with the given byte.
/// </summary>
/// <param name="writer">Where to write the pad values.</param>
/// <param name="bytes">The number of bytes to pad.</param>
/// <param name="pad">What value to pad with.</param>
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);
}
}

2
src/Data/Matlab/Matlab.csproj

@ -53,13 +53,11 @@
<Compile Include="ArrayFlags.cs" />
<Compile Include="MatlabMatrix.cs" />
<Compile Include="Formatter.cs" />
<Compile Include="NumericArrayFormatter.cs" />
<Compile Include="DataType.cs" />
<Compile Include="Parser.cs" />
<Compile Include="MatlabReader.cs" />
<Compile Include="MatlabWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SparseArrayFormatter.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

150
src/Data/Matlab/NumericArrayFormatter.cs

@ -1,150 +0,0 @@
// <copyright file="NumericArrayFormatter.cs" company="Math.NET">
// 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.
// </copyright>
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<double> 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<float> 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<Complex> 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<Complex32> 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);
}
/// <summary>
/// Pads the data with the given byte.
/// </summary>
/// <param name="writer">Where to write the pad values.</param>
/// <param name="bytes">The number of bytes to pad.</param>
/// <param name="pad">What value to pad with.</param>
static void PadData(BinaryWriter writer, int bytes, byte pad = (byte)0)
{
for (var i = 0; i < bytes; i++)
{
writer.Write(pad);
}
}
}
}

30
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<T> matrix;
// Data
switch (arrayClass)
{
case ArrayClass.Sparse:
matrix = PopulateSparseMatrix<T>(reader, complex, rows, columns);
break;
return PopulateSparseMatrix<T>(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<T>(reader, complex, rows, columns);
break;
return PopulateDenseMatrix<T>(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<T>.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);
}
/// <summary>

301
src/Data/Matlab/SparseArrayFormatter.cs

@ -1,301 +0,0 @@
// <copyright file="SparseArrayFormatter.cs" company="Math.NET">
// 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.
// </copyright>
using System.IO;
using System.Numerics;
using MathNet.Numerics.LinearAlgebra.Storage;
namespace MathNet.Numerics.Data.Matlab
{
internal static class SparseArrayFormatter
{
//public static void FormatSparseMatrix<T>(BinaryWriter writer, Matrix<T> matrix, string name, bool isComplex, int rows, int columns, int size)
// where T : struct, IEquatable<T>, IFormattable
//{
// var transposed = matrix.Transpose();
// var storage = (SparseCompressedRowMatrixStorage<T>)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<double>)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<float>)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<Complex>)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<Complex32>)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);
}
/// <summary>
/// Pads the data with the given byte.
/// </summary>
/// <param name="writer">Where to write the pad values.</param>
/// <param name="bytes">The number of bytes to pad.</param>
/// <param name="pad">What value to pad with.</param>
static void PadData(BinaryWriter writer, int bytes, byte pad = (byte)0)
{
for (var i = 0; i < bytes; i++)
{
writer.Write(pad);
}
}
}
}
Loading…
Cancel
Save