diff --git a/src/FSharp/DenseMatrix.fs b/src/FSharp/DenseMatrix.fs
new file mode 100644
index 00000000..7678caa7
--- /dev/null
+++ b/src/FSharp/DenseMatrix.fs
@@ -0,0 +1,127 @@
+//
+// 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.
+//
+
+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>) =
+ 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) =
+ 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*)
\ No newline at end of file
diff --git a/src/FSharp/FSharp.fsproj b/src/FSharp/FSharp.fsproj
index 61279acb..43d622bd 100644
--- a/src/FSharp/FSharp.fsproj
+++ b/src/FSharp/FSharp.fsproj
@@ -46,6 +46,7 @@
+
diff --git a/src/FSharp/Main.fs b/src/FSharp/Main.fs
index 55e2ac23..0afbd4b8 100644
--- a/src/FSharp/Main.fs
+++ b/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>) = DenseMatrix.of_list lst :> Matrix
+ let inline matrix (lst: list>) = DenseMatrix.of_list lst :> Matrix
/// Construct a dense vector from a list of floating point numbers.
let inline vector (lst: list) = DenseVector.of_list lst :> Vector
\ No newline at end of file
diff --git a/src/FSharpUnitTests/Program.fs b/src/FSharpUnitTests/Program.fs
index e73ad1aa..884475dd 100644
--- a/src/FSharpUnitTests/Program.fs
+++ b/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:"
diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
new file mode 100644
index 00000000..c0ef53e4
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
@@ -0,0 +1,164 @@
+//
+// 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.
+//
+
+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;
+
+ ///
+ /// A Matrix class with dense storage.
+ ///
+ public class DenseMatrix : Matrix
+ {
+ ///
+ /// Initializes a new instance of the class. This matrix is square with a given size.
+ ///
+ /// the size of the square matrix.
+ ///
+ /// If is less than one.
+ ///
+ public DenseMatrix(int order)
+ : base(order)
+ {
+ Data = new double[order*order];
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ public DenseMatrix(int rows, int columns)
+ : base(rows, columns)
+ {
+ Data = new double[rows * columns];
+ }
+
+ ///
+ /// Initializes a new instance of the class with all entries set to a particular value.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ /// The value which we assign to each element of the matrix.
+ 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;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class from a 2D array.
+ ///
+ /// The 2D array to create this matrix from.
+ public DenseMatrix(double[,] array)
+ : base(array.GetLength(0), array.GetLength(1))
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets or sets the matrix's data.
+ ///
+ /// The matrix's data.
+ internal double[] Data
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Creates a DenseMatrix for the given number of rows and columns.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ ///
+ /// A DenseMatrix with the given dimensions.
+ ///
+ public override Matrix CreateMatrix(int numberOfRows, int numberOfColumns)
+ {
+ return new DenseMatrix(numberOfRows, numberOfColumns);
+ }
+
+ ///
+ /// Retrieves the requested element without range checking.
+ ///
+ ///
+ /// The row of the element.
+ ///
+ ///
+ /// The column of the element.
+ ///
+ ///
+ /// The requested element.
+ ///
+ public override double At(int row, int column)
+ {
+ return Data[column * RowCount + row];
+ }
+
+ ///
+ /// Sets the value of the given element.
+ ///
+ ///
+ /// The row of the element.
+ ///
+ ///
+ /// The column of the element.
+ ///
+ ///
+ /// The value to set the element to.
+ ///
+ public override void At(int row, int column, double value)
+ {
+ Data[column * RowCount + row] = value;
+ }
+ }
+}
diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index c7103461..42efec89 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -92,6 +92,7 @@
+
diff --git a/src/UnitTests/DistributionTests/CommonDistributionTests.cs b/src/UnitTests/DistributionTests/CommonDistributionTests.cs
index 34cb6479..b6018479 100644
--- a/src/UnitTests/DistributionTests/CommonDistributionTests.cs
+++ b/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]
diff --git a/src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs
new file mode 100644
index 00000000..306108d8
--- /dev/null
+++ b/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);
+ }
+ }
+ }
+ }
+}
diff --git a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs
new file mode 100644
index 00000000..656c634e
--- /dev/null
+++ b/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 testData;
+ protected Dictionary 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()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index 3799ad3a..45b72e39 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -86,6 +86,8 @@
+
+