diff --git a/src/Data/Matlab/MatlabFile.cs b/src/Data/Matlab/MatlabFile.cs index ab4cd184..202c42fe 100644 --- a/src/Data/Matlab/MatlabFile.cs +++ b/src/Data/Matlab/MatlabFile.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2013 Math.NET +// 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 @@ -37,13 +37,12 @@ namespace MathNet.Numerics.Data.Matlab /// /// Represents a MATLAB file /// - /// The data type of the matrix to return. - internal class MatlabFile where TDataType : struct, IEquatable, IFormattable + internal class MatlabFile { /// /// 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. @@ -55,32 +54,26 @@ namespace MathNet.Numerics.Data.Matlab /// Gets or sets the first name of the matrix. /// /// The first name of the matrix. - internal string FirstMatrixName { get; set; } + internal string FirstMatrixName { get; private set; } - /// - /// Gets the first matrix. - /// - /// The first matrix. - internal Matrix FirstMatrix + internal ICollection MatrixNames { - get - { - if (string.IsNullOrEmpty(FirstMatrixName) || !_matrices.ContainsKey(FirstMatrixName)) - { - return null; - } + get { return _matrices.Keys; } + } - return _matrices[FirstMatrixName]; + internal void Add(string name, byte[] data) + { + if (FirstMatrixName == null) + { + FirstMatrixName = name; } + + _matrices.Add(name, data); } - /// - /// Gets the matrices. - /// - /// The matrices. - internal IDictionary> Matrices + internal Matrix ReadMatrix(string name) where TDataType : struct, IEquatable, IFormattable { - get { return _matrices; } + return Parser.ReadMatrix(_matrices[name]); } } } diff --git a/src/Data/Matlab/MatlabReader.cs b/src/Data/Matlab/MatlabReader.cs index c5ef2bbe..f78327da 100644 --- a/src/Data/Matlab/MatlabReader.cs +++ b/src/Data/Matlab/MatlabReader.cs @@ -51,15 +51,15 @@ namespace MathNet.Numerics.Data.Matlab if (string.IsNullOrEmpty(matrixName)) { - return file.FirstMatrix; + return file.ReadMatrix(file.FirstMatrixName); } - if (!file.Matrices.ContainsKey(matrixName)) + if (!file.MatrixNames.Contains(matrixName)) { throw new KeyNotFoundException("Matrix with the provided name was not found."); } - return file.Matrices[matrixName]; + return file.ReadMatrix(matrixName); } /// The data type of the Matrix. It can be either: double, float, Complex, or Complex32. @@ -78,7 +78,7 @@ namespace MathNet.Numerics.Data.Matlab { var parser = new Parser(stream, matrixNames); var file = parser.Parse(); - return file.Matrices.ToDictionary(matrix => matrix.Key, matrix => matrix.Value); + return file.MatrixNames.ToDictionary(name => name, file.ReadMatrix); } /// 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 aa68f9d4..d55ca6af 100644 --- a/src/Data/Matlab/Parser.cs +++ b/src/Data/Matlab/Parser.cs @@ -136,9 +136,9 @@ namespace MathNet.Numerics.Data.Matlab /// Parses the file. /// /// The parsed MATLAB file as a object. - internal MatlabFile Parse() + internal MatlabFile Parse() { - var file = new MatlabFile(); + var file = new MatlabFile(); using (var reader = new BinaryReader(_stream)) { @@ -245,10 +245,43 @@ namespace MathNet.Numerics.Data.Matlab /// /// The data of the matrix. /// The instance. - void AddMatrix(byte[] data, MatlabFile file) + 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) + { + using (var stream = new MemoryStream(data)) + using (var reader = new BinaryReader(stream)) { // skip tag - doesn't tell us anything we don't already know reader.BaseStream.Seek(8, SeekOrigin.Current); @@ -282,12 +315,6 @@ namespace MathNet.Numerics.Data.Matlab var name = Encoding.ASCII.GetString(reader.ReadBytes(size)); AlignData(reader.BaseStream, size, smallBlock); - // only grab wanted objects - if (_names.Count != 0 && !_names.Contains(name)) - { - return; - } - var type = (DataType)reader.ReadInt16(); size = reader.ReadInt16(); if (size == 0) @@ -313,11 +340,7 @@ namespace MathNet.Numerics.Data.Matlab break; } - file.Matrices.Add(name, matrix); - if (file.FirstMatrixName == null) - { - file.FirstMatrixName = name; - } + return matrix; } } }