Browse Source

Added initial DenseMatrix implementation.

Ported F# Matrix and DenseMatrix interface.
la-knuth
Jurgen Van Gael 17 years ago
parent
commit
7f23d8d912
  1. 127
      src/FSharp/DenseMatrix.fs
  2. 1
      src/FSharp/FSharp.fsproj
  3. 2
      src/FSharp/Main.fs
  4. 147
      src/FSharpUnitTests/Program.fs
  5. 164
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  6. 1
      src/Numerics/Numerics.csproj
  7. 3
      src/UnitTests/DistributionTests/CommonDistributionTests.cs
  8. 52
      src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs
  9. 162
      src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs
  10. 2
      src/UnitTests/UnitTests.csproj

127
src/FSharp/DenseMatrix.fs

@ -0,0 +1,127 @@
// <copyright file="DenseMatrix.fs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 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.LinearAlgebra.Double
open MathNet.Numerics.LinearAlgebra
/// A module which implements functional dense vector operations.
module DenseMatrix =
/// Initialize a matrix by calling a construction function for every element.
let inline init (n: int) (m: int) f =
let A = new DenseMatrix(n,m)
for i=0 to n-1 do
for j=0 to m-1 do
A.[i,j] <- f i j
A
/// Create the identity matrix.
let inline identity (n:int) =
let A = new DenseMatrix(n, n, 0.0)
for i=0 to n-1 do
A.[i,i] <- 1.0
A
/// Create a matrix from a list of float lists. Every list in the master list specifies a row.
let inline of_list (fll: float list list) =
let n = List.length fll
let m = List.length (List.hd fll)
let A = DenseMatrix(n,m)
fll |> List.iteri (fun i fl ->
if (List.length fl) <> m then failwith "Each subrow must be of the same length." else
List.iteri (fun j f -> A.[i,j] <- f) fl)
A
/// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row.
let inline of_seq (fss: #seq<#seq<float>>) =
let n = Seq.length fss
let m = Seq.length (Seq.hd fss)
let A = DenseMatrix(n,m)
fss |> Seq.iteri (fun i fs ->
if (Seq.length fs) <> m then failwith "Each subrow must be of the same length." else
Seq.iteri (fun j f -> A.[i,j] <- f) fs)
A
/// Create a matrix from a 2D array of floating point numbers.
let inline of_array2 (arr: float[,]) = new DenseMatrix(arr)
/// Create a matrix with the given entries.
let inline init_dense (n: int) (m: int) (es: #seq<int * int * float>) =
let A = new DenseMatrix(n,m)
Seq.iter (fun (i,j,f) -> A.[i,j] <- f) es
A
/// Create a square matrix with constant diagonal entries.
let inline constDiag (n: int) (f: float) =
let A = new DenseMatrix(n,n)
for i=0 to n-1 do
A.[i,i] <- f
A
/// Create a square matrix with the vector elements on the diagonal.
let inline diag (v: #Vector) =
let n = v.Count
let A = new DenseMatrix(n,n)
for i=0 to n-1 do
A.[i,i] <- v.Item(i)
A
(*
/// Initialize a matrix by calling a construction function for every row.
let inline init_row (n: int) (m: int) (f: int -> #Vector) =
let A = new DenseMatrix(n,m)
for i=0 to n-1 do
let row = f i
if row.Count <> m then failwith "Row generator does not create rows of the appropriate size."
A.SetRow(i, row)
A
/// Initialize a matrix by calling a construction function for every column.
let inline init_col (n: int) (m: int) (f: int -> #Vector) =
let A = new DenseMatrix(n,m)
for i=0 to m-1 do
let col = f i
if col.Count <> n then failwith "Column generator does not create columns of the appropriate size."
A.SetColumn(i, col)
A
/// Create a 1xn dimensional matrix from a row vector.
let inline of_rowvector (v: #Vector) =
let n = v.Count
let A = new DenseMatrix(1, n)
A.SetRow(0, v)
A
/// Create an nx1 dimensional matrix from a column vector.
let inline of_vector (v: #Vector) =
let n = v.Count
let A = new DenseMatrix(n, 1)
A.SetColumn(0, v)
A*)

1
src/FSharp/FSharp.fsproj

@ -46,6 +46,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DenseVector.fs" />
<Compile Include="DenseMatrix.fs" />
<Compile Include="Vector.fs" />
<Compile Include="Main.fs" />
<Compile Include="Matrix.fs" />

2
src/FSharp/Main.fs

@ -34,7 +34,7 @@ open MathNet.Numerics.LinearAlgebra.Double
module FSharp =
/// Construct a dense matrix from a list of floating point numbers.
//let inline matrix (lst: list<list<float>>) = DenseMatrix.of_list lst :> Matrix
let inline matrix (lst: list<list<float>>) = DenseMatrix.of_list lst :> Matrix
/// Construct a dense vector from a list of floating point numbers.
let inline vector (lst: list<float>) = DenseVector.of_list lst :> Vector

147
src/FSharpUnitTests/Program.fs

@ -23,6 +23,153 @@ let DenseVectorTests =
spec "DenseVector.range"
(DenseVector.range 0 99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> float i |] ) ))
]
/// Unit tests for the vector type.
let VectorTests =
/// A small uniform vector.
let smallv = new DenseVector( [|0.3;0.3;0.3;0.3;0.3|] ) :> Vector
/// A large vector with increasingly large entries
let largev = new DenseVector( Array.init 100 (fun i -> float i / 100.0) ) :> Vector
specs "Vector" [
spec "Vector.to_array"
(Vector.to_array smallv |> should equal [|0.3;0.3;0.3;0.3;0.3|])
spec "Vector.to_list"
(Vector.to_list smallv |> should equal [0.3;0.3;0.3;0.3;0.3])
spec "Vector.mapInPlace"
( let w = smallv.Clone()
Vector.mapInPlace (fun x -> 2.0 * x) w
w |> should equal (2.0 * smallv))
spec "Vector.mapiInPlace"
( let w = largev.Clone()
Vector.mapiInPlace (fun i x -> float i / 100.0) w
w |> should equal (largev))
spec "Vector.addInPlace"
( let w = largev.Clone()
Vector.addInPlace w largev
w |> should equal (2.0 * largev))
spec "Vector.subInPlace"
( let w = largev.Clone()
Vector.subInPlace w largev
w |> should equal (0.0 * largev))
spec "Vector.map"
(Vector.map (fun x -> 2.0 * x) largev |> should equal (2.0 * largev))
spec "Vector.mapi"
(Vector.mapi (fun i x -> float i / 100.0) largev |> should equal largev)
spec "Vector.fold"
(Vector.fold (fun a b -> a + b) 0.0 smallv |> should equal 1.5)
spec "Vector.foldi"
(Vector.foldi (fun i a b -> a + b) 0.0 smallv |> should equal 1.5)
spec "Vector.forall"
(Vector.forall (fun x -> x = 0.3) smallv |> should equal true)
spec "Vector.exists"
(Vector.exists (fun x -> x = 0.3) smallv |> should equal true)
spec "Vector.foralli"
(Vector.foralli (fun i x -> x = 0.3 && i < 5) smallv |> should equal true)
spec "Vector.existsi"
(Vector.existsi (fun i x -> x = 0.3 && i = 2) smallv |> should equal true)
spec "Vector.scan"
(Vector.scan (fun acc x -> acc + x) smallv |> should approximately_vector_equal 14 (new DenseVector( [|0.3;0.6;0.9;1.2;1.5|] ) :> Vector) )
spec "Vector.scanBack"
(Vector.scanBack (fun x acc -> acc + x) smallv |> should approximately_vector_equal 14 (new DenseVector( [|1.5;1.2;0.9;0.6;0.3|] ) :> Vector) )
spec "Vector.reduce_left"
(Vector.reduce (fun acc x -> acc ** x) smallv |> should approximately_equal 14 0.990295218585507)
spec "Vector.reduce_right"
(Vector.reduceBack (fun x acc -> x ** acc) smallv |> should approximately_equal 14 0.488911287726319)
]
/// Unit tests for the matrix type.
let MatrixTests =
/// A small uniform vector.
let smallM = new DenseMatrix( Array2D.create 2 2 0.3 )
/// A large vector with increasingly large entries
let largeM = new DenseMatrix( Array2D.init 100 100 (fun i j -> float i * 100.0 + float j) )
specs "Matrix" [
spec "Matrix.fold"
(Matrix.fold (fun a b -> a + b) 0.0 smallM |> should equal 1.2)
spec "Matrix.foldi"
(Matrix.foldi (fun i j acc x -> acc + x + float (i+j)) 0.0 smallM |> should equal 5.2)
spec "Matrix.toArray2"
(Matrix.toArray2 smallM |> should equal (Array2D.create 2 2 0.3))
spec "Matrix.forall"
(Matrix.forall (fun x -> x = 0.3) smallM |> should equal true)
spec "Matrix.exists"
(Matrix.exists (fun x -> x = 0.5) smallM |> should equal false)
spec "Matrix.foralli"
(Matrix.foralli (fun i j x -> x = float i * 100.0 + float j) largeM |> should equal true)
spec "Matrix.existsi"
(Matrix.existsi (fun i j x -> x = float i * 100.0 + float j) largeM |> should equal true)
(*spec "Matrix.map"
(Matrix.map (fun x -> 2.0 * x) smallM |> should equal (2.0 * smallM))
spec "Matrix.mapi"
(Matrix.mapi (fun i j x -> float i * 100.0 + float j + x) largeM |> should equal (2.0 * largeM))
spec "Matrix.inplaceAssign"
( let N = smallM.Clone()
Matrix.inplaceAssign (fun i j -> 0.0) N
N |> should equal (0.0 * smallM))
spec "Matrix.inplaceMapi"
( let N = largeM.Clone()
Matrix.inplaceMapi (fun i j x -> 2.0 * (float i * 100.0 + float j) + x) N
N |> should equal (3.0 * largeM))*)
spec "Matrix.nonZeroEntries"
(Seq.length (Matrix.nonZeroEntries smallM) |> should equal 4)
spec "Matrix.sum"
(Matrix.sum smallM |> should equal 1.2)
spec "Matrix.foldCol"
(Matrix.foldCol (+) 0.0 largeM 0 |> should equal 495000.0)
spec "Matrix.foldRow"
(Matrix.foldRow (+) 0.0 largeM 0 |> should equal 4950.0)
spec "Matrix.foldByCol"
(Matrix.foldByCol (+) 0.0 smallM |> should equal (DenseVector.of_list [0.6;0.6] :> Vector))
spec "Matrix.foldByRow"
(Matrix.foldByRow (+) 0.0 smallM |> should equal (DenseVector.of_list [0.6;0.6] :> Vector))
]
/// Unit tests for the dense matrix type.
let DenseMatrixTests =
/// A small uniform vector.
let smallM = new DenseMatrix( Array2D.create 2 2 0.3 )
/// A large vector with increasingly large entries
let largeM = new DenseMatrix( Array2D.init 100 100 (fun i j -> float i * 100.0 + float j) )
specs "DenseMatrix" [
spec "DenseMatrix.init"
(DenseMatrix.init 100 100 (fun i j -> float i * 100.0 + float j) |> should equal largeM)
spec "DenseMatrix.identity"
(DenseMatrix.identity 10 |> should equal (DenseMatrix.init 10 10 (fun i j -> if i = j then 1.0 else 0.0)))
spec "DenseMatrix.of_list"
(DenseMatrix.of_list [[0.3;0.3];[0.3;0.3]] |> should equal smallM)
spec "DenseMatrix.of_seq"
(DenseMatrix.of_seq (Seq.of_list [[0.3;0.3];[0.3;0.3]]) |> should equal smallM)
spec "DenseMatrix.of_array2"
(DenseMatrix.of_array2 (Array2D.create 2 2 0.3) |> should equal smallM)
spec "DenseMatrix.init_dense"
(DenseMatrix.init_dense 100 100 (seq { for i in 0 .. 99 do
for j in 0 .. 99 -> (i,j, float i * 100.0 + float j)}) |> should equal largeM)
(*spec "DenseMatrix.constDiag"
(DenseMatrix.constDiag 100 2.0 |> should equal (2.0 * (DenseMatrix.identity 100)))
spec "DenseMatrix.diag"
(DenseMatrix.diag (new DenseVector(100, 2.0)) |> should equal (2.0 * (DenseMatrix.identity 100)))
spec "DenseMatrix.init_row"
(DenseMatrix.init_row 100 100 (fun i -> (DenseVector.init 100 (fun j -> float i * 100.0 + float j))) |> should equal largeM)
spec "DenseMatrix.init_col"
(DenseMatrix.init_col 100 100 (fun j -> (DenseVector.init 100 (fun i -> float i * 100.0 + float j))) |> should equal largeM)
spec "DenseMatrix.of_rowvector"
(DenseMatrix.of_rowvector (new DenseVector(10,3.0)) |> should equal ((new DenseMatrix(1,10,3.0))))
spec "DenseMatrix.of_vector"
(DenseMatrix.of_vector (new DenseVector(10,3.0)) |> should equal ((new DenseMatrix(10,1,3.0))))*)
]
/// Report on errors and success and exit.
printfn "F# Test Results:"

164
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -0,0 +1,164 @@
// <copyright file="DenseMatrix.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 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.LinearAlgebra.Double
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Algorithms;
using Algorithms.LinearAlgebra;
using NumberTheory;
using Properties;
using Threading;
/// <summary>
/// A Matrix class with dense storage.
/// </summary>
public class DenseMatrix : Matrix
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseMatrix"/> class. This matrix is square with a given size.
/// </summary>
/// <param name="order">the size of the square matrix.</param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseMatrix(int order)
: base(order)
{
Data = new double[order*order];
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseMatrix"/> class.
/// </summary>
/// <param name="rows">
/// The number of rows.
/// </param>
/// <param name="columns">
/// The number of columns.
/// </param>
public DenseMatrix(int rows, int columns)
: base(rows, columns)
{
Data = new double[rows * columns];
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseMatrix"/> class with all entries set to a particular value.
/// </summary>
/// <param name="rows">
/// The number of rows.
/// </param>
/// <param name="columns">
/// The number of columns.
/// </param
/// <param name="value">The value which we assign to each element of the matrix.</param>
public DenseMatrix(int rows, int columns, double value)
: base(rows, columns)
{
Data = new double[rows * columns];
for (int i = 0; i < Data.Length; i++)
{
Data[i] = value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseMatrix"/> class from a 2D array.
/// </summary>
/// <param name="array">The 2D array to create this matrix from.</param>
public DenseMatrix(double[,] array)
: base(array.GetLength(0), array.GetLength(1))
{
throw new NotImplementedException();
}
/// <summary>
/// Gets or sets the matrix's data.
/// </summary>
/// <value>The matrix's data.</value>
internal double[] Data
{
get;
private set;
}
/// <summary>
/// Creates a <strong>DenseMatrix</strong> for the given number of rows and columns.
/// </summary>
/// <param name="numberOfRows">
/// The number of rows.
/// </param>
/// <param name="numberOfColumns">
/// The number of columns.
/// </param>
/// <returns>
/// A <strong>DenseMatrix</strong> with the given dimensions.
/// </returns>
public override Matrix CreateMatrix(int numberOfRows, int numberOfColumns)
{
return new DenseMatrix(numberOfRows, numberOfColumns);
}
/// <summary>
/// Retrieves the requested element without range checking.
/// </summary>
/// <param name="row">
/// The row of the element.
/// </param>
/// <param name="column">
/// The column of the element.
/// </param>
/// <returns>
/// The requested element.
/// </returns>
public override double At(int row, int column)
{
return Data[column * RowCount + row];
}
/// <summary>
/// Sets the value of the given element.
/// </summary>
/// <param name="row">
/// The row of the element.
/// </param>
/// <param name="column">
/// The column of the element.
/// </param>
/// <param name="value">
/// The value to set the element to.
/// </param>
public override void At(int row, int column, double value)
{
Data[column * RowCount + row] = value;
}
}
}

1
src/Numerics/Numerics.csproj

@ -92,6 +92,7 @@
<Compile Include="Interpolation\IInterpolation.cs" />
<Compile Include="Interpolation\Interpolate.cs" />
<Compile Include="Interpolation\SplineBoundaryCondition.cs" />
<Compile Include="LinearAlgebra\Double\DenseMatrix.cs" />
<Compile Include="LinearAlgebra\Double\DenseVector.cs" />
<Compile Include="LinearAlgebra\Double\Matrix.cs" />
<Compile Include="LinearAlgebra\Double\Vector.cs" />

3
src/UnitTests/DistributionTests/CommonDistributionTests.cs

@ -41,7 +41,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests
[SetUp]
public void SetupDistributions()
{
dists = new IDistribution[7];
dists = new IDistribution[8];
dists[0] = new Beta(1.0, 1.0);
dists[1] = new ContinuousUniform(0.0, 1.0);
@ -50,6 +50,7 @@ namespace MathNet.Numerics.UnitTests.DistributionTests
dists[4] = new Bernoulli(0.6);
dists[5] = new Weibull(1.0, 1.0);
dists[6] = new DiscreteUniform(1, 10);
dists[7] = new LogNormal(1.0, 1.0);
}
[Test]

52
src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs

@ -0,0 +1,52 @@
using System.Collections.Generic;
using MbUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
using LinearAlgebra.Double;
public class DenseMatrixTests : MatrixTests
{
protected override Matrix CreateMatrix(int rows, int columns)
{
return new DenseMatrix(rows, columns);
}
protected override Matrix CreateMatrix(double[,] data)
{
return new DenseMatrix(data);
}
[Test]
[Row("Singular3x3")]
[Row("Singular3x3")]
[Row("Square3x3")]
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
public void CanCreateMatrixFromArray(string name)
{
var matrix = new DenseMatrix(testData[name]);
for (var i = 0; i < testData[name].GetLength(0); i++)
{
for (var j = 0; j < testData[name].GetLength(0); j++)
{
Assert.AreEqual(testData[name][i,j], matrix[i,j]);
}
}
}
[Test]
public void CanCreateMatrixWithUniformValues()
{
var matrix = new DenseMatrix(10, 10, 10.0);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.ColumnCount; j++)
{
Assert.AreEqual(matrix[i, j], 10.0);
}
}
}
}
}

162
src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using MathNet.Numerics.LinearAlgebra.Double;
using MbUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
public abstract partial class MatrixTests
{
protected Dictionary<string, double[,]> testData;
protected Dictionary<string, Matrix> testMatrices;
protected abstract Matrix CreateMatrix(int rows, int columns);
protected abstract Matrix CreateMatrix(double[,] data);
[SetUp]
public void SetupDistributions()
{
testData.Add("Singular3x3", new double[,] { { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 } });
testData.Add("Square3x3", new double[,] { { -1.1, -2.2, -3.3 }, { 0, 1.1, 2.2 }, { -4.4, 5.5, 6.6 } });
testData.Add("Square4x4", new double[,] { { -1.1, -2.2, -3.3, -4.4 }, { 0, 1.1, 2.2, 3.3 }, { -4.4, 5.5, 6.6, -7.7 } });
testData.Add("Tall3x2", new double[,] { { -1.1, -2.2 }, { 0, 1.1 }, { -4.4, 5.5 } });
testData.Add("Wide2x3", new double[,] { { -1.1, -2.2, -3.3 }, { 0, 1.1, 2.2 } });
foreach(var name in testData.Keys)
{
testMatrices.Add(name, CreateMatrix(testData[name]));
}
}
[Test]
[Row("Singular3x3")]
[Row("Square3x3")]
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
[MultipleAsserts]
public void CanCloneMatrix(string name)
{
var matrix = CreateMatrix(testData[name]);
var clone = matrix.Clone();
Assert.AreNotSame(matrix, clone);
Assert.AreEqual(matrix.RowCount, clone.RowCount);
Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.RowCount; j++)
{
Assert.AreEqual(matrix[i,j], clone[i,j]);
}
}
}
[Test]
[Row("Singular3x3")]
[Row("Square3x3")]
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
[MultipleAsserts]
public void CanCloneMatrixUsingICloneable(string name)
{
var matrix = CreateMatrix(testData[name]);
var clone = (Matrix)((ICloneable)matrix).Clone();
Assert.AreNotSame(matrix, clone);
Assert.AreEqual(matrix.RowCount, clone.RowCount);
Assert.AreEqual(matrix.ColumnCount, clone.ColumnCount);
for (var i = 0; i < matrix.RowCount; i++)
{
for (var j = 0; j < matrix.RowCount; j++)
{
Assert.AreEqual(matrix[i, j], clone[i, j]);
}
}
}
[Test]
[Ignore]
public void CanConvertVectorToString()
{
}
[Test]
public void CanCreateMatrix()
{
var expected = CreateMatrix(5, 6);
var actual = expected.CreateMatrix(5, 6);
Assert.AreEqual(expected.GetType(), actual.GetType(), "Matrices are same type.");
}
[Test]
[Row("Singular3x3")]
[Row("Square3x3")]
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
[MultipleAsserts]
public void CanEquateMatrices(string name)
{
var matrix1 = CreateMatrix(testData[name]);
var matrix2 = CreateMatrix(testData[name]);
var matrix3 = CreateMatrix(testData[name].GetLength(0), testData[name].GetLength(1));
Assert.IsTrue(matrix1.Equals(matrix1));
Assert.IsTrue(matrix1.Equals(matrix2));
Assert.IsFalse(matrix1.Equals(matrix3));
Assert.IsFalse(matrix1.Equals(null));
}
[Test]
[Row(0, 2)]
[Row(-1, 1)]
[ExpectedArgumentException]
public void ThrowsArgumentExceptionIfSizeIsNotPositive(int rows, int columns)
{
var A = CreateMatrix(rows, columns);
}
[Test]
[Row("Singular3x3")]
[Row("Square3x3")]
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
public void TestingForEqualityWithNonMatrixReturnsFalse(string name)
{
var matrix = CreateMatrix(testData[name]);
Assert.IsFalse(matrix.Equals(2));
}
[Test]
[Row("Singular3x3")]
[Row("Square3x3")]
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
public void CanTestForEqualityUsingObjectEquals(string name)
{
var matrix1 = CreateMatrix(testData[name]);
var matrix2 = CreateMatrix(testData[name]);
Assert.IsTrue(matrix1.Equals((object)matrix2));
}
[Test]
[Row(-1, 1, "Singular3x3")]
[Row(1, -1, "Singular3x3")]
[Row(4, 2, "Square3x3")]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void RangeCheckFails(int i, int j, string name)
{
var d = testMatrices[name][i, j];
}
[Test]
[Ignore]
public void MatrixGetHashCode()
{
}
}
}

2
src/UnitTests/UnitTests.csproj

@ -86,6 +86,8 @@
<Compile Include="InterpolationTests\InterpolationFunctionalContract.cs" />
<Compile Include="InterpolationTests\InterpolationInfrastructureContract.cs" />
<Compile Include="InterpolationTests\InterpolationFunctionalTest.cs" />
<Compile Include="LinearAlgebraTests\Double\MatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseVectorTest.TextHandling.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.Norm.cs" />

Loading…
Cancel
Save