forked from tsai/mathnet-numerics
17 changed files with 1146 additions and 54 deletions
@ -0,0 +1,752 @@ |
|||
// <copyright file="MatlabWriter.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-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.
|
|||
// </copyright>
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Text; |
|||
using zlib; |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.IO |
|||
{ |
|||
using Generic; |
|||
using Matlab; |
|||
using Properties; |
|||
|
|||
/// <summary>
|
|||
/// Writes matrices to a Matlab file.
|
|||
/// </summary>
|
|||
public class MatlabMatrixWriter : IDisposable |
|||
{ |
|||
/// <summary>
|
|||
/// The file header value
|
|||
/// </summary>
|
|||
private const string HeaderText = "MATLAB 5.0 MAT-file, Platform: .NET 4 - Math.NET Numerics, Created on: "; |
|||
|
|||
/// <summary>
|
|||
/// The length of the header text.
|
|||
/// </summary>
|
|||
private const int HeaderTextLength = 116; |
|||
|
|||
/// <summary>
|
|||
/// Have we written the header yet.
|
|||
/// </summary>
|
|||
private bool _headerWritten; |
|||
|
|||
/// <summary>
|
|||
/// The binary writer to write to.
|
|||
/// </summary>
|
|||
private BinaryWriter _writer; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="MatlabMatrixWriter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="filename">The name of the Matlab file to save the matrices to.</param>
|
|||
public MatlabMatrixWriter(string filename) |
|||
{ |
|||
if (string.IsNullOrEmpty(filename)) |
|||
{ |
|||
throw new ArgumentException(Resources.StringNullOrEmpty, "filename"); |
|||
} |
|||
|
|||
_writer = new BinaryWriter(new BufferedStream(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
|||
/// </summary>
|
|||
public void Dispose() |
|||
{ |
|||
if (_writer != null) |
|||
{ |
|||
_writer.Flush(); |
|||
_writer.Close(); |
|||
_writer = null; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Writes the given <see cref="Matrix{T}"/> to the file.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to write.</param>
|
|||
/// <param name="name">The name of the matrix to store in the file.</param>
|
|||
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="name"/> is <c>null</c>.</exception>
|
|||
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
|
|||
public void WriteMatrix<TDataType>(Matrix<TDataType> matrix, string name) where TDataType : struct, IEquatable<TDataType>, IFormattable |
|||
{ |
|||
if (matrix == null) |
|||
{ |
|||
throw new ArgumentNullException("matrix"); |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(name)) |
|||
{ |
|||
throw new ArgumentException(Resources.StringNullOrEmpty, "name"); |
|||
} |
|||
|
|||
if (name.IndexOf(' ') > -1) |
|||
{ |
|||
throw new ArgumentException(string.Format(Resources.NameCannotContainASpace, name), "name"); |
|||
} |
|||
|
|||
if (!_headerWritten) |
|||
{ |
|||
WriteHeader(); |
|||
_headerWritten = true; |
|||
} |
|||
|
|||
// write datatype
|
|||
_writer.Write((int)DataType.Compressed); |
|||
|
|||
byte[] data = null; |
|||
|
|||
if (typeof(TDataType) == typeof(double)) |
|||
{ |
|||
if (matrix is Double.SparseMatrix) |
|||
{ |
|||
data = GetSparseDataArray((Double.SparseMatrix)(object)matrix, name); |
|||
} |
|||
else |
|||
{ |
|||
data = GetDenseDataArray((Double.Matrix)(object)matrix, name); |
|||
} |
|||
} |
|||
else if (typeof(TDataType) == typeof(float)) |
|||
{ |
|||
if (matrix is Single.SparseMatrix) |
|||
{ |
|||
data = GetSparseDataArray((Single.SparseMatrix)(object)matrix, name); |
|||
} |
|||
else |
|||
{ |
|||
data = GetDenseDataArray((Single.Matrix)(object)matrix, name); |
|||
} |
|||
} |
|||
else if (typeof(TDataType) == typeof(System.Numerics.Complex)) |
|||
{ |
|||
if (matrix is Complex.SparseMatrix) |
|||
{ |
|||
data = GetSparseDataArray((Complex.SparseMatrix)(object)matrix, name); |
|||
} |
|||
else |
|||
{ |
|||
data = GetDenseDataArray((Complex.Matrix)(object)matrix, name); |
|||
} |
|||
} |
|||
else if (typeof(TDataType) == typeof(Numerics.Complex32)) |
|||
{ |
|||
if (matrix is Complex32.SparseMatrix) |
|||
{ |
|||
data = GetSparseDataArray((Complex32.SparseMatrix)(object)matrix, name); |
|||
} |
|||
else |
|||
{ |
|||
data = GetDenseDataArray((Complex32.Matrix)(object)matrix, name); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
WriteCompressedData(data); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Writes the given <see cref="Matrix{TDataType}"/> to the file.
|
|||
/// </summary>
|
|||
/// <param name="matrices">The matrices to write.</param>
|
|||
/// <param name="names">The names of the matrices to store in the file.</param>
|
|||
/// <exception cref="ArgumentNullException">If either <paramref name="matrices"/> or <paramref name="names"/> is null.</exception>
|
|||
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
|
|||
public void WriteMatrices<TDataType>(IList<Matrix<TDataType>> matrices, IList<string> names) where TDataType : struct, IEquatable<TDataType>, IFormattable |
|||
{ |
|||
if (matrices == null) |
|||
{ |
|||
throw new ArgumentNullException("matrices"); |
|||
} |
|||
|
|||
if (names == null) |
|||
{ |
|||
throw new ArgumentNullException("names"); |
|||
} |
|||
|
|||
if (matrices.Count != names.Count) |
|||
{ |
|||
throw new ArgumentException(Resources.ArgumentMatrixDimensions); |
|||
} |
|||
|
|||
for (int i = 0; i < matrices.Count; i++) |
|||
{ |
|||
WriteMatrix(matrices[i], names[i]); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Closes the stream the being written to.
|
|||
/// </summary>
|
|||
/// <remarks>Calls <see cref="IDisposable.Dispose"/>.</remarks>
|
|||
public void Close() |
|||
{ |
|||
Dispose(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Writes the matrix tag and name.
|
|||
/// </summary>
|
|||
/// <param name="writer">The writer we are using.</param>
|
|||
/// <param name="arrayClass">The array class we are writing.</param>
|
|||
/// <param name="name">The name name of the matrix.</param>
|
|||
/// <param name="rows">The number of rows.</param>
|
|||
/// <param name="columns">The columns of columns.</param>
|
|||
/// <param name="nzmax">The maximum number of non-zero elements.</param>
|
|||
private static void WriteMatrixTagAndName(BinaryWriter writer, ArrayClass arrayClass, string name, int rows, int columns, int nzmax) |
|||
{ |
|||
writer.Write((int)DataType.Matrix); |
|||
|
|||
// add place holder for data size
|
|||
writer.Write(0); |
|||
|
|||
// write flag, data type and size
|
|||
writer.Write((int)DataType.UInt32); |
|||
writer.Write(8); |
|||
|
|||
// write array class and flags
|
|||
writer.Write((byte)arrayClass); |
|||
writer.Write((byte)0); |
|||
|
|||
writer.Write((short)0); |
|||
writer.Write(nzmax); |
|||
|
|||
// write dimensions
|
|||
writer.Write((int)DataType.Int32); |
|||
writer.Write(8); |
|||
writer.Write(rows); |
|||
writer.Write(columns); |
|||
|
|||
byte[] nameBytes = Encoding.ASCII.GetBytes(name); |
|||
|
|||
// write name
|
|||
if (nameBytes.Length > 4) |
|||
{ |
|||
writer.Write((int)DataType.Int8); |
|||
writer.Write(nameBytes.Length); |
|||
writer.Write(nameBytes); |
|||
int pad = 8 - (nameBytes.Length % 8); |
|||
PadData(writer, pad); |
|||
} |
|||
else |
|||
{ |
|||
writer.Write((short)DataType.Int8); |
|||
writer.Write((short)nameBytes.Length); |
|||
writer.Write(nameBytes); |
|||
PadData(writer, 4 - nameBytes.Length); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compresses the data array.
|
|||
/// </summary>
|
|||
/// <param name="data">The data to compress.</param>
|
|||
/// <returns>The compressed data.</returns>
|
|||
private static byte[] CompressData(byte[] data) |
|||
{ |
|||
using (var compressedStream = new MemoryStream()) |
|||
{ |
|||
using (var outputStream = new ZOutputStream(compressedStream, zlibConst.Z_DEFAULT_COMPRESSION)) |
|||
{ |
|||
outputStream.Write(data, 0, data.Length); |
|||
} |
|||
|
|||
return compressedStream.ToArray(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the dense data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetDenseDataArray(Matrix<double> matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Double, name, matrix.RowCount, matrix.ColumnCount, 0); |
|||
|
|||
// write data
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the dense data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetDenseDataArray(Matrix<float> matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Single, 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++) |
|||
{ |
|||
var column = matrix.Column(j); |
|||
foreach (var value in column) |
|||
{ |
|||
dataWriter.Write(value); |
|||
} |
|||
} |
|||
|
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the dense data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetDenseDataArray(Matrix<System.Numerics.Complex> matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Double, name, matrix.RowCount, matrix.ColumnCount, 0); |
|||
|
|||
// write data
|
|||
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.Real); |
|||
} |
|||
} |
|||
|
|||
throw new NotImplementedException(); |
|||
|
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the dense data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetDenseDataArray(Matrix<Numerics.Complex32> matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Single, 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++) |
|||
{ |
|||
var column = matrix.Column(j); |
|||
foreach (var value in column) |
|||
{ |
|||
dataWriter.Write(value.Real); |
|||
} |
|||
} |
|||
|
|||
throw new NotImplementedException(); |
|||
|
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the sparse data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetSparseDataArray(Double.SparseMatrix matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
var nzmax = matrix.NonZerosCount; |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); |
|||
|
|||
// write ir
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write(nzmax * 4); |
|||
|
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
foreach (var row in column.Value.GetIndexedEnumerator()) |
|||
{ |
|||
dataWriter.Write(row.Key); |
|||
} |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (nzmax % 2 == 1) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write jc
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write((matrix.ColumnCount + 1) * 4); |
|||
dataWriter.Write(0); |
|||
int count = 0; |
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
count += ((Double.SparseVector)column.Value).NonZerosCount; |
|||
dataWriter.Write(count); |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (matrix.ColumnCount % 2 == 0) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write data
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the sparse data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetSparseDataArray(Single.SparseMatrix matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
var nzmax = matrix.NonZerosCount; |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); |
|||
|
|||
// write ir
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write(nzmax * 4); |
|||
|
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
foreach (var row in column.Value.GetIndexedEnumerator()) |
|||
{ |
|||
dataWriter.Write(row.Key); |
|||
} |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (nzmax % 2 == 1) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write jc
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write((matrix.ColumnCount + 1) * 4); |
|||
dataWriter.Write(0); |
|||
int count = 0; |
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
count += ((Single.SparseVector)column.Value).NonZerosCount; |
|||
dataWriter.Write(count); |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (matrix.ColumnCount % 2 == 0) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write data
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the sparse data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetSparseDataArray(Complex.SparseMatrix matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
var nzmax = matrix.NonZerosCount; |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); |
|||
|
|||
// write ir
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write(nzmax * 4); |
|||
|
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
foreach (var row in column.Value.GetIndexedEnumerator()) |
|||
{ |
|||
dataWriter.Write(row.Key); |
|||
} |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (nzmax % 2 == 1) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write jc
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write((matrix.ColumnCount + 1) * 4); |
|||
dataWriter.Write(0); |
|||
int count = 0; |
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
count += ((Complex.SparseVector)column.Value).NonZerosCount; |
|||
dataWriter.Write(count); |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (matrix.ColumnCount % 2 == 0) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write data
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
throw new NotImplementedException(); |
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the sparse data array.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix to get the data from.</param>
|
|||
/// <param name="name">The name of the matrix.</param>
|
|||
/// <returns>The matrix data as an array.</returns>
|
|||
private static byte[] GetSparseDataArray(Complex32.SparseMatrix matrix, string name) |
|||
{ |
|||
byte[] data; |
|||
using (var dataMemoryStream = new MemoryStream()) |
|||
using (var dataWriter = new BinaryWriter(dataMemoryStream)) |
|||
{ |
|||
var nzmax = matrix.NonZerosCount; |
|||
WriteMatrixTagAndName(dataWriter, ArrayClass.Sparse, name, matrix.RowCount, matrix.ColumnCount, nzmax); |
|||
|
|||
// write ir
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write(nzmax * 4); |
|||
|
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
foreach (var row in column.Value.GetIndexedEnumerator()) |
|||
{ |
|||
dataWriter.Write(row.Key); |
|||
} |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (nzmax % 2 == 1) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write jc
|
|||
dataWriter.Write((int)DataType.Int32); |
|||
dataWriter.Write((matrix.ColumnCount + 1) * 4); |
|||
dataWriter.Write(0); |
|||
int count = 0; |
|||
foreach (var column in matrix.ColumnEnumerator()) |
|||
{ |
|||
count += ((Complex32.SparseVector)column.Value).NonZerosCount; |
|||
dataWriter.Write(count); |
|||
} |
|||
|
|||
// add pad if needed
|
|||
if (matrix.ColumnCount % 2 == 0) |
|||
{ |
|||
dataWriter.Write(0); |
|||
} |
|||
|
|||
// write data
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
throw new NotImplementedException(); |
|||
data = dataMemoryStream.ToArray(); |
|||
} |
|||
|
|||
return data; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Writes the compressed data.
|
|||
/// </summary>
|
|||
/// <param name="data">The data to write.</param>
|
|||
private void WriteCompressedData(byte[] data) |
|||
{ |
|||
// fill in data size
|
|||
var size = BitConverter.GetBytes(data.Length); |
|||
data[4] = size[0]; |
|||
data[5] = size[1]; |
|||
data[6] = size[2]; |
|||
data[7] = size[3]; |
|||
|
|||
// compress data
|
|||
var compressedData = CompressData(data); |
|||
|
|||
// write compressed data to file
|
|||
_writer.Write(compressedData.Length); |
|||
_writer.Write(compressedData); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Writes the file header.
|
|||
/// </summary>
|
|||
private void WriteHeader() |
|||
{ |
|||
var header = Encoding.ASCII.GetBytes(HeaderText + DateTime.Now.ToString(Resources.MatlabDateHeaderFormat)); |
|||
_writer.Write(header); |
|||
PadData(_writer, HeaderTextLength - header.Length + 8, 32); |
|||
|
|||
// write version
|
|||
_writer.Write((short)0x100); |
|||
|
|||
// write little endian indicator
|
|||
_writer.Write((byte)0x49); |
|||
_writer.Write((byte)0x4D); |
|||
} |
|||
|
|||
/// <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>
|
|||
private static void PadData(BinaryWriter writer, int bytes, byte pad = (byte)0) |
|||
{ |
|||
for (int i = 0; i < bytes; i++) |
|||
{ |
|||
writer.Write(pad); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,115 @@ |
|||
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.IO |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using LinearAlgebra.Double; |
|||
using LinearAlgebra.Double.IO; |
|||
using LinearAlgebra.IO; |
|||
using MbUnit.Framework; |
|||
|
|||
[TestFixture] |
|||
public class MatlabMatrixWriterTests |
|||
{ |
|||
[Test] |
|||
public void Constructor_ThrowsArgumentException() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(string.Empty)); |
|||
Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(null)); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrices_ThrowsArgumentException() |
|||
{ |
|||
Matrix matrix = new DenseMatrix(1, 1); |
|||
var writer = new MatlabMatrixWriter("somefile3"); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new[] { string.Empty })); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new string[] { null })); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix, matrix }, new[] { "matrix" })); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new[] { "some matrix" })); |
|||
writer.Dispose(); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrices_ThrowsArgumentNullException() |
|||
{ |
|||
var writer = new MatlabMatrixWriter("somefile4"); |
|||
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new Matrix[] { null }, new[] { "matrix" })); |
|||
Matrix matrix = new DenseMatrix(1, 1); |
|||
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new[] { matrix }, null)); |
|||
writer.Dispose(); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatricesTest() |
|||
{ |
|||
Matrix mat1 = new DenseMatrix(5, 4); |
|||
for (var i = 0; i < mat1.ColumnCount; i++) |
|||
{ |
|||
mat1[i, i] = i + 1; |
|||
} |
|||
|
|||
Matrix mat2 = new DenseMatrix(4, 5); |
|||
for (var i = 0; i < mat2.RowCount; i++) |
|||
{ |
|||
mat2[i, i] = i + 1; |
|||
} |
|||
|
|||
Matrix mat3 = new SparseMatrix(5, 4); |
|||
for (var i = 0; i < mat3.ColumnCount; i++) |
|||
{ |
|||
mat3[i, i] = i + 1; |
|||
} |
|||
|
|||
Matrix mat4 = new SparseMatrix(4, 5); |
|||
for (var i = 0; i < mat4.RowCount; i++) |
|||
{ |
|||
mat4[i, i] = i + 1; |
|||
} |
|||
|
|||
var write = new[] { mat1, mat2, mat3, mat4 }; |
|||
|
|||
var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" }; |
|||
if (File.Exists("test.mat")) |
|||
{ |
|||
File.Delete("test.mat"); |
|||
} |
|||
|
|||
var writer = new MatlabMatrixWriter("test.mat"); |
|||
writer.WriteMatrices(write, names); |
|||
writer.Dispose(); |
|||
|
|||
var reader = new MatlabMatrixReader("test.mat"); |
|||
var read = reader.ReadMatrices(names); |
|||
|
|||
Assert.AreEqual(write.Length, read.Count); |
|||
|
|||
for (var i = 0; i < write.Length; i++ ) |
|||
{ |
|||
var w = write[i]; |
|||
var r = read[names[i]]; |
|||
|
|||
Assert.AreEqual(w.RowCount, r.RowCount); |
|||
Assert.AreEqual(w.ColumnCount, r.ColumnCount); |
|||
Assert.IsTrue(w.Equals(r)); |
|||
} |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrix_ThrowsArgumentException() |
|||
{ |
|||
Matrix matrix = new DenseMatrix(1, 1); |
|||
var writer = new MatlabMatrixWriter("somefile1"); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrix(matrix, string.Empty)); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrix(matrix, null)); |
|||
writer.Dispose(); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrix_ThrowsArgumentNullException() |
|||
{ |
|||
var writer = new MatlabMatrixWriter("somefile2"); |
|||
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrix<double>(null, "matrix")); |
|||
writer.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,115 @@ |
|||
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.IO |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using LinearAlgebra.IO; |
|||
using LinearAlgebra.Single; |
|||
using LinearAlgebra.Single.IO; |
|||
using MbUnit.Framework; |
|||
|
|||
[TestFixture] |
|||
public class MatlabMatrixWriterTests |
|||
{ |
|||
[Test] |
|||
public void Constructor_ThrowsArgumentException() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(string.Empty)); |
|||
Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(null)); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrices_ThrowsArgumentException() |
|||
{ |
|||
Matrix matrix = new DenseMatrix(1, 1); |
|||
var writer = new MatlabMatrixWriter("somefile3"); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new[] { string.Empty })); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new string[] { null })); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix, matrix }, new[] { "matrix" })); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrices(new[] { matrix }, new[] { "some matrix" })); |
|||
writer.Dispose(); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrices_ThrowsArgumentNullException() |
|||
{ |
|||
var writer = new MatlabMatrixWriter("somefile4"); |
|||
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new Matrix[] { null }, new[] { "matrix" })); |
|||
Matrix matrix = new DenseMatrix(1, 1); |
|||
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new[] { matrix }, null)); |
|||
writer.Dispose(); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatricesTest() |
|||
{ |
|||
Matrix mat1 = new DenseMatrix(5, 4); |
|||
for (var i = 0; i < mat1.ColumnCount; i++) |
|||
{ |
|||
mat1[i, i] = i + 1; |
|||
} |
|||
|
|||
Matrix mat2 = new DenseMatrix(4, 5); |
|||
for (var i = 0; i < mat2.RowCount; i++) |
|||
{ |
|||
mat2[i, i] = i + 1; |
|||
} |
|||
|
|||
Matrix mat3 = new SparseMatrix(5, 4); |
|||
for (var i = 0; i < mat3.ColumnCount; i++) |
|||
{ |
|||
mat3[i, i] = i + 1; |
|||
} |
|||
|
|||
Matrix mat4 = new SparseMatrix(4, 5); |
|||
for (var i = 0; i < mat4.RowCount; i++) |
|||
{ |
|||
mat4[i, i] = i + 1; |
|||
} |
|||
|
|||
var write = new[] { mat1, mat2, mat3, mat4 }; |
|||
|
|||
var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" }; |
|||
if (File.Exists("test.mat")) |
|||
{ |
|||
File.Delete("test.mat"); |
|||
} |
|||
|
|||
var writer = new MatlabMatrixWriter("test.mat"); |
|||
writer.WriteMatrices(write, names); |
|||
writer.Dispose(); |
|||
|
|||
var reader = new MatlabMatrixReader("test.mat"); |
|||
var read = reader.ReadMatrices(names); |
|||
|
|||
Assert.AreEqual(write.Length, read.Count); |
|||
|
|||
for (var i = 0; i < write.Length; i++ ) |
|||
{ |
|||
var w = write[i]; |
|||
var r = read[names[i]]; |
|||
|
|||
Assert.AreEqual(w.RowCount, r.RowCount); |
|||
Assert.AreEqual(w.ColumnCount, r.ColumnCount); |
|||
Assert.IsTrue(w.Equals(r)); |
|||
} |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrix_ThrowsArgumentException() |
|||
{ |
|||
Matrix matrix = new DenseMatrix(1, 1); |
|||
var writer = new MatlabMatrixWriter("somefile1"); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrix(matrix, string.Empty)); |
|||
Assert.Throws<ArgumentException>(() => writer.WriteMatrix(matrix, null)); |
|||
writer.Dispose(); |
|||
} |
|||
|
|||
[Test] |
|||
public void WriteMatrix_ThrowsArgumentNullException() |
|||
{ |
|||
var writer = new MatlabMatrixWriter("somefile2"); |
|||
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrix<double>(null, "matrix")); |
|||
writer.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue