diff --git a/src/Data/Matlab/Matlab.csproj b/src/Data/Matlab/Matlab.csproj
index e612944b..edbce808 100644
--- a/src/Data/Matlab/Matlab.csproj
+++ b/src/Data/Matlab/Matlab.csproj
@@ -51,6 +51,7 @@
+
diff --git a/src/Data/Matlab/MatlabFile.cs b/src/Data/Matlab/MatlabFile.cs
index 202c42fe..bce0f85c 100644
--- a/src/Data/Matlab/MatlabFile.cs
+++ b/src/Data/Matlab/MatlabFile.cs
@@ -42,7 +42,7 @@ namespace MathNet.Numerics.Data.Matlab
///
/// Matrices in a MATLAB file stored as 1-D arrays
///
- readonly IDictionary _matrices = new SortedList();
+ readonly IDictionary _matrices = new SortedList();
///
/// Gets or sets the header text.
@@ -61,7 +61,7 @@ namespace MathNet.Numerics.Data.Matlab
get { return _matrices.Keys; }
}
- internal void Add(string name, byte[] data)
+ internal void Add(string name, MatlabMatrix data)
{
if (FirstMatrixName == null)
{
@@ -73,7 +73,7 @@ namespace MathNet.Numerics.Data.Matlab
internal Matrix ReadMatrix(string name) where TDataType : struct, IEquatable, IFormattable
{
- return Parser.ReadMatrix(_matrices[name]);
+ return _matrices[name].Read();
}
}
}
diff --git a/src/Data/Matlab/MatlabMatrix.cs b/src/Data/Matlab/MatlabMatrix.cs
new file mode 100644
index 00000000..d10d9b12
--- /dev/null
+++ b/src/Data/Matlab/MatlabMatrix.cs
@@ -0,0 +1,59 @@
+//
+// 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;
+using MathNet.Numerics.LinearAlgebra;
+
+namespace MathNet.Numerics.Data.Matlab
+{
+ public class MatlabMatrix
+ {
+ byte[] _data;
+
+ public string Name { get; private set; }
+ public int Size { get; private set; }
+ public int Dimensions { get; private set; }
+
+ internal MatlabMatrix(string name, int size, int dimensions, byte[] data)
+ {
+ _data = data;
+
+ Name = name;
+ Size = size;
+ Dimensions = dimensions;
+ }
+
+ internal Matrix Read()
+ where TDataType : struct, IEquatable, IFormattable
+ {
+ return Parser.ReadMatrixBlock(_data);
+ }
+ }
+}
diff --git a/src/Data/Matlab/MatlabReader.cs b/src/Data/Matlab/MatlabReader.cs
index f78327da..bca107d3 100644
--- a/src/Data/Matlab/MatlabReader.cs
+++ b/src/Data/Matlab/MatlabReader.cs
@@ -47,19 +47,20 @@ namespace MathNet.Numerics.Data.Matlab
{
var names = string.IsNullOrEmpty(matrixName) ? new string[] { } : new[] { matrixName };
var parser = new Parser(stream, names);
- var file = parser.Parse();
+ var file = parser.ParseAll();
if (string.IsNullOrEmpty(matrixName))
{
- return file.ReadMatrix(file.FirstMatrixName);
+ return file.First().Read();
}
- if (!file.MatrixNames.Contains(matrixName))
+ var matrix = file.Find(m => m.Name == matrixName);
+ if (matrix == null)
{
throw new KeyNotFoundException("Matrix with the provided name was not found.");
}
- return file.ReadMatrix(matrixName);
+ return matrix.Read();
}
/// The data type of the Matrix. It can be either: double, float, Complex, or Complex32.
@@ -76,9 +77,10 @@ namespace MathNet.Numerics.Data.Matlab
public static Dictionary> ReadMatrices(Stream stream, params string[] matrixNames)
where TDataType : struct, IEquatable, IFormattable
{
+ var names = new HashSet(matrixNames);
var parser = new Parser(stream, matrixNames);
- var file = parser.Parse();
- return file.MatrixNames.ToDictionary(name => name, file.ReadMatrix);
+ var file = parser.ParseAll();
+ return file.Where(m => names.Count == 0 || names.Contains(m.Name)).ToDictionary(m => m.Name, m => m.Read());
}
/// The data type of the Matrix. It can be either: double, float, Complex, or Complex32.
diff --git a/src/Data/Matlab/Parser.cs b/src/Data/Matlab/Parser.cs
index d55ca6af..7414481a 100644
--- a/src/Data/Matlab/Parser.cs
+++ b/src/Data/Matlab/Parser.cs
@@ -133,20 +133,15 @@ namespace MathNet.Numerics.Data.Matlab
}
///
- /// Parses the file.
+ /// Extracts all matrix blocks in a format we support.
///
- /// The parsed MATLAB file as a object.
- internal MatlabFile Parse()
+ internal List ParseAll()
{
- var file = new MatlabFile();
+ var matrices = new List();
using (var reader = new BinaryReader(_stream))
{
- file.HeaderText = Encoding.ASCII.GetString(reader.ReadBytes(116));
-
- // skipping subsystem offsets
reader.BaseStream.Position = 126;
-
if (reader.ReadByte() != LittleEndianIndicator)
{
throw new NotSupportedException(Resources.BigEndianNotSupported);
@@ -182,16 +177,32 @@ namespace MathNet.Numerics.Data.Matlab
if (type == DataType.Matrix)
{
- AddMatrix(data, file);
- }
- else
- {
- throw new NotSupportedException(string.Format(Resources.NotSupportedType, type));
+ using (var matrixStream = new MemoryStream(data))
+ using (var matrixReader = new BinaryReader(matrixStream))
+ {
+ matrixReader.BaseStream.Seek(20, SeekOrigin.Current);
+ var matrixDim = matrixReader.ReadInt32()/8;
+ if (matrixDim > 2)
+ {
+ continue;
+ }
+
+ matrixReader.BaseStream.Seek(10, SeekOrigin.Current);
+ int matrixSize = matrixReader.ReadInt16();
+ if (matrixSize == 0)
+ {
+ matrixSize = matrixReader.ReadInt32();
+ }
+
+ var matrixName = Encoding.ASCII.GetString(matrixReader.ReadBytes(matrixSize));
+
+ matrices.Add(new MatlabMatrix(matrixName, matrixSize, matrixDim, data));
+ }
}
}
}
- return file;
+ return matrices;
}
///
@@ -240,45 +251,7 @@ namespace MathNet.Numerics.Data.Matlab
return data;
}
- ///
- /// Adds a matrix from the actual file into our presentation of a MATLAB file.
- ///
- /// The data of the matrix.
- /// The instance.
- void AddMatrix(byte[] data, MatlabFile file)
- {
- using (var ms = new MemoryStream(data))
- using (var reader = new BinaryReader(ms))
- {
- // skip unneeded bytes
- reader.BaseStream.Seek(20, SeekOrigin.Current);
-
- var numDimensions = reader.ReadInt32()/8;
- if (numDimensions > 2)
- {
- throw new NotSupportedException(Resources.MoreThan2D);
- }
-
- // skip unneeded bytes
- reader.BaseStream.Seek(10, SeekOrigin.Current);
-
- int size = reader.ReadInt16();
- if (size == 0)
- {
- size = reader.ReadInt32();
- }
-
- var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
-
- // only grab wanted objects
- if (_names.Count == 0 || _names.Contains(name))
- {
- file.Add(name, data);
- }
- }
- }
-
- internal static Matrix ReadMatrix(byte[] data)
+ internal static Matrix ReadMatrixBlock(byte[] data)
{
using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream))
@@ -302,7 +275,7 @@ namespace MathNet.Numerics.Data.Matlab
var rows = reader.ReadInt32();
var columns = reader.ReadInt32();
- // skip unneeded bytes
+ // skip name and unneeded bytes
reader.BaseStream.Seek(2, SeekOrigin.Current);
int size = reader.ReadInt16();
var smallBlock = true;
@@ -311,8 +284,7 @@ namespace MathNet.Numerics.Data.Matlab
size = reader.ReadInt32();
smallBlock = false;
}
-
- var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
+ reader.BaseStream.Seek(size, SeekOrigin.Current);
AlignData(reader.BaseStream, size, smallBlock);
var type = (DataType)reader.ReadInt16();