Browse Source

Data: import data extension soltion back into main repository

pull/222/head
Christoph Ruegg 12 years ago
parent
commit
87f6ce1bbe
  1. 49
      MathNet.Numerics.Data.sln
  2. 4
      RELEASENOTES.md
  3. 54489
      data/MatrixMarket/fidap007.mtx
  4. 95
      src/Data/Matlab/Adler32.cs
  5. 123
      src/Data/Matlab/ArrayClass.cs
  6. 56
      src/Data/Matlab/ArrayFlags.cs
  7. 118
      src/Data/Matlab/DataType.cs
  8. 75
      src/Data/Matlab/Matlab.csproj
  9. 86
      src/Data/Matlab/MatlabFile.cs
  10. 1525
      src/Data/Matlab/MatlabParser.cs
  11. 227
      src/Data/Matlab/MatlabReader.cs
  12. 818
      src/Data/Matlab/MatlabWriter.cs
  13. 46
      src/Data/Matlab/Properties/AssemblyInfo.cs
  14. 4
      src/Data/Matlab/packages.config
  15. 255
      src/Data/Text/DelimitedReader.cs
  16. 215
      src/Data/Text/DelimitedWriter.cs
  17. 374
      src/Data/Text/MatrixMarketReader.cs
  18. 227
      src/Data/Text/MatrixMarketWriter.cs
  19. 46
      src/Data/Text/Properties/AssemblyInfo.cs
  20. 71
      src/Data/Text/Text.csproj
  21. 4
      src/Data/Text/packages.config
  22. 277
      src/DataUnitTests/AssertHelpers.cs
  23. 419
      src/DataUnitTests/Matlab/MatlabReaderTests.cs
  24. 327
      src/DataUnitTests/Matlab/MatlabWriterTests.cs
  25. 36
      src/DataUnitTests/Properties/AssemblyInfo.cs
  26. 251
      src/DataUnitTests/Text/DelimitedReaderTests.cs
  27. 171
      src/DataUnitTests/Text/DelimitedWriterTests.cs
  28. 159
      src/DataUnitTests/Text/MatrixMarketReaderTests.cs
  29. 72
      src/DataUnitTests/Text/MatrixMarketWriterTests.cs
  30. 122
      src/DataUnitTests/UnitTests.csproj
  31. 5
      src/DataUnitTests/packages.config

49
MathNet.Numerics.Data.sln

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Matlab", "src\Data\Matlab\Matlab.csproj", "{550FB330-C86F-4C9D-9B4C-6D830CEB7520}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "src\DataUnitTests\UnitTests.csproj", "{6B0247F6-B332-41BC-B100-C0E5509EE612}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Text", "src\Data\Text\Text.csproj", "{9D3A08E1-6B96-4552-A535-412E589B3264}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "src\Numerics\Numerics.csproj", "{B7CAE5F4-A23F-4438-B5BE-41226618B695}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Release-Signed|Any CPU = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{550FB330-C86F-4C9D-9B4C-6D830CEB7520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{550FB330-C86F-4C9D-9B4C-6D830CEB7520}.Debug|Any CPU.Build.0 = Debug|Any CPU
{550FB330-C86F-4C9D-9B4C-6D830CEB7520}.Release|Any CPU.ActiveCfg = Release|Any CPU
{550FB330-C86F-4C9D-9B4C-6D830CEB7520}.Release|Any CPU.Build.0 = Release|Any CPU
{550FB330-C86F-4C9D-9B4C-6D830CEB7520}.Release-Signed|Any CPU.ActiveCfg = Release|Any CPU
{550FB330-C86F-4C9D-9B4C-6D830CEB7520}.Release-Signed|Any CPU.Build.0 = Release|Any CPU
{6B0247F6-B332-41BC-B100-C0E5509EE612}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B0247F6-B332-41BC-B100-C0E5509EE612}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B0247F6-B332-41BC-B100-C0E5509EE612}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B0247F6-B332-41BC-B100-C0E5509EE612}.Release|Any CPU.Build.0 = Release|Any CPU
{6B0247F6-B332-41BC-B100-C0E5509EE612}.Release-Signed|Any CPU.ActiveCfg = Release|Any CPU
{6B0247F6-B332-41BC-B100-C0E5509EE612}.Release-Signed|Any CPU.Build.0 = Release|Any CPU
{9D3A08E1-6B96-4552-A535-412E589B3264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D3A08E1-6B96-4552-A535-412E589B3264}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D3A08E1-6B96-4552-A535-412E589B3264}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D3A08E1-6B96-4552-A535-412E589B3264}.Release|Any CPU.Build.0 = Release|Any CPU
{9D3A08E1-6B96-4552-A535-412E589B3264}.Release-Signed|Any CPU.ActiveCfg = Release|Any CPU
{9D3A08E1-6B96-4552-A535-412E589B3264}.Release-Signed|Any CPU.Build.0 = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|Any CPU.Build.0 = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

4
RELEASENOTES.md

@ -2,7 +2,7 @@
* Linear Algebra: vector outer product now follows common style, supports explicit result argument, more efficient.
* Interpolation: must not modify/sort original data; alternative Sorted and Inplace functions.
* Distributions: static IsValidParameterSet functions.
* Distributions: all distributions are now immutable in their distribution parameters.
* Distributions: all distributions are now immutable in their distribution parameters. **Breaking.**
* NuGet: attempt to create proper symbol+source packages on symbolsource; primary packages smaller, w/o pdbs
* Build: skip long tests with new "quick" argument (FAKE)
* Build: clearing is more explicit, fixes most locking issues if solution is also open in IDE.
@ -17,7 +17,7 @@
* matrix FoldRows/FoldColumns.
* matrix column/row norms, normalization.
* prefer enums over boolean parameters (e.g. `Zeros.AllowSkip`).
* IsSymmetric is now a method, add IsConjugateSymmetric. **breaking**
* IsSymmetric is now a method, add IsConjugateSymmetric. **Breaking.**
* Eigenvalue decomposition can optionally skip symmetry test.
* Direct diagonal-scalar division implementation
* Test Functions: Rosenbrock, Rastrigin, DropWave, Ackley, Bohachevsky, Matyas, SixHumpCamel, Himmelblau

54489
data/MatrixMarket/fidap007.mtx

File diff suppressed because it is too large

95
src/Data/Matlab/Adler32.cs

@ -0,0 +1,95 @@
// <copyright file="Adler32.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-2013 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>
/* This code is a port and simplification of
adler32.c -- compute the Adler-32 checksum of a data stream
Copyright (C) 1995-2011 Mark Adler
zlib license:
Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
*/
namespace MathNet.Numerics.Data.Matlab
{
internal static class Adler32
{
/* largest prime smaller than 65536 */
const int Base = 65521;
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
const int Nmax = 5552;
/// <summary>
/// Computes the Adler-32 checksum of the given data.
/// </summary>
/// <param name="data">The data to create the checksum.</param>
/// <returns>The checksum</returns>
public static uint Compute(byte[] data)
{
uint adler = 1;
uint sum2 = 0;
var len = data.Length;
var offset = 0;
while (len > 0)
{
var tlen = len < Nmax ? len : Nmax;
len -= tlen;
do
{
adler += data[offset++];
sum2 += adler;
} while (--tlen > 0);
adler %= Base;
sum2 %= Base;
}
return adler | (sum2 << 16);
}
}
}

123
src/Data/Matlab/ArrayClass.cs

@ -0,0 +1,123 @@
// <copyright file="ArrayClass.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-2013 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>
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Enumeration for the Matlab array types
/// </summary>
internal enum ArrayClass : byte
{
/// <summary>
/// mxUNKNOWN CLASS
/// </summary>
Unknown = 0,
/// <summary>
/// mxCELL CLASS
/// </summary>
Cell = 1,
/// <summary>
/// mxSTRUCT CLASS
/// </summary>
Structure = 2,
/// <summary>
/// mxOBJECT CLASS
/// </summary>
Object = 3,
/// <summary>
/// mxCHAR CLASS
/// </summary>
Character = 4,
/// <summary>
/// mxSPARSE CLASS
/// </summary>
Sparse = 5,
/// <summary>
/// mxDOUBLE CLASS
/// </summary>
Double = 6,
/// <summary>
/// mxSINGLE CLASS
/// </summary>
Single = 7,
/// <summary>
/// mxINT8 CLASS
/// </summary>
Int8 = 8,
/// <summary>
/// mxUINT8 CLASS
/// </summary>
UInt8 = 9,
/// <summary>
/// mxINT16 CLASS
/// </summary>
Int16 = 10,
/// <summary>
/// mxUINT16 CLASS
/// </summary>
UInt16 = 11,
/// <summary>
/// mxINT32 CLASS
/// </summary>
Int32 = 12,
/// <summary>
/// mxUINT32 CLASS
/// </summary>
UInt32 = 13,
/// <summary>
/// mxINT64 CLASS
/// </summary>
Int64 = 14,
/// <summary>
/// mxUINT64 CLASS
/// </summary>
UInt64 = 15,
/// <summary>
/// mxFUNCTION CLASS
/// </summary>
Function = 16
}
}

56
src/Data/Matlab/ArrayFlags.cs

@ -0,0 +1,56 @@
// <copyright file="ArrayFlags.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-2013 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;
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Matlab Array Flags
/// </summary>
[Flags]
internal enum ArrayFlags
{
/// <summary>
/// Complex flag
/// </summary>
Complex = 8,
/// <summary>
/// Global flag
/// </summary>
Global = 4,
/// <summary>
/// Logical flag
/// </summary>
Logical = 2
}
}

118
src/Data/Matlab/DataType.cs

@ -0,0 +1,118 @@
// <copyright file="DataType.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-2013 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>
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Matlab data types
/// </summary>
internal enum DataType
{
/// <summary>
/// Unkown type
/// </summary>
Unknown = 0,
/// <summary>
/// miINT8 type
/// </summary>
Int8 = 1,
/// <summary>
/// miUINT8 type
/// </summary>
UInt8 = 2,
/// <summary>
/// miINT16 type
/// </summary>
Int16 = 3,
/// <summary>
/// miUINT16 type
/// </summary>
UInt16 = 4,
/// <summary>
/// miINT32 type
/// </summary>
Int32 = 5,
/// <summary>
/// miUINT32 type
/// </summary>
UInt32 = 6,
/// <summary>
/// miSINGLE type
/// </summary>
Single = 7,
/// <summary>
/// miDOUBLE type
/// </summary>
Double = 9,
/// <summary>
/// miINT64 type
/// </summary>
Int64 = 12,
/// <summary>
/// miUINT6 4type
/// </summary>
UInt64 = 13,
/// <summary>
/// miMATRIX type
/// </summary>
Matrix = 14,
/// <summary>
/// miCOMPRESSED type
/// </summary>
Compressed = 15,
/// <summary>
/// miUTF8 type
/// </summary>
Utf8 = 16,
/// <summary>
/// miUTF16 type
/// </summary>
Utf16 = 17,
/// <summary>
/// miUTF32 type
/// </summary>
Utf32 = 18
}
}

75
src/Data/Matlab/Matlab.csproj

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{550FB330-C86F-4C9D-9B4C-6D830CEB7520}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MathNet.Numerics.Data.Matlab</RootNamespace>
<AssemblyName>MathNet.Numerics.Data.Matlab</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\out\lib-debug\Net40\</OutputPath>
<IntermediateOutputPath>..\..\..\obj\lib-debug\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\..\obj\lib-debug\Net40\</BaseIntermediateOutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\out\lib\Net40\</OutputPath>
<IntermediateOutputPath>..\..\..\obj\lib\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\..\obj\lib\Net40\</BaseIntermediateOutputPath>
<DocumentationFile>..\..\..\out\lib\Net40\MathNet.Numerics.Data.Matlab.xml</DocumentationFile>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Adler32.cs" />
<Compile Include="ArrayClass.cs" />
<Compile Include="ArrayFlags.cs" />
<Compile Include="DataType.cs" />
<Compile Include="MatlabFile.cs" />
<Compile Include="MatlabParser.cs" />
<Compile Include="MatlabReader.cs" />
<Compile Include="MatlabWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Numerics\Numerics.csproj">
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

86
src/Data/Matlab/MatlabFile.cs

@ -0,0 +1,86 @@
// <copyright file="MatlabFile.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-2013 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 MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Represents a Matlab file
/// </summary>
/// <typeparam name="TDataType">The data type of the matrix to return.</typeparam>
internal class MatlabFile<TDataType> where TDataType : struct, IEquatable<TDataType>, IFormattable
{
/// <summary>
/// Matrices in a matlab file stored as 1-D arrays
/// </summary>
private readonly IDictionary<string, Matrix<TDataType>> _matrices = new SortedList<string, Matrix<TDataType>>();
/// <summary>
/// Gets or sets the header text.
/// </summary>
/// <value>The header text.</value>
public string HeaderText { get; set; }
/// <summary>
/// Gets or sets the first name of the matrix.
/// </summary>
/// <value>The first name of the matrix.</value>
public string FirstMatrixName { get; set; }
/// <summary>
/// Gets the first matrix.
/// </summary>
/// <value>The first matrix.</value>
public Matrix<TDataType> FirstMatrix
{
get
{
if (string.IsNullOrEmpty(FirstMatrixName) || !_matrices.ContainsKey(FirstMatrixName))
{
return null;
}
return _matrices[FirstMatrixName];
}
}
/// <summary>
/// Gets the matrices.
/// </summary>
/// <value>The matrices.</value>
public IDictionary<string, Matrix<TDataType>> Matrices
{
get { return _matrices; }
}
}
}

1525
src/Data/Matlab/MatlabParser.cs

File diff suppressed because it is too large

227
src/Data/Matlab/MatlabReader.cs

@ -0,0 +1,227 @@
// <copyright file="MatlabReader.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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Creates matrices from Matlab files.
/// </summary>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
public class MatlabMatrixReader<TDataType> where TDataType : struct, IEquatable<TDataType>, IFormattable
{
/// <summary>
/// The name of the file to read from.
/// </summary>
private readonly string _filename;
/// <summary>
/// The stream to read from if we are not reading from a file directly.
/// </summary>
private readonly Stream _stream;
/// <summary>
/// Initializes a new instance of the <see cref="MatlabMatrixReader{TDataType}"/> class.
/// </summary>
/// <param name="filename">Name of the file to read matrices from.</param>
public MatlabMatrixReader(string filename)
{
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentException(Resources.StringNullOrEmpty, "filename");
}
if (!File.Exists(filename))
{
throw new FileNotFoundException(Resources.FileDoesNotExist, "filename");
}
_filename = filename;
}
/// <summary>
/// Initializes a new instance of the <see cref="MatlabMatrixReader{TDataType}"/> class.
/// </summary>
/// <param name="stream">The stream to reader matrices from.</param>
public MatlabMatrixReader(Stream stream)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
_stream = stream;
}
public static Matrix<TDataType> ReadMatrix(Stream stream, string matrixName = null)
{
var names = string.IsNullOrEmpty(matrixName) ? new string[] { } : new[] { matrixName };
var parser = new MatlabParser<TDataType>(stream, names);
var file = parser.Parse();
if (string.IsNullOrEmpty(matrixName))
{
return file.FirstMatrix;
}
if (!file.Matrices.ContainsKey(matrixName))
{
throw new KeyNotFoundException("Matrix with the provided name was not found.");
}
return file.Matrices[matrixName];
}
public static Matrix<TDataType> ReadMatrix(string filePath, string matrixName = null)
{
using (var stream = File.OpenRead(filePath))
{
return ReadMatrix(stream, matrixName);
}
}
public static Dictionary<string, Matrix<TDataType>> ReadMatrices(Stream stream, params string[] matrixNames)
{
var reader = new MatlabMatrixReader<TDataType>(stream);
return reader.ReadMatrices(matrixNames);
}
public static Dictionary<string, Matrix<TDataType>> ReadMatrices(string filePath, params string[] matrixNames)
{
using (var stream = File.OpenRead(filePath))
{
return ReadMatrices(stream, matrixNames);
}
}
/// <summary>
/// Reads the first matrix from the file or stream.
/// </summary>
/// <returns>
/// A sparse or dense matrix depending on how the matrix
/// is defined in the Matlab file.
/// </returns>
public Matrix<TDataType> ReadMatrix()
{
return ReadMatrix(null);
}
/// <summary>
/// Reads the named matrix from the file or stream.
/// </summary>
/// <param name="matrixName">The name of the matrix to read.</param>
/// <returns>
/// A sparse or dense matrix depending on how the matrix
/// is defined in the Matlab file.
/// <see langword="null"/> is returned if a matrix with the requests name doesn't exist.
/// </returns>
public Matrix<TDataType> ReadMatrix(string matrixName)
{
Stream stream;
if (_filename == null)
{
stream = _stream;
_stream.Seek(0, SeekOrigin.Begin);
}
else
{
stream = new FileStream(_filename, FileMode.Open, FileAccess.Read);
}
var names = string.IsNullOrEmpty(matrixName) ? new string[] { } : new[] { matrixName };
var parser = new MatlabParser<TDataType>(stream, names);
var file = parser.Parse();
Matrix<TDataType> matrix = null;
if (string.IsNullOrEmpty(matrixName))
{
matrix = file.FirstMatrix;
}
else if (file.Matrices.ContainsKey(matrixName))
{
matrix = file.Matrices[matrixName];
}
if (_filename != null)
{
stream.Close();
stream.Dispose();
}
return matrix;
}
/// <summary>
/// Reads all matrices from the file or stream.
/// </summary>
/// <returns>All matrices from the file or stream. The key to the <see cref="IDictionary{T,K}"/>
/// is the matrix's name.</returns>
public Dictionary<string, Matrix<TDataType>> ReadMatrices()
{
return ReadMatrices(new string[] { });
}
/// <summary>
/// Reads the named matrices from the file or stream.
/// </summary>
/// <param name="names">The names of the matrices to retrieve.</param>
/// <returns>
/// The named matrices from the file or stream. The key to the <see cref="IDictionary{T,K}"/>
/// is the matrix's name.</returns>
public Dictionary<string, Matrix<TDataType>> ReadMatrices(IEnumerable<string> names)
{
Stream stream;
if (_filename == null)
{
stream = _stream;
_stream.Seek(0, SeekOrigin.Begin);
}
else
{
stream = new BufferedStream(new FileStream(_filename, FileMode.Open, FileAccess.Read));
}
var parser = new MatlabParser<TDataType>(stream, names);
var file = parser.Parse();
if (_filename != null)
{
stream.Close();
stream.Dispose();
}
return file.Matrices.ToDictionary(matrix => matrix.Key, matrix => matrix.Value);
}
}
}

818
src/Data/Matlab/MatlabWriter.cs

@ -0,0 +1,818 @@
// <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-2013 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.IO.Compression;
using System.Numerics;
using System.Text;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Storage;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Data.Matlab
{
/// <summary>
/// Writes matrices to a Matlab file.
/// </summary>
public class MatlabMatrixWriter : IDisposable
{
/// <summary>
/// The file header value
/// </summary>
const string HeaderText = "MATLAB 5.0 MAT-file, Platform: .NET 4 - Math.NET Numerics, Created on: ";
/// <summary>
/// The length of the header text.
/// </summary>
const int HeaderTextLength = 116;
/// <summary>
/// Have we written the header yet.
/// </summary>
bool _headerWritten;
/// <summary>
/// The binary writer to write to.
/// </summary>
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;
if (typeof (TDataType) == typeof (double))
{
var o = matrix as LinearAlgebra.Double.SparseMatrix;
data = o != null
? GetSparseDataArray((LinearAlgebra.Double.SparseMatrix) (object) matrix, name)
: GetDenseDataArray((LinearAlgebra.Double.Matrix) (object) matrix, name);
}
else if (typeof (TDataType) == typeof (float))
{
var o = matrix as LinearAlgebra.Single.SparseMatrix;
data = o != null
? GetSparseDataArray((LinearAlgebra.Single.SparseMatrix) (object) matrix, name)
: GetDenseDataArray((LinearAlgebra.Single.Matrix) (object) matrix, name);
}
else if (typeof (TDataType) == typeof (Complex))
{
var o = matrix as LinearAlgebra.Complex.SparseMatrix;
data = o != null
? GetSparseDataArray((LinearAlgebra.Complex.SparseMatrix) (object) matrix, name)
: GetDenseDataArray((LinearAlgebra.Complex.Matrix) (object) matrix, name);
}
else if (typeof (TDataType) == typeof (Complex32))
{
var o = matrix as LinearAlgebra.Complex32.SparseMatrix;
data = o != null
? GetSparseDataArray((LinearAlgebra.Complex32.SparseMatrix) (object) matrix, name)
: GetDenseDataArray((LinearAlgebra.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 (var 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="isComplex">if set to <c>true</c> if this a complex matrix.</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>
static void WriteMatrixTagAndName(BinaryWriter writer, ArrayClass arrayClass, bool isComplex,
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);
if (isComplex)
{
writer.Write((byte) ArrayFlags.Complex);
}
else
{
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);
var nameBytes = Encoding.ASCII.GetBytes(name);
// write name
if (nameBytes.Length > 4)
{
writer.Write((int) DataType.Int8);
writer.Write(nameBytes.Length);
writer.Write(nameBytes);
var 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>
static byte[] CompressData(byte[] data)
{
var adler = BitConverter.GetBytes(Adler32.Compute(data));
using (var compressedStream = new MemoryStream())
{
compressedStream.WriteByte(0x58);
compressedStream.WriteByte(0x85);
using (var outputStream = new DeflateStream(compressedStream, CompressionMode.Compress, true))
{
outputStream.Write(data, 0, data.Length);
}
compressedStream.WriteByte(adler[3]);
compressedStream.WriteByte(adler[2]);
compressedStream.WriteByte(adler[1]);
compressedStream.WriteByte(adler[0]);
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>
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, false, 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>
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, false, 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);
}
}
var pad = (matrix.RowCount*matrix.ColumnCount*4)%8;
PadData(dataWriter, pad);
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>
static byte[] GetDenseDataArray(Matrix<Complex> matrix, string name)
{
byte[] data;
using (var dataMemoryStream = new MemoryStream())
using (var dataWriter = new BinaryWriter(dataMemoryStream))
{
WriteMatrixTagAndName(dataWriter, ArrayClass.Double, true, 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);
}
}
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.Imaginary);
}
}
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>
static byte[] GetDenseDataArray(Matrix<Complex32> matrix, string name)
{
byte[] data;
using (var dataMemoryStream = new MemoryStream())
using (var dataWriter = new BinaryWriter(dataMemoryStream))
{
WriteMatrixTagAndName(dataWriter, ArrayClass.Single, true, 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);
}
}
var pad = (matrix.RowCount*matrix.ColumnCount*4)%8;
PadData(dataWriter, pad);
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);
}
}
PadData(dataWriter, pad);
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>
static byte[] GetSparseDataArray(LinearAlgebra.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, false, name, matrix.RowCount, matrix.ColumnCount,
nzmax);
// write ir
dataWriter.Write((int) DataType.Int32);
dataWriter.Write(nzmax*4);
foreach (var column in matrix.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item1);
}
}
// 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);
var count = 0;
foreach (var column in matrix.EnumerateColumns())
{
count += ((SparseVectorStorage<double>) column.Storage).ValueCount;
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.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item2);
}
}
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>
static byte[] GetSparseDataArray(LinearAlgebra.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, false, name, matrix.RowCount, matrix.ColumnCount,
nzmax);
// write ir
dataWriter.Write((int) DataType.Int32);
dataWriter.Write(nzmax*4);
foreach (var column in matrix.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item1);
}
}
// 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);
var count = 0;
foreach (var column in matrix.EnumerateColumns())
{
count += ((SparseVectorStorage<float>) column.Storage).ValueCount;
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.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item2);
}
}
var pad = (nzmax*4)%8;
PadData(dataWriter, pad);
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>
static byte[] GetSparseDataArray(LinearAlgebra.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, true, name, matrix.RowCount, matrix.ColumnCount,
nzmax);
// write ir
dataWriter.Write((int) DataType.Int32);
dataWriter.Write(nzmax*4);
foreach (var column in matrix.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item1);
}
}
// 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);
var count = 0;
foreach (var column in matrix.EnumerateColumns())
{
count += ((SparseVectorStorage<Complex>) column.Storage).ValueCount;
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.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item2.Real);
}
}
dataWriter.Write((int) DataType.Double);
dataWriter.Write(nzmax*8);
foreach (var column in matrix.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item2.Real);
}
}
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>
static byte[] GetSparseDataArray(LinearAlgebra.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, true, name, matrix.RowCount, matrix.ColumnCount,
nzmax);
// write ir
dataWriter.Write((int) DataType.Int32);
dataWriter.Write(nzmax*4);
foreach (var column in matrix.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item1);
}
}
// 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);
var count = 0;
foreach (var column in matrix.EnumerateColumns())
{
count += ((SparseVectorStorage<Complex32>) column.Storage).ValueCount;
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.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item2.Real);
}
}
var pad = (nzmax*4)%8;
PadData(dataWriter, pad);
dataWriter.Write((int) DataType.Single);
dataWriter.Write(nzmax*4);
foreach (var column in matrix.EnumerateColumns())
{
foreach (var row in column.EnumerateNonZeroIndexed())
{
dataWriter.Write(row.Item2.Real);
}
}
PadData(dataWriter, pad);
data = dataMemoryStream.ToArray();
}
return data;
}
/// <summary>
/// Writes the compressed data.
/// </summary>
/// <param name="data">The data to write.</param>
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>
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>
static void PadData(BinaryWriter writer, int bytes, byte pad = (byte) 0)
{
for (var i = 0; i < bytes; i++)
{
writer.Write(pad);
}
}
}
}

46
src/Data/Matlab/Properties/AssemblyInfo.cs

@ -0,0 +1,46 @@
// <copyright file="AssemblyInfo.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009-2013 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.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Math.NET Numerics - MATLAB Data I/O Extensions")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Marcus Cuda, Christoph Ruegg")]
[assembly: AssemblyProduct("Math.NET Numerics")]
[assembly: AssemblyCopyright("Copyright © Math.NET Project")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: CLSCompliant(true)]
[assembly: ComVisible(false)]
[assembly: Guid("1a350030-3ad3-4e15-953d-33342a371aba")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

4
src/Data/Matlab/packages.config

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MathNet.Numerics" version="3.0.0-beta03" targetFramework="net40" />
</packages>

255
src/Data/Text/DelimitedReader.cs

@ -0,0 +1,255 @@
// <copyright file="DelimitedReader.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-2013 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.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text.RegularExpressions;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Data.Text
{
/// <summary>
/// Creates a <see cref="Matrix{T}"/> from a delimited text file. If the user does not
/// specify a delimiter, then any whitespace is used.
/// </summary>
public class DelimitedReader
{
/// <summary>
/// The base regular expression.
/// </summary>
private const string RegexTemplate = "\\([^\\)]*\\)|'[^']*'|\"[^\"]*\"|[^{0}]*";
/// <summary>
/// Cached compiled regular expressions for various delimiters, as needed.
/// </summary>
static readonly ConcurrentDictionary<string, Regex> RegexCache = new ConcurrentDictionary<string, Regex>();
/// <summary>
/// The delimiter to use for parsing. Defaults to any whitespace.
/// </summary>
public string Delimiter { get; set; }
/// <summary>
/// Whether to create sparse matrices or not. Defaults to false.
/// </summary>
public bool Sparse { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the files has a header row.
/// </summary>
/// <value>
/// <c>true</c> if this instance has a header row; otherwise, <c>false</c>.
/// </value>
/// <remarks>Defaults to <see langword="false"/>.</remarks>
public bool HasHeaderRow { get; set; }
/// <summary>
/// Gets or sets the <see cref="FormatProvider"/> to use when parsing the numbers.
/// </summary>
/// <value>The culture info.</value>
/// <remarks>Defaults to <c>CultureInfo.CurrentCulture</c>.</remarks>
public IFormatProvider FormatProvider { get; set; }
/// <summary>
/// Performs the actual reading.
/// </summary>
/// <param name="filePath">The path and name of the file to read the matrix from.</param>
/// <returns>
/// A matrix containing the data from the <see cref="Stream"/>.
/// </returns>
public Matrix<TDataType> ReadMatrix<TDataType>(string filePath)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
return ReadFile<TDataType>(filePath, Sparse, Delimiter, HasHeaderRow, FormatProvider);
}
/// <summary>
/// Performs the actual reading.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to read the matrix from.</param>
/// <returns>
/// A matrix containing the data from the <see cref="Stream"/>.
/// </returns>
public Matrix<TDataType> ReadMatrix<TDataType>(Stream stream)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
return ReadStream<TDataType>(stream, Sparse, Delimiter, HasHeaderRow, FormatProvider);
}
/// <summary>
/// Performs the actual reading.
/// </summary>
/// <param name="reader">The <see cref="TextReader"/> to read the matrix from.</param>
/// <returns>
/// A matrix containing the data from the <see cref="Stream"/>.
/// </returns>
public Matrix<TDataType> ReadMatrix<TDataType>(TextReader reader)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
return Read<TDataType>(reader, Sparse, Delimiter, HasHeaderRow, FormatProvider);
}
/// <summary>
/// Reads a <see cref="Matrix{TDataType}"/> from the given <see cref="TextReader"/>.
/// </summary>
/// <param name="reader">The <see cref="TextReader"/> to read the matrix from.</param>
/// <param name="sparse">Whether the the returned matrix should be constructed as sparse (true) or dense (false). Default: false.</param>
/// <param name="delimiter">Number delimiter between numbers of the same line. Supports Regex groups. Default: "\s" (white space).</param>
/// <param name="hasHeaders">Whether the first row contains column headers or not. Default: false.</param>
/// <param name="formatProvider">The culture to use. Default: null.</param>
/// <returns>A matrix containing the data from the <see cref="TextReader"/>.</returns>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
public static Matrix<TDataType> Read<TDataType>(TextReader reader, bool sparse = false, string delimiter = @"\s", bool hasHeaders = false, IFormatProvider formatProvider = null)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
if (String.IsNullOrEmpty(delimiter))
{
delimiter = @"\s";
}
var regex = RegexCache.GetOrAdd(delimiter, d => new Regex(string.Format(RegexTemplate, d), RegexOptions.Compiled));
var data = new List<string[]>();
// max is used to supports files like:
// 1,2
// 3,4,5,6
// 7
// this creates a 3x4 matrix:
// 1, 2, 0 ,0
// 3, 4, 5, 6
// 7, 0, 0, 0
var max = -1;
var line = reader.ReadLine();
if (hasHeaders)
{
line = reader.ReadLine();
}
while (line != null)
{
line = line.Trim();
if (line.Length > 0)
{
var matches = regex.Matches(line);
var row = (from Match match in matches where match.Length > 0 select match.Value).ToArray();
max = Math.Max(max, row.Length);
data.Add(row);
}
line = reader.ReadLine();
}
var parse = CreateParser<TDataType>(formatProvider);
var matrix = sparse ? Matrix<TDataType>.Build.Sparse(data.Count, max) : Matrix<TDataType>.Build.Dense(data.Count, max);
var storage = matrix.Storage;
for (var i = 0; i < data.Count; i++)
{
var row = data[i];
for (var j = 0; j < row.Length; j++)
{
// strip off quotes (TODO: can we replace this with trimming?)
var value = row[j].Replace("'", string.Empty).Replace("\"", string.Empty);
storage.At(i, j, parse(value));
}
}
reader.Close();
reader.Dispose();
return matrix;
}
/// <summary>
/// Reads a <see cref="Matrix{TDataType}"/> from the given file.
/// </summary>
/// <param name="filePath">The path and name of the file to read the matrix from.</param>
/// <param name="sparse">Whether the the returned matrix should be constructed as sparse (true) or dense (false). Default: false.</param>
/// <param name="delimiter">Number delimiter between numbers of the same line. Supports Regex groups. Default: "\s" (white space).</param>
/// <param name="hasHeaders">Whether the first row contains column headers or not. Default: false.</param>
/// <param name="formatProvider">The culture to use. Default: null.</param>
/// <returns>A matrix containing the data from the <see cref="TextReader"/>.</returns>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
public static Matrix<TDataType> ReadFile<TDataType>(string filePath, bool sparse = false, string delimiter = @"\s", bool hasHeaders = false, IFormatProvider formatProvider = null)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
using (var reader = new StreamReader(filePath))
{
return Read<TDataType>(reader, sparse, delimiter, hasHeaders, formatProvider);
}
}
/// <summary>
/// Reads a <see cref="Matrix{TDataType}"/> from the given <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to read the matrix from.</param>
/// <param name="sparse">Whether the the returned matrix should be constructed as sparse (true) or dense (false). Default: false.</param>
/// <param name="delimiter">Number delimiter between numbers of the same line. Supports Regex groups. Default: "\s" (white space).</param>
/// <param name="hasHeaders">Whether the first row contains column headers or not. Default: false.</param>
/// <param name="formatProvider">The culture to use. Default: null.</param>
/// <returns>A matrix containing the data from the <see cref="TextReader"/>.</returns>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: double, float, Complex, or Complex32.</typeparam>
public static Matrix<TDataType> ReadStream<TDataType>(Stream stream, bool sparse = false, string delimiter = @"\s", bool hasHeaders = false, IFormatProvider formatProvider = null)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
using (var reader = new StreamReader(stream))
{
return Read<TDataType>(reader, sparse, delimiter, hasHeaders, formatProvider);
}
}
static Func<string, T> CreateParser<T>(IFormatProvider formatProvider)
{
if (typeof (T) == typeof (double))
{
return number => (T) (object) double.Parse(number, NumberStyles.Any, formatProvider);
}
if (typeof (T) == typeof (float))
{
return number => (T) (object) float.Parse(number, NumberStyles.Any, formatProvider);
}
if (typeof (T) == typeof (Complex))
{
return number => (T) (object) number.ToComplex(formatProvider);
}
if (typeof (T) == typeof (Complex32))
{
return number => (T) (object) number.ToComplex32(formatProvider);
}
throw new NotSupportedException();
}
}
}

215
src/Data/Text/DelimitedWriter.cs

@ -0,0 +1,215 @@
// <copyright file="DelimitedWriter.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-2013 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 MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Data.Text
{
/// <summary>
/// Writes an <see cref="Matrix{TDataType}"/> to delimited text file. If the user does not
/// specify a delimiter, a tab separator is used.
/// </summary>
public class DelimitedWriter
{
/// <summary>
/// Initializes a new instance of the <see cref="DelimitedWriter"/> class, using a tabulator as the delimiter.
/// </summary>
public DelimitedWriter()
{
Delimiter = "\t";
}
/// <summary>
/// Initializes a new instance of the <see cref="DelimitedWriter"/> class, using the given delimiter.
/// </summary>
public DelimitedWriter(string delimiter)
{
Delimiter = delimiter;
}
/// <summary>
/// The delimiter to use.
/// </summary>
public string Delimiter { get; private set; }
/// <summary>
/// Gets or sets column headers. Headers are only written if the header list is neither <c>null</c> nor empty.
/// </summary>
public IList<string> ColumnHeaders { get; set; }
/// <summary>
/// Gets or sets the number format to use when writing numbers.
/// </summary>
public string Format { get; set; }
/// <summary>
/// Gets or sets the number format culture provider to use when writing numbers.
/// </summary>
public IFormatProvider FormatProvider { get; set; }
/// <summary>
/// Writes the given <see cref="Matrix{DataType}"/> to the given file. If the file already exists,
/// the file will be overwritten.
/// </summary>
/// <param name="matrix">The matrix to write.</param>
/// <param name="filePath">The file to write the matrix to.</param>
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="filePath"/> 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 filePath)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
WriteFile(matrix, filePath, Delimiter, ColumnHeaders, Format, FormatProvider);
}
/// <summary>
/// Writes the given <see cref="Matrix{DataType}"/> to the given stream.
/// </summary>
/// <param name="matrix">The matrix to write.</param>
/// <param name="stream">The <see cref="Stream"/> to write the matrix to.</param>
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="stream"/> 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, Stream stream)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
WriteStream(matrix, stream, Delimiter, ColumnHeaders, Format, FormatProvider);
}
/// <summary>
/// Writes the given <see cref="Matrix{TDataType}"/> to the given <see cref="TextWriter"/>.
/// </summary>
/// <param name="matrix">The matrix to write.</param>
/// <param name="writer">The <see cref="TextWriter"/> to write the matrix to.</param>
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="writer"/> 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, TextWriter writer)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
Write(matrix, writer, Delimiter, ColumnHeaders, Format, FormatProvider);
}
/// <summary>
/// Writes a matrix to the given TextWriter. Optionally accepts custom column headers, delimiter, number format and culture.
/// </summary>
/// <param name="matrix">The matrix to write.</param>
/// <param name="writer">The <see cref="TextWriter"/> to write the matrix to.</param>
/// <param name="delimiter">Number delimiter to write between numbers of the same line. Default: "\t" (tabulator).</param>
/// <param name="columnHeaders">Custom column header. Headers are only written if non-null and non-empty headers are provided. Default: null.</param>
/// <param name="format">The number format to use on each element. Default: null.</param>
/// <param name="formatProvider">The culture to use. Default: null.</param>
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="writer"/> is <c>null</c>.</exception>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: Double, Single, Complex, or Complex32.</typeparam>
public static void Write<TDataType>(Matrix<TDataType> matrix, TextWriter writer, string delimiter = "\t", IList<string> columnHeaders = null, string format = null, IFormatProvider formatProvider = null)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (writer == null)
{
throw new ArgumentNullException("writer");
}
if (columnHeaders != null && columnHeaders.Count > 0)
{
for (var i = 0; i < columnHeaders.Count - 1; i++)
{
writer.Write(columnHeaders[i]);
writer.Write(delimiter);
}
writer.WriteLine(columnHeaders[columnHeaders.Count - 1]);
}
var cols = matrix.ColumnCount - 1;
var rows = matrix.RowCount - 1;
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
writer.Write(matrix[i, j].ToString(format, formatProvider));
if (j != cols)
{
writer.Write(delimiter);
}
}
if (i != rows)
{
writer.Write(Environment.NewLine);
}
}
}
/// <summary>
/// Writes a matrix to the given file. Optionally accepts custom column headers, delimiter, number format and culture.
/// </summary>
/// <param name="matrix">The matrix to write.</param>
/// <param name="filePath">The path and name of the file to write the matrix to. If the file already exists, the file will be overwritten.</param>
/// <param name="delimiter">Number delimiter to write between numbers of the same line. Default: "\t" (tabulator).</param>
/// <param name="columnHeaders">Custom column header. Headers are only written if non-null and non-empty headers are provided. Default: null.</param>
/// <param name="format">The number format to use on each element. Default: null.</param>
/// <param name="formatProvider">The culture to use. Default: null.</param>
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="filePath"/> is <c>null</c>.</exception>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: Double, Single, Complex, or Complex32.</typeparam>
public static void WriteFile<TDataType>(Matrix<TDataType> matrix, string filePath, string delimiter = "\t", IList<string> columnHeaders = null, string format = null, IFormatProvider formatProvider = null)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
using (var writer = new StreamWriter(filePath))
{
Write(matrix, writer, delimiter, columnHeaders, format, formatProvider);
}
}
/// <summary>
/// Writes a matrix to the given stream. Optionally accepts custom column headers, delimiter, number format and culture.
/// </summary>
/// <param name="matrix">The matrix to write.</param>
/// <param name="stream">The <see cref="Stream"/> to write the matrix to.</param>
/// <param name="delimiter">Number delimiter to write between numbers of the same line. Default: "\t" (tabulator).</param>
/// <param name="columnHeaders">Custom column header. Headers are only written if non-null and non-empty headers are provided. Default: null.</param>
/// <param name="format">The number format to use on each element. Default: null.</param>
/// <param name="formatProvider">The culture to use. Default: null.</param>
/// <exception cref="ArgumentNullException">If either <paramref name="matrix"/> or <paramref name="stream"/> is <c>null</c>.</exception>
/// <typeparam name="TDataType">The data type of the Matrix. It can be either: Double, Single, Complex, or Complex32.</typeparam>
public static void WriteStream<TDataType>(Matrix<TDataType> matrix, Stream stream, string delimiter = "\t", IList<string> columnHeaders = null, string format = null, IFormatProvider formatProvider = null)
where TDataType : struct, IEquatable<TDataType>, IFormattable
{
using (var writer = new StreamWriter(stream))
{
Write(matrix, writer, delimiter, columnHeaders, format, formatProvider);
}
}
}
}

374
src/Data/Text/MatrixMarketReader.cs

@ -0,0 +1,374 @@
// <copyright file="MatrixMarketReader.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-2013 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.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Numerics;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Data.Text
{
internal enum MatrixMarketSymmetry
{
General,
Symmetric,
SkewSymmetric,
Hermitian
}
/// <summary>
/// NIST MatrixMarket Format Reader (http://math.nist.gov/MatrixMarket/)
/// </summary>
public static class MatrixMarketReader
{
static readonly char[] Separators = {' '};
static readonly NumberFormatInfo Format = CultureInfo.InvariantCulture.NumberFormat;
public static Matrix<T> ReadMatrix<T>(string filePath, bool compressed = false) where T : struct, IEquatable<T>, IFormattable
{
using (var stream = File.OpenRead(filePath))
{
if (compressed)
{
using (var decompressed = new GZipStream(stream, CompressionMode.Decompress))
using (var reader = new StreamReader(decompressed))
{
return ReadMatrix<T>(reader);
}
}
using (var reader = new StreamReader(stream))
{
return ReadMatrix<T>(reader);
}
}
}
public static Vector<T> ReadVector<T>(string filePath, bool compressed = false) where T : struct, IEquatable<T>, IFormattable
{
using (var stream = File.OpenRead(filePath))
{
if (compressed)
{
using (var decompressed = new GZipStream(stream, CompressionMode.Decompress))
using (var reader = new StreamReader(decompressed))
{
return ReadVector<T>(reader);
}
}
using (var reader = new StreamReader(stream))
{
return ReadVector<T>(reader);
}
}
}
public static Matrix<T> ReadMatrix<T>(Stream stream) where T : struct, IEquatable<T>, IFormattable
{
using (var reader = new StreamReader(stream))
{
return ReadMatrix<T>(reader);
}
}
public static Vector<T> ReadVector<T>(Stream stream) where T : struct, IEquatable<T>, IFormattable
{
using (var reader = new StreamReader(stream))
{
return ReadVector<T>(reader);
}
}
public static Matrix<T> ReadMatrix<T>(TextReader reader) where T : struct, IEquatable<T>, IFormattable
{
bool complex, sparse;
MatrixMarketSymmetry symmetry;
ExpectHeader(reader, true, out complex, out sparse, out symmetry);
var parse = CreateValueParser<T>(complex);
var sizes = ExpectLine(reader).Split(Separators, StringSplitOptions.RemoveEmptyEntries);
int rows = int.Parse(sizes[0]);
int cols = int.Parse(sizes[1]);
if (sparse)
{
var indexed = ReadTokenLines(reader).Select(tokens => new Tuple<int, int, T>(int.Parse(tokens[0]) - 1, int.Parse(tokens[1]) - 1, parse(2, tokens)));
return Matrix<T>.Build.SparseOfIndexed(rows, cols, symmetry == MatrixMarketSymmetry.General ? indexed : ExpandSparse(symmetry, indexed));
}
var columnMajor = ReadTokenLines(reader).Select(tokens => parse(0, tokens));
switch (symmetry)
{
case MatrixMarketSymmetry.General:
{
return Matrix<T>.Build.DenseOfColumnMajor(rows, cols, columnMajor);
}
case MatrixMarketSymmetry.Symmetric:
{
var m = Matrix<T>.Build.Dense(rows, cols);
int k = 0;
foreach (var slice in SliceDecreasing(rows, columnMajor))
{
var vector = Vector<T>.Build.Dense(slice);
m.SetColumn(k, k, rows - k, vector);
m.SetRow(k, k, cols - k, vector);
k++;
}
return m;
}
case MatrixMarketSymmetry.Hermitian:
{
var m = Matrix<T>.Build.Dense(rows, cols);
int k = 0;
foreach (var slice in SliceDecreasing(rows, columnMajor))
{
var vector = Vector<T>.Build.Dense(slice);
m.SetColumn(k, k, rows - k, vector);
m.SetRow(k, k, cols - k, vector.Conjugate());
k++;
}
return m;
}
case MatrixMarketSymmetry.SkewSymmetric:
{
var m = Matrix<T>.Build.Dense(rows, cols);
int k = 0;
foreach (var slice in SliceDecreasing(rows - 1, columnMajor))
{
var vector = Vector<T>.Build.Dense(slice);
m.SetColumn(k, k + 1, rows - 1 - k, vector);
m.SetRow(k, k + 1, cols - 1 - k, vector);
k++;
}
return m;
}
default:
throw new NotSupportedException("Symmetry type not supported.");
}
}
public static Vector<T> ReadVector<T>(TextReader reader)
where T : struct, IEquatable<T>, IFormattable
{
bool complex, sparse;
MatrixMarketSymmetry symmetry;
ExpectHeader(reader, false, out complex, out sparse, out symmetry);
var parse = CreateValueParser<T>(complex);
var sizes = ExpectLine(reader).Split(Separators, StringSplitOptions.RemoveEmptyEntries);
int length = int.Parse(sizes[0]);
if (sparse)
{
var indexedSeq = ReadTokenLines(reader).Select(tokens => new Tuple<int, T>(int.Parse(tokens[0]) - 1, parse(1, tokens)));
return Vector<T>.Build.SparseOfIndexed(length, indexedSeq);
}
return Vector<T>.Build.Dense(ReadTokenLines(reader).Select(tokens => parse(0, tokens)).ToArray());
}
static void ExpectHeader(TextReader reader, bool matrix, out bool complex, out bool sparse, out MatrixMarketSymmetry symmetry)
{
string line;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.StartsWith("%%MatrixMarket"))
{
var tokens = line.ToLowerInvariant().Substring(15).Split(Separators, StringSplitOptions.RemoveEmptyEntries);
if (tokens.Length < 2)
{
throw new FormatException(@"Expected MatrixMarket Header with 2-4 attributes: object format [field] [symmetry]; see http://math.nist.gov/MatrixMarket/ for details.");
}
if (tokens[0] != (matrix ? "matrix" : "vector"))
{
throw new FormatException("Expected matrix content.");
}
switch (tokens[1])
{
case "array":
sparse = false;
break;
case "coordinate":
sparse = true;
break;
default:
throw new NotSupportedException("Format type not supported.");
}
if (tokens.Length < 3)
{
complex = false;
}
else
{
switch (tokens[2])
{
case "real":
case "double":
case "integer":
complex = false;
break;
case "complex":
complex = true;
break;
default:
throw new NotSupportedException("Field type not supported.");
}
}
if (tokens.Length < 4)
{
symmetry = MatrixMarketSymmetry.General;
}
else
{
switch (tokens[3])
{
case "general":
symmetry = MatrixMarketSymmetry.General;
break;
case "symmetric":
symmetry = MatrixMarketSymmetry.Symmetric;
break;
case "skew-symmetric":
symmetry = MatrixMarketSymmetry.SkewSymmetric;
break;
case "hermitian":
symmetry = MatrixMarketSymmetry.Hermitian;
break;
default:
throw new NotSupportedException("Symmetry type not supported");
}
}
return;
}
}
throw new FormatException(@"Expected MatrixMarket Header, see http://math.nist.gov/MatrixMarket/ for details.");
}
static string ExpectLine(TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
var trim = line.Trim();
if (trim.Length > 0 && !trim.StartsWith("%"))
{
return trim;
}
}
throw new FormatException(@"End of file reached unexpectedly.");
}
static IEnumerable<string[]> ReadTokenLines(TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
var trim = line.Trim();
if (trim.Length > 0 && !trim.StartsWith("%"))
{
yield return trim.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
}
}
}
static IEnumerable<Tuple<int, int, T>> ExpandSparse<T>(MatrixMarketSymmetry symmetry, IEnumerable<Tuple<int, int, T>> indexedValues)
{
var map = CreateSymmetryMap<T>(symmetry);
foreach (var x in indexedValues)
{
yield return x;
if (x.Item1 != x.Item2)
{
yield return new Tuple<int, int, T>(x.Item2, x.Item1, map(x.Item3));
}
}
}
static IEnumerable<T[]> SliceDecreasing<T>(int initialLength, IEnumerable<T> columnMajor)
{
int nextIndex = 0;
var slice = new T[initialLength];
foreach (var value in columnMajor)
{
if (nextIndex == initialLength)
{
yield return slice;
slice = new T[--initialLength];
nextIndex = 0;
}
slice[nextIndex++] = value;
}
yield return slice;
}
static Func<int, string[], T> CreateValueParser<T>(bool sourceIsComplex)
{
if (typeof (T) == typeof (double))
{
// ignore imaginary part if source is complex
return (offset, tokens) => (T) (object) double.Parse(tokens[offset], NumberStyles.Any, Format);
}
if (typeof (T) == typeof (float))
{
// ignore imaginary part if source is complex
return (offset, tokens) => (T) (object) float.Parse(tokens[offset], NumberStyles.Any, Format);
}
if (typeof (T) == typeof (Complex))
{
return sourceIsComplex
? ((offset, tokens) => (T) (object) new Complex(double.Parse(tokens[offset], NumberStyles.Any, Format), double.Parse(tokens[offset + 1], NumberStyles.Any, Format)))
: (Func<int, string[], T>) ((offset, tokens) => (T) (object) new Complex(double.Parse(tokens[offset], NumberStyles.Any, Format), 0d));
}
if (typeof (T) == typeof (Complex32))
{
return sourceIsComplex
? ((offset, tokens) => (T) (object) new Complex32(float.Parse(tokens[offset], NumberStyles.Any, Format), float.Parse(tokens[offset + 1], NumberStyles.Any, Format)))
: (Func<int, string[], T>) ((offset, tokens) => (T) (object) new Complex32(float.Parse(tokens[offset], NumberStyles.Any, Format), 0f));
}
throw new NotSupportedException();
}
static Func<T, T> CreateSymmetryMap<T>(MatrixMarketSymmetry symmetry)
{
if (symmetry != MatrixMarketSymmetry.Hermitian) return x => x;
if (typeof (T) == typeof (double) || typeof (T) == typeof (float)) return x => x;
if (typeof (T) == typeof (Complex)) return x => (T) (object) ((Complex) (object) x).Conjugate();
if (typeof (T) == typeof (Complex32)) return x => (T) (object) ((Complex32) (object) x).Conjugate();
throw new NotSupportedException();
}
}
}

227
src/Data/Text/MatrixMarketWriter.cs

@ -0,0 +1,227 @@
// <copyright file="MatrixMarketWriter.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-2013 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.Globalization;
using System.IO;
using System.IO.Compression;
using System.Numerics;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Storage;
namespace MathNet.Numerics.Data.Text
{
/// <summary>
/// NIST MatrixMarket Format Writer (http://math.nist.gov/MatrixMarket/)
/// </summary>
public static class MatrixMarketWriter
{
static readonly NumberFormatInfo Format = CultureInfo.InvariantCulture.NumberFormat;
public static void WriteMatrix<T>(string filePath, Matrix<T> matrix, bool compress = false) where T : struct, IEquatable<T>, IFormattable
{
using (var stream = File.OpenWrite(filePath))
{
if (compress)
{
using (var compressed = new GZipStream(stream, CompressionMode.Compress))
using (var buffered = new BufferedStream(compressed, 4096))
using (var writer = new StreamWriter(buffered))
{
WriteMatrix(writer, matrix);
return;
}
}
using (var writer = new StreamWriter(stream))
{
WriteMatrix(writer, matrix);
}
}
}
public static void WriteVector<T>(string filePath, Vector<T> vector, bool compress = false) where T : struct, IEquatable<T>, IFormattable
{
using (var stream = File.OpenRead(filePath))
{
if (compress)
{
using (var compressed = new GZipStream(stream, CompressionMode.Compress))
using (var buffered = new BufferedStream(compressed, 4096))
using (var writer = new StreamWriter(buffered))
{
WriteVector(writer, vector);
return;
}
}
using (var writer = new StreamWriter(stream))
{
WriteVector(writer, vector);
}
}
}
public static void WriteMatrix<T>(Stream stream, Matrix<T> matrix) where T : struct, IEquatable<T>, IFormattable
{
using (var writer = new StreamWriter(stream))
{
WriteMatrix(writer, matrix);
}
}
public static void WriteVector<T>(Stream stream, Vector<T> vector) where T : struct, IEquatable<T>, IFormattable
{
using (var writer = new StreamWriter(stream))
{
WriteVector(writer, vector);
}
}
public static void WriteMatrix<T>(TextWriter writer, Matrix<T> matrix) where T : struct, IEquatable<T>, IFormattable
{
var complex = typeof (T) == typeof (Complex) || typeof (T) == typeof (Complex32);
var format = CreateValueFormatter<T>();
var storage = matrix.Storage;
var sparse = storage as SparseCompressedRowMatrixStorage<T>;
if (sparse != null)
{
writer.WriteLine("%%MatrixMarket matrix coordinate {0} general", complex ? "complex" : "real");
writer.WriteLine("{0} {1} {2}", sparse.RowCount, sparse.ColumnCount, sparse.ValueCount);
for (int row = 0; row < sparse.RowCount; row++)
{
var endIndex = sparse.RowPointers[row + 1];
for (var j = sparse.RowPointers[row]; j < endIndex; j++)
{
writer.WriteLine("{0} {1} {2}", row + 1, sparse.ColumnIndices[j] + 1, format(sparse.Values[j]));
}
}
return;
}
var diagonal = storage as DiagonalMatrixStorage<T>;
if (diagonal != null)
{
writer.WriteLine("%%MatrixMarket matrix coordinate {0} general", complex ? "complex" : "real");
writer.WriteLine("{0} {1} {2}", diagonal.RowCount, diagonal.ColumnCount, diagonal.Data.Length);
for (int k = 0; k < diagonal.Data.Length; k++)
{
writer.WriteLine("{0} {1} {2}", k + 1, k + 1, format(diagonal.Data[k]));
}
return;
}
var dense = storage as DenseColumnMajorMatrixStorage<T>;
if (dense != null)
{
writer.WriteLine("%%MatrixMarket matrix array {0} general", complex ? "complex" : "real");
writer.WriteLine("{0} {1}", dense.RowCount, dense.ColumnCount);
foreach (var value in dense.Data)
{
writer.WriteLine(format(value));
}
return;
}
writer.WriteLine("%%MatrixMarket matrix array {0} general", complex ? "complex" : "real");
writer.WriteLine("{0} {1}", storage.RowCount, storage.ColumnCount);
foreach (var value in storage.ToColumnMajorArray())
{
writer.WriteLine(format(value));
}
}
public static void WriteVector<T>(TextWriter writer, Vector<T> vector) where T : struct, IEquatable<T>, IFormattable
{
var complex = typeof (T) == typeof (Complex) || typeof (T) == typeof (Complex32);
var format = CreateValueFormatter<T>();
var storage = vector.Storage;
var sparse = storage as SparseVectorStorage<T>;
if (sparse != null)
{
writer.WriteLine("%%MatrixMarket vector coordinate {0}", complex ? "complex" : "real");
writer.WriteLine("{0} {1}", sparse.Length, sparse.ValueCount);
for (var k = 0; k < sparse.ValueCount; k++)
{
writer.WriteLine("{0} {1}", k + 1, format(sparse.Values[k]));
}
return;
}
var dense = storage as DenseVectorStorage<T>;
if (dense != null)
{
writer.WriteLine("%%MatrixMarket vector array {0}", complex ? "complex" : "real");
writer.WriteLine("{0}", dense.Length);
foreach (var value in dense.Data)
{
writer.WriteLine(format(value));
}
return;
}
writer.WriteLine("%%MatrixMarket vector array {0}", complex ? "complex" : "real");
writer.WriteLine("{0}", storage.Length);
foreach (var value in storage.Enumerate())
{
writer.WriteLine(format(value));
}
}
static Func<T, string> CreateValueFormatter<T>() where T : IFormattable
{
if (typeof (T) == typeof (double))
{
return value => string.Format(Format, "{0:G14}", value);
}
if (typeof (T) == typeof (float))
{
return value => string.Format(Format, "{0:G7}", value);
}
if (typeof (T) == typeof (Complex))
{
return value =>
{
var c = (Complex) (object) value;
return string.Format(Format, "{0:G14} {1:G14}", c.Real, c.Imaginary);
};
}
if (typeof (T) == typeof (Complex32))
{
return value =>
{
var c = (Complex32) (object) value;
return string.Format(Format, "{0:G7} {1:G7}", c.Real, c.Imaginary);
};
}
throw new NotSupportedException();
}
}
}

46
src/Data/Text/Properties/AssemblyInfo.cs

@ -0,0 +1,46 @@
// <copyright file="AssemblyInfo.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009-2013 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.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Math.NET Numerics - Text Data I/O Extensions")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Marcus Cuda, Christoph Ruegg")]
[assembly: AssemblyProduct("Math.NET Numerics")]
[assembly: AssemblyCopyright("Copyright © Math.NET Project")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: CLSCompliant(true)]
[assembly: ComVisible(false)]
[assembly: Guid("d9f6a513-7772-4a7d-a15e-668dfcdf5b00")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

71
src/Data/Text/Text.csproj

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9D3A08E1-6B96-4552-A535-412E589B3264}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MathNet.Numerics.Data.Text</RootNamespace>
<AssemblyName>MathNet.Numerics.Data.Text</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\out\lib-debug\Net40\</OutputPath>
<IntermediateOutputPath>..\..\..\obj\lib-debug\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\..\obj\lib-debug\Net40\</BaseIntermediateOutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\out\lib\Net40\</OutputPath>
<IntermediateOutputPath>..\..\..\obj\lib\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\..\obj\lib\Net40\</BaseIntermediateOutputPath>
<DocumentationFile>..\..\..\out\lib\Net40\MathNet.Numerics.Data.Text.xml</DocumentationFile>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DelimitedReader.cs" />
<Compile Include="DelimitedWriter.cs" />
<Compile Include="MatrixMarketReader.cs" />
<Compile Include="MatrixMarketWriter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Numerics\Numerics.csproj">
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

4
src/Data/Text/packages.config

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MathNet.Numerics" version="3.0.0-beta03" targetFramework="net40" />
</packages>

277
src/DataUnitTests/AssertHelpers.cs

@ -0,0 +1,277 @@
// <copyright file="AssertHelpers.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.Collections.Generic;
using System.Numerics;
using NUnit.Framework;
namespace MathNet.Numerics.Data.UnitTests
{
/// <summary>
/// A class which includes some assertion helper methods particularly for numerical code.
/// </summary>
internal class AssertHelpers
{
/// <summary>
/// Asserts that the expected value and the actual value are equal.
/// </summary>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
public static void AreEqual(Complex expected, Complex actual)
{
if (expected.IsNaN() && actual.IsNaN())
{
return;
}
if (expected.IsInfinity() && expected.IsInfinity())
{
return;
}
var pass = expected.Real.AlmostEqual(actual.Real);
if (!pass)
{
Assert.Fail("Real components are not equal. Expected:{0}; Actual:{1}", expected.Real, actual.Real);
}
pass = expected.Imaginary.AlmostEqual(actual.Imaginary);
if (!pass)
{
Assert.Fail("Imaginary components are not equal. Expected:{0}; Actual:{1}", expected.Imaginary, actual.Imaginary);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal.
/// </summary>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
public static void AreEqual(Complex32 expected, Complex32 actual)
{
if (expected.IsNaN() && actual.IsNaN())
{
return;
}
if (expected.IsInfinity() && expected.IsInfinity())
{
return;
}
var pass = expected.Real.AlmostEqual(actual.Real);
if (!pass)
{
Assert.Fail("Real components are not equal. Expected:{0}; Actual:{1}", expected.Real, actual.Real);
}
pass = expected.Imaginary.AlmostEqual(actual.Imaginary);
if (!pass)
{
Assert.Fail("Imaginary components are not equal. Expected:{0}; Actual:{1}", expected.Imaginary, actual.Imaginary);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain number of decimal places. If both
/// <paramref name="expected"/> and <paramref name="actual"/> are NaN then no assert is thrown.
/// </summary>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
/// <param name="decimalPlaces">The number of decimal places to agree on.</param>
public static void AlmostEqual(double expected, double actual, int decimalPlaces)
{
if (double.IsNaN(expected) && double.IsNaN(actual))
{
return;
}
var pass = expected.AlmostEqualRelative(actual, decimalPlaces);
if (!pass)
{
// signals Gallio that the test failed.
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain number of decimal places. If both
/// <paramref name="expected"/> and <paramref name="actual"/> are NaN then no assert is thrown.
/// </summary>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
/// <param name="decimalPlaces">The number of decimal places to agree on.</param>
public static void AlmostEqual(float expected, float actual, int decimalPlaces)
{
if (float.IsNaN(expected) && float.IsNaN(actual))
{
return;
}
var pass = expected.AlmostEqualRelative(actual, decimalPlaces);
if (!pass)
{
// signals Gallio that the test failed.
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain number of decimal places.
/// </summary>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
/// <param name="decimalPlaces">The number of decimal places to agree on.</param>
public static void AlmostEqual(Complex expected, Complex actual, int decimalPlaces)
{
var pass = expected.Real.AlmostEqualRelative(actual.Real, decimalPlaces);
if (!pass)
{
Assert.Fail("Real components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Real, actual.Real);
}
pass = expected.Imaginary.AlmostEqualRelative(actual.Imaginary, decimalPlaces);
if (!pass)
{
Assert.Fail("Imaginary components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Imaginary, actual.Imaginary);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain number of decimal places.
/// </summary>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
/// <param name="decimalPlaces">The number of decimal places to agree on.</param>
public static void AlmostEqual(Complex32 expected, Complex32 actual, int decimalPlaces)
{
var pass = expected.Real.AlmostEqualRelative(actual.Real, decimalPlaces);
if (!pass)
{
Assert.Fail("Real components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Real, actual.Real);
}
pass = expected.Imaginary.AlmostEqualRelative(actual.Imaginary, decimalPlaces);
if (!pass)
{
Assert.Fail("Imaginary components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Imaginary, actual.Imaginary);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain
/// maximum error.
/// </summary>
/// <typeparam name="T">The type of the structures. Must implement
/// <see cref="IPrecisionSupport{T}"/>.</typeparam>
/// <param name="expected">The expected value.</param>
/// <param name="actual">The actual value.</param>
/// <param name="maximumError">The accuracy required for being almost equal.</param>
public static void AlmostEqual<T>(T expected, T actual, double maximumError)
where T : IPrecisionSupport<T>
{
if (!actual.AlmostEqualNorm(expected, maximumError))
{
Assert.Fail("Not equal within a maximum error {0}. Expected:{1}; Actual:{2}", maximumError, expected, actual);
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain
/// maximum error.
/// </summary>
/// <param name="expected">The expected value list.</param>
/// <param name="actual">The actual value list.</param>
/// <param name="maximumError">The accuracy required for being almost equal.</param>
public static void AlmostEqualList(IList<double> expected, IList<double> actual, double maximumError)
{
for (var i = 0; i < expected.Count; i++)
{
if (!actual[i].AlmostEqual(expected[i], maximumError))
{
Assert.Fail("Not equal within a maximum error {0}. Expected:{1}; Actual:{2}", maximumError, expected[i], actual[i]);
}
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain
/// maximum error.
/// </summary>
/// <param name="expected">The expected value list.</param>
/// <param name="actual">The actual value list.</param>
/// <param name="maximumError">The accuracy required for being almost equal.</param>
public static void AlmostEqualList(IList<float> expected, IList<float> actual, double maximumError)
{
for (var i = 0; i < expected.Count; i++)
{
if (!actual[i].AlmostEqual(expected[i], maximumError))
{
Assert.Fail("Not equal within a maximum error {0}. Expected:{1}; Actual:{2}", maximumError, expected[i], actual[i]);
}
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain
/// maximum error.
/// </summary>
/// <typeparam name="T">The type of the structures. Must implement
/// <see cref="IPrecisionSupport{T}"/>.</typeparam>
/// <param name="expected">The expected value list.</param>
/// <param name="actual">The actual value list.</param>
/// <param name="maximumError">The accuracy required for being almost equal.</param>
public static void AlmostEqualList<T>(IList<T> expected, IList<T> actual, double maximumError)
where T : IPrecisionSupport<T>
{
for (var i = 0; i < expected.Count; i++)
{
if (!actual[i].AlmostEqualNorm(expected[i], maximumError))
{
Assert.Fail("Not equal within a maximum error {0}. Expected:{1}; Actual:{2}", maximumError, expected[i], actual[i]);
}
}
}
/// <summary>
/// Asserts that the expected value and the actual value are equal up to a certain
/// maximum error.
/// </summary>
/// <param name="expected">The expected value list.</param>
/// <param name="actual">The actual value list.</param>
/// <param name="maximumError">The accuracy required for being almost equal.</param>
public static void AlmostEqualList(IList<Complex> expected, IList<Complex> actual, double maximumError)
{
for (var i = 0; i < expected.Count; i++)
{
if (!actual[i].AlmostEqual(expected[i], maximumError))
{
Assert.Fail("Not equal within a maximum error {0}. Expected:{1}; Actual:{2}", maximumError, expected[i], actual[i]);
}
}
}
}
}

419
src/DataUnitTests/Matlab/MatlabReaderTests.cs

@ -0,0 +1,419 @@
// <copyright file="MatlabReaderTests.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.Numerics;
using MathNet.Numerics.Data.Matlab;
using NUnit.Framework;
namespace MathNet.Numerics.Data.UnitTests.Matlab
{
/// <summary>
/// Matlab matrix reader test.
/// </summary>
[TestFixture]
public class MatlabMatrixReaderTests
{
/// <summary>
/// Can read all matrices.
/// </summary>
[Test]
public void CanReadAllMatrices()
{
var dmr = new MatlabMatrixReader<double>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(30, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Double.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read first matrix.
/// </summary>
[Test]
public void CanReadFirstMatrix()
{
var dmr = new MatlabMatrixReader<double>("./data/Matlab/A.mat");
var matrix = dmr.ReadMatrix();
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Double.DenseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(100.108979553704, matrix.FrobeniusNorm(), 5);
}
/// <summary>
/// Can read named matrices.
/// </summary>
[Test]
public void CanReadNamedMatrices()
{
var dmr = new MatlabMatrixReader<double>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad", "Au64" });
Assert.AreEqual(2, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Double.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read named matrix.
/// </summary>
[Test]
public void CanReadNamedMatrix()
{
var dmr = new MatlabMatrixReader<double>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad" });
Assert.AreEqual(1, matrices.Count);
var ad = matrices["Ad"];
Assert.AreEqual(100, ad.RowCount);
Assert.AreEqual(100, ad.ColumnCount);
AssertHelpers.AlmostEqual(100.431635988639, ad.FrobeniusNorm(), 5);
Assert.AreEqual(typeof(LinearAlgebra.Double.DenseMatrix), ad.GetType());
}
/// <summary>
/// Can read named sparse matrix.
/// </summary>
[Test]
public void CanReadNamedSparseMatrix()
{
var dmr = new MatlabMatrixReader<double>("./data/Matlab/sparse-small.mat");
var matrix = dmr.ReadMatrix("S");
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Double.SparseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(17.6385090630805, matrix.FrobeniusNorm(), 12);
}
/// <summary>
/// Can read all complex matrices.
/// </summary>
[Test]
public void CanReadComplexAllMatrices()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/complex.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(3, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex.DenseMatrix), matrix.Value.GetType());
}
var a = matrices["a"];
Assert.AreEqual(100, a.RowCount);
Assert.AreEqual(100, a.ColumnCount);
AssertHelpers.AlmostEqual(27.232498979698409, a.L2Norm(), 13);
}
/// <summary>
/// Can read sparse complex matrices.
/// </summary>
[Test]
public void CanReadSparseComplexAllMatrices()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/sparse_complex.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(3, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex.SparseMatrix), matrix.Value.GetType());
}
var a = matrices["sa"];
Assert.AreEqual(100, a.RowCount);
Assert.AreEqual(100, a.ColumnCount);
AssertHelpers.AlmostEqual(13.223654390985379, a.L2Norm(), 13);
}
/// <summary>
/// Can read non-complex matrices.
/// </summary>
[Test]
public void CanReadNonComplexAllMatrices()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(30, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read non-complex first matrix.
/// </summary>
[Test]
public void CanReadNonComplexFirstMatrix()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/A.mat");
var matrix = dmr.ReadMatrix();
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Complex.DenseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(100.108979553704, matrix.FrobeniusNorm(), 13);
}
/// <summary>
/// Can read non-complex named matrices.
/// </summary>
[Test]
public void CanReadNonComplexNamedMatrices()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad", "Au64" });
Assert.AreEqual(2, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read non-complex named matrix.
/// </summary>
[Test]
public void CanReadNonComplexNamedMatrix()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad" });
Assert.AreEqual(1, matrices.Count);
var ad = matrices["Ad"];
Assert.AreEqual(100, ad.RowCount);
Assert.AreEqual(100, ad.ColumnCount);
AssertHelpers.AlmostEqual(100.431635988639, ad.FrobeniusNorm(), 13);
Assert.AreEqual(typeof(LinearAlgebra.Complex.DenseMatrix), ad.GetType());
}
/// <summary>
/// Can read non-complex named sparse matrix.
/// </summary>
[Test]
public void CanReadNonComplexNamedSparseMatrix()
{
var dmr = new MatlabMatrixReader<Complex>("./data/Matlab/sparse-small.mat");
var matrix = dmr.ReadMatrix("S");
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Complex.SparseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(17.6385090630805, matrix.FrobeniusNorm(), 12);
}
/// <summary>
/// Can read all complex matrices.
/// </summary>
[Test]
public void CanReadComplex32AllMatrices()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/complex.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(3, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex32.DenseMatrix), matrix.Value.GetType());
}
var a = matrices["a"];
Assert.AreEqual(100, a.RowCount);
Assert.AreEqual(100, a.ColumnCount);
AssertHelpers.AlmostEqual(27.232498979698409, a.L2Norm(), 5);
}
/// <summary>
/// Can read sparse complex matrices.
/// </summary>
[Test]
public void CanReadSparseComplex32AllMatrices()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/sparse_complex.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(3, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex32.SparseMatrix), matrix.Value.GetType());
}
var a = matrices["sa"];
Assert.AreEqual(100, a.RowCount);
Assert.AreEqual(100, a.ColumnCount);
AssertHelpers.AlmostEqual(13.223654390985379, a.L2Norm(), 5);
}
/// <summary>
/// Can read non-complex matrices.
/// </summary>
[Test]
public void CanReadNonComplex32AllMatrices()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(30, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex32.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read non-complex first matrix.
/// </summary>
[Test]
public void CanReadNonComplex32FirstMatrix()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/A.mat");
var matrix = dmr.ReadMatrix();
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Complex32.DenseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(100.108979553704, matrix.FrobeniusNorm(), 6);
}
/// <summary>
/// Can read non-complex named matrices.
/// </summary>
[Test]
public void CanReadNonComplex32NamedMatrices()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad", "Au64" });
Assert.AreEqual(2, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Complex32.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read non-complex named matrix.
/// </summary>
[Test]
public void CanReadNonComplex32NamedMatrix()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad" });
Assert.AreEqual(1, matrices.Count);
var ad = matrices["Ad"];
Assert.AreEqual(100, ad.RowCount);
Assert.AreEqual(100, ad.ColumnCount);
AssertHelpers.AlmostEqual(100.431635988639, ad.FrobeniusNorm(), 6);
Assert.AreEqual(typeof(LinearAlgebra.Complex32.DenseMatrix), ad.GetType());
}
/// <summary>
/// Can read non-complex named sparse matrix.
/// </summary>
[Test]
public void CanReadNonComplex32NamedSparseMatrix()
{
var dmr = new MatlabMatrixReader<Complex32>("./data/Matlab/sparse-small.mat");
var matrix = dmr.ReadMatrix("S");
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Complex32.SparseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(17.6385090630805, matrix.FrobeniusNorm(), 6);
}
/// <summary>
/// Can read all matrices.
/// </summary>
[Test]
public void CanReadFloatAllMatrices()
{
var dmr = new MatlabMatrixReader<float>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices();
Assert.AreEqual(30, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Single.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read first matrix.
/// </summary>
[Test]
public void CanReadFloatFirstMatrix()
{
var dmr = new MatlabMatrixReader<float>("./data/Matlab/A.mat");
var matrix = dmr.ReadMatrix();
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Single.DenseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(100.108979553704f, matrix.FrobeniusNorm(), 6);
}
/// <summary>
/// Can read named matrices.
/// </summary>
[Test]
public void CanReadFloatNamedMatrices()
{
var dmr = new MatlabMatrixReader<float>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad", "Au64" });
Assert.AreEqual(2, matrices.Count);
foreach (var matrix in matrices)
{
Assert.AreEqual(typeof(LinearAlgebra.Single.DenseMatrix), matrix.Value.GetType());
}
}
/// <summary>
/// Can read named matrix.
/// </summary>
[Test]
public void CanReadFloatNamedMatrix()
{
var dmr = new MatlabMatrixReader<float>("./data/Matlab/collection.mat");
var matrices = dmr.ReadMatrices(new[] { "Ad" });
Assert.AreEqual(1, matrices.Count);
var ad = matrices["Ad"];
Assert.AreEqual(100, ad.RowCount);
Assert.AreEqual(100, ad.ColumnCount);
AssertHelpers.AlmostEqual(100.431635988639f, ad.FrobeniusNorm(), 6);
Assert.AreEqual(typeof(LinearAlgebra.Single.DenseMatrix), ad.GetType());
}
/// <summary>
/// Can read named sparse matrix.
/// </summary>
[Test]
public void CanReadFloatNamedSparseMatrix()
{
var dmr = new MatlabMatrixReader<float>("./data/Matlab/sparse-small.mat");
var matrix = dmr.ReadMatrix("S");
Assert.AreEqual(100, matrix.RowCount);
Assert.AreEqual(100, matrix.ColumnCount);
Assert.AreEqual(typeof(LinearAlgebra.Single.SparseMatrix), matrix.GetType());
AssertHelpers.AlmostEqual(17.6385090630805f, matrix.FrobeniusNorm(), 6);
}
}
}

327
src/DataUnitTests/Matlab/MatlabWriterTests.cs

@ -0,0 +1,327 @@
// <copyright file="MatlabWriterTests.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.IO;
using System.Numerics;
using MathNet.Numerics.Data.Matlab;
using NUnit.Framework;
namespace MathNet.Numerics.Data.UnitTests.Matlab
{
/// <summary>
/// Matlab matrix writer tests.
/// </summary>
[TestFixture]
public class MatlabMatrixWriterTests
{
/// <summary>
/// Invalid constructor throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void InvalidConstructorThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(string.Empty));
Assert.Throws<ArgumentException>(() => new MatlabMatrixWriter(null));
}
/// <summary>
/// Write bad matrices throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void WriteBadMatricesThrowsArgumentException()
{
var matrix = new LinearAlgebra.Single.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();
}
/// <summary>
/// Write <c>null</c> matrices throws <c>ArgumentNullException</c>.
/// </summary>
[Test]
public void WriteNullMatricesThrowsArgumentNullException()
{
var writer = new MatlabMatrixWriter("somefile4");
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new LinearAlgebra.Single.Matrix[] { null }, new[] { "matrix" }));
var matrix = new LinearAlgebra.Single.DenseMatrix(1, 1);
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrices(new LinearAlgebra.Single.Matrix[] { matrix }, null));
writer.Dispose();
}
/// <summary>
/// Can write double matrices.
/// </summary>
[Test]
public void CanWriteDoubleMatrices()
{
var mat1 = new LinearAlgebra.Double.DenseMatrix(5, 3);
for (var i = 0; i < mat1.ColumnCount; i++)
{
mat1[i, i] = i + .1;
}
var mat2 = new LinearAlgebra.Double.DenseMatrix(4, 5);
for (var i = 0; i < mat2.RowCount; i++)
{
mat2[i, i] = i + .1;
}
var mat3 = new LinearAlgebra.Double.SparseMatrix(5, 4);
mat3[0, 0] = 1.1;
mat3[0, 2] = 2.2;
mat3[4, 3] = 3.3;
var mat4 = new LinearAlgebra.Double.SparseMatrix(3, 5);
mat4[0, 0] = 1.1;
mat4[0, 2] = 2.2;
mat4[2, 4] = 3.3;
var write = new LinearAlgebra.Double.Matrix[] { mat1, mat2, mat3, mat4 };
var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" };
if (File.Exists("testd.mat"))
{
File.Delete("testd.mat");
}
var writer = new MatlabMatrixWriter("testd.mat");
writer.WriteMatrices(write, names);
writer.Dispose();
var reader = new MatlabMatrixReader<double>("testd.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));
}
}
/// <summary>
/// Can write float matrices.
/// </summary>
[Test]
public void CanWriteFloatMatrices()
{
var mat1 = new LinearAlgebra.Single.DenseMatrix(5, 3);
for (var i = 0; i < mat1.ColumnCount; i++)
{
mat1[i, i] = i + .1f;
}
var mat2 = new LinearAlgebra.Single.DenseMatrix(4, 5);
for (var i = 0; i < mat2.RowCount; i++)
{
mat2[i, i] = i + .1f;
}
var mat3 = new LinearAlgebra.Single.SparseMatrix(5, 4);
mat3[0, 0] = 1.1f;
mat3[0, 2] = 2.2f;
mat3[4, 3] = 3.3f;
var mat4 = new LinearAlgebra.Single.SparseMatrix(3, 5);
mat4[0, 0] = 1.1f;
mat4[0, 2] = 2.2f;
mat4[2, 4] = 3.3f;
var write = new LinearAlgebra.Single.Matrix[] { mat1, mat2, mat3, mat4 };
var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" };
if (File.Exists("tests.mat"))
{
File.Delete("tests.mat");
}
var writer = new MatlabMatrixWriter("tests.mat");
writer.WriteMatrices(write, names);
writer.Dispose();
var reader = new MatlabMatrixReader<float>("tests.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));
}
}
/// <summary>
/// Can write complex32 matrices.
/// </summary>
[Test]
public void CanWriteComplex32Matrices()
{
var mat1 = new LinearAlgebra.Complex32.DenseMatrix(5, 3);
for (var i = 0; i < mat1.ColumnCount; i++)
{
mat1[i, i] = new Complex32(i + .1f, i + .1f);
}
var mat2 = new LinearAlgebra.Complex32.DenseMatrix(4, 5);
for (var i = 0; i < mat2.RowCount; i++)
{
mat2[i, i] = new Complex32(i + .1f, i + .1f);
}
var mat3 = new LinearAlgebra.Complex32.SparseMatrix(5, 4);
mat3[0, 0] = new Complex32(1.1f, 1.1f);
mat3[0, 2] = new Complex32(2.2f, 2.2f);
mat3[4, 3] = new Complex32(3.3f, 3.3f);
var mat4 = new LinearAlgebra.Complex32.SparseMatrix(3, 5);
mat4[0, 0] = new Complex32(1.1f, 1.1f);
mat4[0, 2] = new Complex32(2.2f, 2.2f);
mat4[2, 4] = new Complex32(3.3f, 3.3f);
var write = new LinearAlgebra.Complex32.Matrix[] { mat1, mat2, mat3, mat4 };
var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" };
if (File.Exists("testc.mat"))
{
File.Delete("testc.mat");
}
var writer = new MatlabMatrixWriter("testc.mat");
writer.WriteMatrices(write, names);
writer.Dispose();
var reader = new MatlabMatrixReader<Complex32>("testc.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));
}
}
/// <summary>
/// Can write complex matrices.
/// </summary>
[Test]
public void CanWriteComplexMatrices()
{
var mat1 = new LinearAlgebra.Complex.DenseMatrix(5, 3);
for (var i = 0; i < mat1.ColumnCount; i++)
{
mat1[i, i] = new Complex(i + .1, i + .1);
}
var mat2 = new LinearAlgebra.Complex.DenseMatrix(4, 5);
for (var i = 0; i < mat2.RowCount; i++)
{
mat2[i, i] = new Complex(i + .1, i + .1);
}
var mat3 = new LinearAlgebra.Complex.SparseMatrix(5, 4);
mat3[0, 0] = new Complex(1.1, 1.1);
mat3[0, 2] = new Complex(2.2, 2.2);
mat3[4, 3] = new Complex(3.3, 3.3);
var mat4 = new LinearAlgebra.Complex.SparseMatrix(3, 5);
mat4[0, 0] = new Complex(1.1, 1.1);
mat4[0, 2] = new Complex(2.2, 2.2);
mat4[2, 4] = new Complex(3.3, 3.3);
var write = new LinearAlgebra.Complex.Matrix[] { mat1, mat2, mat3, mat4 };
var names = new[] { "mat1", "dense_matrix_2", "s1", "sparse2" };
if (File.Exists("testz.mat"))
{
File.Delete("testz.mat");
}
var writer = new MatlabMatrixWriter("testz.mat");
writer.WriteMatrices(write, names);
writer.Dispose();
var reader = new MatlabMatrixReader<Complex>("testz.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));
}
}
/// <summary>
/// Write bad matrix throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void WriteBadMatrixThrowsArgumentException()
{
var matrix = new LinearAlgebra.Single.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();
}
/// <summary>
/// Write <c>null</c> matrix throws <c>ArgumentNullException</c>.
/// </summary>
[Test]
public void WriteNullMatrixThrowsArgumentNullException()
{
var writer = new MatlabMatrixWriter("somefile2");
Assert.Throws<ArgumentNullException>(() => writer.WriteMatrix<double>(null, "matrix"));
writer.Dispose();
}
}
}

36
src/DataUnitTests/Properties/AssemblyInfo.cs

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NUnitTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NUnitTests")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bb41bee6-eb4c-48c9-8edd-7a5ae2422567")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

251
src/DataUnitTests/Text/DelimitedReaderTests.cs

@ -0,0 +1,251 @@
// <copyright file="DelimitedReaderTests.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-2013 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.Globalization;
using System.IO;
using System.Numerics;
using System.Text;
using NUnit.Framework;
using MathNet.Numerics.Data.Text;
namespace MathNet.Numerics.Data.UnitTests.Text
{
/// <summary>
/// Delimited reader tests.
/// </summary>
[TestFixture]
public class DelimitedReaderTests
{
/// <summary>
/// Can parse comma delimited data.
/// </summary>
[Test]
public void CanParseCommaDelimitedData()
{
var data = "a,b,c" + Environment.NewLine
+ "1" + Environment.NewLine
+ "\"2.2\",0.3e1" + Environment.NewLine
+ "'4',5,6" + Environment.NewLine;
var reader = new DelimitedReader
{
Delimiter = ",",
HasHeaderRow = true,
FormatProvider = CultureInfo.InvariantCulture
};
var matrix = reader.ReadMatrix<double>(new MemoryStream(Encoding.UTF8.GetBytes(data)));
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0, matrix[0, 0]);
Assert.AreEqual(0.0, matrix[0, 1]);
Assert.AreEqual(0.0, matrix[0, 2]);
Assert.AreEqual(2.2, matrix[1, 0]);
Assert.AreEqual(3.0, matrix[1, 1]);
Assert.AreEqual(0.0, matrix[1, 2]);
Assert.AreEqual(4.0, matrix[2, 0]);
Assert.AreEqual(5.0, matrix[2, 1]);
Assert.AreEqual(6.0, matrix[2, 2]);
}
/// <summary>
/// Can parse tab delimited data.
/// </summary>
[Test]
public void CanParseTabDelimitedData()
{
var data = "1" + Environment.NewLine
+ "\"2.2\"\t\t0.3e1" + Environment.NewLine
+ "'4'\t5\t6";
var matrix = DelimitedReader.ReadStream<float>(new MemoryStream(Encoding.UTF8.GetBytes(data)), delimiter: "\t", formatProvider: CultureInfo.InvariantCulture);
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0f, matrix[0, 0]);
Assert.AreEqual(0.0f, matrix[0, 1]);
Assert.AreEqual(0.0f, matrix[0, 2]);
Assert.AreEqual(2.2f, matrix[1, 0]);
Assert.AreEqual(3.0f, matrix[1, 1]);
Assert.AreEqual(0.0f, matrix[1, 2]);
Assert.AreEqual(4.0f, matrix[2, 0]);
Assert.AreEqual(5.0f, matrix[2, 1]);
Assert.AreEqual(6.0f, matrix[2, 2]);
}
/// <summary>
/// Can parse white space delimited data.
/// </summary>
[Test]
public void CanParseWhiteSpaceDelimitedData()
{
var data = "1" + Environment.NewLine
+ "\"2.2\" 0.3e1" + Environment.NewLine
+ "'4' 5 6" + Environment.NewLine;
var reader = new DelimitedReader
{
FormatProvider = CultureInfo.InvariantCulture
};
var matrix = reader.ReadMatrix<float>(new MemoryStream(Encoding.UTF8.GetBytes(data)));
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0f, matrix[0, 0]);
Assert.AreEqual(0.0f, matrix[0, 1]);
Assert.AreEqual(0.0f, matrix[0, 2]);
Assert.AreEqual(2.2f, matrix[1, 0]);
Assert.AreEqual(3.0f, matrix[1, 1]);
Assert.AreEqual(0.0f, matrix[1, 2]);
Assert.AreEqual(4.0f, matrix[2, 0]);
Assert.AreEqual(5.0f, matrix[2, 1]);
Assert.AreEqual(6.0f, matrix[2, 2]);
}
/// <summary>
/// Can parse period delimited data.
/// </summary>
[Test]
public void CanParsePeriodDelimitedData()
{
var data = "a.b.c" + Environment.NewLine
+ "1" + Environment.NewLine
+ "\"2,2\".0,3e1" + Environment.NewLine
+ "'4,0'.5,0.6,0" + Environment.NewLine;
var reader = new DelimitedReader
{
Delimiter = ".",
HasHeaderRow = true,
FormatProvider = new CultureInfo("tr-TR")
};
var matrix = reader.ReadMatrix<double>(new MemoryStream(Encoding.UTF8.GetBytes(data)));
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0, matrix[0, 0]);
Assert.AreEqual(0.0, matrix[0, 1]);
Assert.AreEqual(0.0, matrix[0, 2]);
Assert.AreEqual(2.2, matrix[1, 0]);
Assert.AreEqual(3.0, matrix[1, 1]);
Assert.AreEqual(0.0, matrix[1, 2]);
Assert.AreEqual(4.0, matrix[2, 0]);
Assert.AreEqual(5.0, matrix[2, 1]);
Assert.AreEqual(6.0, matrix[2, 2]);
}
/// <summary>
/// Can parse comma delimited complex data.
/// </summary>
[Test]
public void CanParseComplexCommaDelimitedData()
{
var data = "a,b,c" + Environment.NewLine
+ "(1,2)" + Environment.NewLine
+ "\"2.2\",0.3e1" + Environment.NewLine
+ "'(4,-5)',5,6" + Environment.NewLine;
var matrix = DelimitedReader.Read<Complex>(new StringReader(data), delimiter: ",", hasHeaders: true, formatProvider: CultureInfo.InvariantCulture);
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0, matrix[0, 0].Real);
Assert.AreEqual(2.0, matrix[0, 0].Imaginary);
Assert.AreEqual((Complex) 0.0, matrix[0, 1]);
Assert.AreEqual((Complex) 0.0, matrix[0, 2]);
Assert.AreEqual((Complex) 2.2, matrix[1, 0]);
Assert.AreEqual((Complex) 3.0, matrix[1, 1]);
Assert.AreEqual((Complex) 0.0, matrix[1, 2]);
Assert.AreEqual(4.0, matrix[2, 0].Real);
Assert.AreEqual(-5.0, matrix[2, 0].Imaginary);
Assert.AreEqual((Complex) 5.0, matrix[2, 1]);
Assert.AreEqual((Complex) 6.0, matrix[2, 2]);
}
/// <summary>
/// Can parse comma delimited complex data.
/// </summary>
[Test]
public void CanParseComplex32CommaDelimitedData()
{
var data = "a,b,c" + Environment.NewLine
+ "(1,2)" + Environment.NewLine
+ "\"2.2\",0.3e1" + Environment.NewLine
+ "'(4,-5)',5,6" + Environment.NewLine;
var reader = new DelimitedReader
{
Delimiter = ",",
HasHeaderRow = true,
FormatProvider = CultureInfo.InvariantCulture
};
var matrix = reader.ReadMatrix<Complex32>(new MemoryStream(Encoding.UTF8.GetBytes(data)));
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0f, matrix[0, 0].Real);
Assert.AreEqual(2.0f, matrix[0, 0].Imaginary);
Assert.AreEqual((Complex32)0.0f, matrix[0, 1]);
Assert.AreEqual((Complex32)0.0f, matrix[0, 2]);
Assert.AreEqual((Complex32)2.2f, matrix[1, 0]);
Assert.AreEqual((Complex32)3.0f, matrix[1, 1]);
Assert.AreEqual((Complex32)0.0f, matrix[1, 2]);
Assert.AreEqual(4.0f, matrix[2, 0].Real);
Assert.AreEqual(-5.0f, matrix[2, 0].Imaginary);
Assert.AreEqual((Complex32)5.0f, matrix[2, 1]);
Assert.AreEqual((Complex32)6.0f, matrix[2, 2]);
}
/// <summary>
/// Can parse comma delimited sparse data.
/// </summary>
[Test]
public void CanParseSparseCommaDelimitedData()
{
var data = "a,b,c" + Environment.NewLine
+ "1" + Environment.NewLine
+ "\"2.2\",0.3e1" + Environment.NewLine
+ "'4',0,6" + Environment.NewLine;
var matrix = DelimitedReader.Read<double>(new StringReader(data), true, ",", true, CultureInfo.InvariantCulture);
Assert.IsTrue(matrix is LinearAlgebra.Double.SparseMatrix);
Assert.AreEqual(3, matrix.RowCount);
Assert.AreEqual(3, matrix.ColumnCount);
Assert.AreEqual(1.0, matrix[0, 0]);
Assert.AreEqual(0.0, matrix[0, 1]);
Assert.AreEqual(0.0, matrix[0, 2]);
Assert.AreEqual(2.2, matrix[1, 0]);
Assert.AreEqual(3.0, matrix[1, 1]);
Assert.AreEqual(0.0, matrix[1, 2]);
Assert.AreEqual(4.0, matrix[2, 0]);
Assert.AreEqual(0.0, matrix[2, 1]);
Assert.AreEqual(6.0, matrix[2, 2]);
}
}
}

171
src/DataUnitTests/Text/DelimitedWriterTests.cs

@ -0,0 +1,171 @@
// <copyright file="DelimitedWriterTests.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-2013 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.Globalization;
using System.IO;
using System.Numerics;
using MathNet.Numerics.Data.Text;
using MathNet.Numerics.LinearAlgebra.Double;
using NUnit.Framework;
namespace MathNet.Numerics.Data.UnitTests.Text
{
/// <summary>
/// Delimited writer tests.
/// </summary>
[TestFixture]
public class DelimitedWriterTests
{
[Test]
public void CanWriteCommaDelimitedComplex32Data()
{
var matrix =
LinearAlgebra.Complex32.DenseMatrix.OfArray(new[,]
{
{new Complex32(1.1f, 1.1f), new Complex32(2.2f, 2.2f), new Complex32(3.3f, 3.3f)},
{new Complex32(4.4f, 4.4f), new Complex32(5.5f, 5.5f), new Complex32(6.6f, 6.6f)},
{new Complex32(7.7f, 7.7f), new Complex32(8.8f, 8.8f), new Complex32(9.9f, 9.9f)}
});
var writer = new DelimitedWriter(",")
{
FormatProvider = CultureInfo.InvariantCulture
};
var stream = new MemoryStream();
writer.WriteMatrix(matrix, stream);
var data = stream.ToArray();
var reader = new StreamReader(new MemoryStream(data));
var text = reader.ReadToEnd();
var expected = "(1.1, 1.1),(2.2, 2.2),(3.3, 3.3)" + Environment.NewLine
+ "(4.4, 4.4),(5.5, 5.5),(6.6, 6.6)" + Environment.NewLine
+ "(7.7, 7.7),(8.8, 8.8),(9.9, 9.9)";
Assert.AreEqual(expected, text);
}
[Test]
public void CanWriteCommaDelimitedComplexData()
{
var matrix =
LinearAlgebra.Complex.DenseMatrix.OfArray(new[,]
{
{new Complex(1.1, 1.1), new Complex(2.2, 2.2), new Complex(3.3, 3.3)},
{new Complex(4.4, 4.4), new Complex(5.5, 5.5), new Complex(6.6, 6.6)},
{new Complex(7.7, 7.7), new Complex(8.8, 8.8), new Complex(9.9, 9.9)}
});
var writer = new DelimitedWriter(",")
{
FormatProvider = CultureInfo.InvariantCulture
};
var stream = new MemoryStream();
writer.WriteMatrix(matrix, stream);
var data = stream.ToArray();
var reader = new StreamReader(new MemoryStream(data));
var text = reader.ReadToEnd();
var expected = "(1.1, 1.1),(2.2, 2.2),(3.3, 3.3)" + Environment.NewLine
+ "(4.4, 4.4),(5.5, 5.5),(6.6, 6.6)" + Environment.NewLine
+ "(7.7, 7.7),(8.8, 8.8),(9.9, 9.9)";
Assert.AreEqual(expected, text);
}
[Test]
public void CanWriteCommaDelimitedDoubleData()
{
var matrix = DenseMatrix.OfArray(new[,] {{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}, {7.7, 8.8, 9.9}});
var writer = new DelimitedWriter(",")
{
FormatProvider = CultureInfo.InvariantCulture
};
var stream = new MemoryStream();
writer.WriteMatrix(matrix, stream);
var data = stream.ToArray();
var reader = new StreamReader(new MemoryStream(data));
var text = reader.ReadToEnd();
var expected = @"1.1,2.2,3.3" + Environment.NewLine
+ "4.4,5.5,6.6" + Environment.NewLine
+ "7.7,8.8,9.9";
Assert.AreEqual(expected, text);
}
[Test]
public void CanWriteCommaDelimitedSingleData()
{
var matrix = LinearAlgebra.Single.DenseMatrix.OfArray(new[,] {{1.1f, 2.2f, 3.3f}, {4.4f, 5.5f, 6.6f}, {7.7f, 8.8f, 9.9f}});
var writer = new DelimitedWriter(",")
{
FormatProvider = CultureInfo.InvariantCulture
};
var stream = new MemoryStream();
writer.WriteMatrix(matrix, stream);
var data = stream.ToArray();
var reader = new StreamReader(new MemoryStream(data));
var text = reader.ReadToEnd();
var expected = @"1.1,2.2,3.3" + Environment.NewLine
+ "4.4,5.5,6.6" + Environment.NewLine
+ "7.7,8.8,9.9";
Assert.AreEqual(expected, text);
}
/// <summary>
/// Can write period delimited data.
/// </summary>
[Test]
public void CanWritePeriodDelimitedData()
{
var matrix = DenseMatrix.OfArray(new[,] {{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}, {7.7, 8.8, 9.9}});
var stream = new MemoryStream();
DelimitedWriter.WriteStream(matrix, stream, ".", formatProvider: new CultureInfo("tr-TR"));
var data = stream.ToArray();
var reader = new StreamReader(new MemoryStream(data));
var text = reader.ReadToEnd();
var expected = @"1,1.2,2.3,3" + Environment.NewLine
+ "4,4.5,5.6,6" + Environment.NewLine
+ "7,7.8,8.9,9";
Assert.AreEqual(expected, text);
}
/// <summary>
/// Can write space delimited data.
/// </summary>
[Test]
public void CanWriteSpaceDelimitedData()
{
var matrix = SparseMatrix.OfArray(new[,] {{1.1, 0, 0}, {0, 5.5, 0}, {0, 0, 9.9}});
var stream = new MemoryStream();
DelimitedWriter.WriteStream(matrix, stream, " ");
var data = stream.ToArray();
var reader = new StreamReader(new MemoryStream(data));
var text = reader.ReadToEnd();
var expected = @"1.1 0 0" + Environment.NewLine
+ "0 5.5 0" + Environment.NewLine
+ "0 0 9.9";
Assert.AreEqual(expected, text);
}
}
}

159
src/DataUnitTests/Text/MatrixMarketReaderTests.cs

@ -0,0 +1,159 @@
// <copyright file="MatrixMarketReaderTests.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-2013 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 System.Text;
using MathNet.Numerics.Data.Text;
using NUnit.Framework;
namespace MathNet.Numerics.Data.UnitTests.Text
{
[TestFixture]
public class MatrixMarketReaderTests
{
[Test]
public void CanReadFudao007AsDouble()
{
var m = MatrixMarketReader.ReadMatrix<double>("./data/MatrixMarket/fidap007.mtx");
Assert.IsInstanceOf<LinearAlgebra.Double.SparseMatrix>(m);
Assert.AreEqual(1633, m.RowCount);
Assert.AreEqual(1633, m.ColumnCount);
Assert.GreaterOrEqual(54487, ((LinearAlgebra.Double.SparseMatrix) m).NonZerosCount);
Assert.Less(46000, ((LinearAlgebra.Double.SparseMatrix) m).NonZerosCount);
Assert.AreEqual(-6.8596032449032e+06d, m[1604, 1631]);
Assert.AreEqual(-9.1914585107976e+06d, m[1616, 1628]);
Assert.AreEqual(7.9403870156486e+07d, m[905, 726]);
}
[Test]
public void CanReadFudao007AsSingle()
{
var m = MatrixMarketReader.ReadMatrix<float>("./data/MatrixMarket/fidap007.mtx");
Assert.IsInstanceOf<LinearAlgebra.Single.SparseMatrix>(m);
Assert.AreEqual(1633, m.RowCount);
Assert.AreEqual(1633, m.ColumnCount);
Assert.GreaterOrEqual(54487, ((LinearAlgebra.Single.SparseMatrix)m).NonZerosCount);
Assert.Less(46000, ((LinearAlgebra.Single.SparseMatrix)m).NonZerosCount);
Assert.AreEqual(-6.8596032449032e+06f, m[1604, 1631]);
Assert.AreEqual(-9.1914585107976e+06f, m[1616, 1628]);
Assert.AreEqual(7.9403870156486e+07f, m[905, 726]);
}
[Test]
public void CanReadFudao007AsComplex()
{
var m = MatrixMarketReader.ReadMatrix<Complex>("./data/MatrixMarket/fidap007.mtx");
Assert.IsInstanceOf<LinearAlgebra.Complex.SparseMatrix>(m);
Assert.AreEqual(1633, m.RowCount);
Assert.AreEqual(1633, m.ColumnCount);
Assert.GreaterOrEqual(54487, ((LinearAlgebra.Complex.SparseMatrix)m).NonZerosCount);
Assert.Less(46000, ((LinearAlgebra.Complex.SparseMatrix)m).NonZerosCount);
Assert.AreEqual(-6.8596032449032e+06d, m[1604, 1631].Real);
Assert.AreEqual(0.0d, m[1604, 1631].Imaginary);
Assert.AreEqual(-9.1914585107976e+06d, m[1616, 1628].Real);
Assert.AreEqual(0.0d, m[1616, 1628].Imaginary);
Assert.AreEqual(7.9403870156486e+07d, m[905, 726].Real);
Assert.AreEqual(0.0d, m[905, 726].Imaginary);
}
[Test]
public void CanReadFudao007AsComplex32()
{
var m = MatrixMarketReader.ReadMatrix<Complex32>("./data/MatrixMarket/fidap007.mtx");
Assert.IsInstanceOf<LinearAlgebra.Complex32.SparseMatrix>(m);
Assert.AreEqual(1633, m.RowCount);
Assert.AreEqual(1633, m.ColumnCount);
Assert.GreaterOrEqual(54487, ((LinearAlgebra.Complex32.SparseMatrix) m).NonZerosCount);
Assert.Less(46000, ((LinearAlgebra.Complex32.SparseMatrix) m).NonZerosCount);
Assert.AreEqual(-6.8596032449032e+06f, m[1604, 1631].Real);
Assert.AreEqual(0.0f, m[1604, 1631].Imaginary);
Assert.AreEqual(-9.1914585107976e+06f, m[1616, 1628].Real);
Assert.AreEqual(0.0f, m[1616, 1628].Imaginary);
Assert.AreEqual(7.9403870156486e+07f, m[905, 726].Real);
Assert.AreEqual(0.0f, m[905, 726].Imaginary);
}
[Test]
public void CanReadSparseHermitianComplexMatrix()
{
var sb = new StringBuilder();
sb.AppendLine("%%MatrixMarket matrix coordinate complex hermitian");
sb.AppendLine("5 5 7");
sb.AppendLine("1 1 1.0 0");
sb.AppendLine("2 2 10.5 0");
sb.AppendLine("4 2 250.5 22.22");
sb.AppendLine("3 3 1.5e-2 0");
sb.AppendLine("4 4 -2.8e2 0.0");
sb.AppendLine("5 5 12. 0.");
sb.AppendLine("5 4 0 33.32");
var m = MatrixMarketReader.ReadMatrix<Complex>(new StringReader(sb.ToString()));
Assert.IsInstanceOf<LinearAlgebra.Complex.SparseMatrix>(m);
Assert.AreEqual(5, m.RowCount);
Assert.AreEqual(5, m.ColumnCount);
Assert.AreEqual(9, ((LinearAlgebra.Complex.SparseMatrix)m).NonZerosCount);
Assert.AreEqual(1.0d, m[0, 0].Real);
Assert.AreEqual(10.5d, m[1, 1].Real);
Assert.AreEqual(250.5d, m[3, 1].Real);
Assert.AreEqual(22.22d, m[3, 1].Imaginary);
Assert.AreEqual(-22.22d, m[1, 3].Imaginary);
Assert.AreEqual(-280d, m[3, 3].Real);
Assert.AreEqual(0d, m[4, 3].Real);
Assert.AreEqual(33.32d, m[4, 3].Imaginary);
Assert.AreEqual(-33.32d, m[3, 4].Imaginary);
}
[Test]
public void CanReadDenseSkewSymmetricMatrix()
{
/* 0 1 2 3
1 0 6 7
2 6 0 11
3 7 11 0 */
var sb = new StringBuilder();
sb.AppendLine("%%MatrixMarket matrix array integer skew-symmetric");
sb.AppendLine("4 4");
sb.Append("1\n2\n3\n6\n7\n11");
var m = MatrixMarketReader.ReadMatrix<double>(new StringReader(sb.ToString()));
Assert.IsInstanceOf<LinearAlgebra.Double.DenseMatrix>(m);
Assert.AreEqual(4, m.RowCount);
Assert.AreEqual(4, m.ColumnCount);
Assert.AreEqual(0.0, m.Diagonal().InfinityNorm());
Assert.AreEqual(0d, m[0, 0]);
Assert.AreEqual(1d, m[1, 0]);
Assert.AreEqual(1d, m[0, 1]);
Assert.AreEqual(7d, m[3, 1]);
Assert.AreEqual(7d, m[1, 3]);
}
}
}

72
src/DataUnitTests/Text/MatrixMarketWriterTests.cs

@ -0,0 +1,72 @@
// <copyright file="MatrixMarketWriterTests.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-2013 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.IO;
using System.Numerics;
using MathNet.Numerics.Data.Text;
using NUnit.Framework;
namespace MathNet.Numerics.Data.UnitTests.Text
{
[TestFixture]
public class MatrixMarketWriterTests
{
[Test]
public void CanWriteRealDenseMatrix()
{
var m = LinearAlgebra.Double.DenseMatrix.OfArray(new[,] {{1.5d, 2}, {3, 4}, {5, 6}});
const string expected = "%%MatrixMarket matrix array real general\n3 2\n1.5\n3\n5\n2\n4\n6\n";
var writer = new StringWriter();
MatrixMarketWriter.WriteMatrix(writer, m);
Assert.AreEqual(expected.Replace("\n",Environment.NewLine), writer.ToString());
}
[Test]
public void CanWriteComplexDenseMatrix()
{
var m = LinearAlgebra.Complex.DenseMatrix.OfArray(new[,] { { new Complex(1.5, 0), new Complex(0, 1) }, { new Complex(4, 5), new Complex(6, 7) } });
const string expected = "%%MatrixMarket matrix array complex general\n2 2\n1.5 0\n4 5\n0 1\n6 7\n";
var writer = new StringWriter();
MatrixMarketWriter.WriteMatrix(writer, m);
Assert.AreEqual(expected.Replace("\n", Environment.NewLine), writer.ToString());
}
[Test]
public void CanWriteRealSparseMatrix()
{
var m = LinearAlgebra.Double.SparseMatrix.OfArray(new[,] { { 1.5d, 2 }, { 0, 4 }, { 5, 0 } });
const string expected = "%%MatrixMarket matrix coordinate real general\n3 2 4\n1 1 1.5\n1 2 2\n2 2 4\n3 1 5\n";
var writer = new StringWriter();
MatrixMarketWriter.WriteMatrix(writer, m);
Assert.AreEqual(expected.Replace("\n", Environment.NewLine), writer.ToString());
}
}
}

122
src/DataUnitTests/UnitTests.csproj

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6B0247F6-B332-41BC-B100-C0E5509EE612}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MathNet.Numerics.Data.UnitTests</RootNamespace>
<AssemblyName>MathNet.Numerics.Data.UnitTests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\out\test-debug\Net40\</OutputPath>
<IntermediateOutputPath>..\..\obj\test-debug\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\test-debug\Net40\</BaseIntermediateOutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\out\test\Net40\</OutputPath>
<IntermediateOutputPath>..\..\obj\test\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\test\Net40\</BaseIntermediateOutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssertHelpers.cs" />
<Compile Include="Matlab\MatlabReaderTests.cs" />
<Compile Include="Matlab\MatlabWriterTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Text\DelimitedReaderTests.cs" />
<Compile Include="Text\DelimitedWriterTests.cs" />
<Compile Include="Text\MatrixMarketReaderTests.cs" />
<Compile Include="Text\MatrixMarketWriterTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\data\Matlab\A.mat">
<Link>data\matlab\A.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\collection-nocompress.mat">
<Link>data\matlab\collection-nocompress.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\collection.mat">
<Link>data\matlab\collection.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\complex.mat">
<Link>data\matlab\complex.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\sparse-large.mat">
<Link>data\matlab\sparse-large.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\sparse-small.mat">
<Link>data\matlab\sparse-small.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\sparse_complex.mat">
<Link>data\matlab\sparse_complex.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\Matlab\v.mat">
<Link>data\matlab\v.mat</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\..\data\MatrixMarket\fidap007.mtx">
<Link>data\MatrixMarket\fidap007.mtx</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Data\Matlab\Matlab.csproj">
<Project>{550fb330-c86f-4c9d-9b4c-6d830ceb7520}</Project>
<Name>Matlab</Name>
</ProjectReference>
<ProjectReference Include="..\Data\Text\Text.csproj">
<Project>{9d3a08e1-6b96-4552-a535-412e589b3264}</Project>
<Name>Text</Name>
</ProjectReference>
<ProjectReference Include="..\Numerics\Numerics.csproj">
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

5
src/DataUnitTests/packages.config

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MathNet.Numerics" version="3.0.0-beta03" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
</packages>
Loading…
Cancel
Save