Browse Source

Updated the F# interface to comply with the October 2009 CTP.

Added a DenseMatrix constructor which references an array.

Signed-off-by: jvangael <jurgen.vangael@gmail.com>
la-knuth
Jurgen Van Gael 17 years ago
parent
commit
6334379f12
  1. 12
      src/FSharp/DenseMatrix.fs
  2. 4
      src/FSharp/DenseVector.fs
  3. 4
      src/FSharp/Main.fs
  4. 4
      src/FSharp/Vector.fs
  5. 1
      src/FSharpExamples/Apply.fs
  6. 3
      src/FSharpExamples/DenseVector.fs
  7. 1
      src/FSharpExamples/Histogram.fs
  8. 8
      src/FSharpUnitTests/FsUnit.fs
  9. 36
      src/FSharpUnitTests/Program.fs
  10. 15
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  11. 47
      src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs
  12. 34
      src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs

12
src/FSharp/DenseMatrix.fs

@ -49,9 +49,9 @@ module DenseMatrix =
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 inline ofList (fll: float list list) =
let n = List.length fll
let m = List.length (List.hd fll)
let m = List.length (List.head 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
@ -59,9 +59,9 @@ module DenseMatrix =
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 inline ofSeq (fss: #seq<#seq<float>>) =
let n = Seq.length fss
let m = Seq.length (Seq.hd fss)
let m = Seq.length (Seq.head 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
@ -69,10 +69,10 @@ module DenseMatrix =
A
/// Create a matrix from a 2D array of floating point numbers.
let inline of_array2 (arr: float[,]) = new DenseMatrix(arr)
let inline ofArray2 (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 inline initDense (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

4
src/FSharp/DenseVector.fs

@ -41,14 +41,14 @@ module DenseVector =
v
/// Create a vector from a float list.
let inline of_list (fl: float list) =
let inline ofList (fl: float list) =
let n = List.length fl
let v = Double.DenseVector(n)
fl |> List.iteri (fun i f -> v.[i] <- f)
v
/// Create a vector from a sequences.
let inline of_seq (fs: #seq<float>) =
let inline ofSeq (fs: #seq<float>) =
let n = Seq.length fs
let v = DenseVector(n)
fs |> Seq.iteri (fun i f -> v.[i] <- f)

4
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.ofList lst :> Matrix
/// Construct a dense vector from a list of floating point numbers.
let inline vector (lst: list<float>) = DenseVector.of_list lst :> Vector
let inline vector (lst: list<float>) = DenseVector.ofList lst :> Vector

4
src/FSharp/Vector.fs

@ -34,12 +34,12 @@ open MathNet.Numerics.LinearAlgebra
module Vector =
/// Transform a vector into an array.
let inline to_array (v: #Vector) =
let inline toArray (v: #Vector) =
let n = v.Count
Array.init n (fun i -> v.Item(i))
/// Transform a vector into an array.
let inline to_list (v: #Vector) =
let inline toList (v: #Vector) =
let n = v.Count
List.init n (fun i -> v.Item(i))

1
src/FSharpExamples/Apply.fs

@ -25,6 +25,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
module MathNet.Numerics.FSharp.Examples.Apply
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra.Double

3
src/FSharpExamples/DenseVector.fs

@ -25,6 +25,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
module MathNet.Numerics.FSharp.Examples.DenseVector
open MathNet.Numerics.FSharp
open MathNet.Numerics.LinearAlgebra
@ -36,7 +37,7 @@ let v = Double.DenseVector.init 100 (fun i -> float i / 100.0)
let w = vector (List.init 100 (fun i -> float i ** 2.0))
// Vectors can also be constructed from sequences.
let t = Double.DenseVector.of_seq (seq { for i in 1 .. 100 do yield float i })
let t = Double.DenseVector.ofSeq (seq { for i in 1 .. 100 do yield float i })
// We can now add two vectors together ...
let z = v + w

1
src/FSharpExamples/Histogram.fs

@ -25,6 +25,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
module MathNet.Numerics.FSharp.Examples.Histogram
open MathNet.Numerics.Statistics

8
src/FSharpUnitTests/FsUnit.fs

@ -196,7 +196,7 @@ module SpecOps =
(sprintf "NOT Expected: %A\nActual: %A" expected actual)
module Results =
open Microsoft.FSharp.Text.Printf
open Microsoft.FSharp.Text
let internal currentResults = new ResizeArray<string * Result>()
@ -225,11 +225,11 @@ module Results =
let summary () =
let buff = new System.Text.StringBuilder()
bprintf buff "%d passed.\n%d failed.\n%d erred." (passedCount()) (failedCount()) (erredCount())
buff.AppendFormat("{0} passed.\n{1} failed.\n{2} erred.", passedCount(), failedCount(), erredCount()) |> ignore
failed()
|> Seq.iter (function (lbl,Fail msg) -> bprintf buff "\n----\nFailed: %s\n%s" lbl msg | _ -> ())
|> Seq.iter (function (lbl,Fail msg) -> buff.AppendFormat("\n----\nFailed: {0}\n{1}", lbl, msg) |> ignore | _ -> ())
erred()
|> Seq.iter (function (lbl,Error msg) -> bprintf buff "\n----\nErred: %s\n%s" lbl msg | _ -> ())
|> Seq.iter (function (lbl,Error msg) -> buff.AppendFormat("\n----\nErred: {0}\n{1}", lbl, msg) |> ignore | _ -> ())
buff.ToString()

36
src/FSharpUnitTests/Program.fs

@ -14,10 +14,10 @@ let DenseVectorTests =
specs "DenseVector" [
spec "DenseVector.init"
(DenseVector.init 100 (fun i -> float i / 100.0) |> should equal largev)
spec "DenseVector.of_list"
(DenseVector.of_list [ for i in 0 .. 99 -> float i / 100.0 ] |> should equal largev)
spec "DenseVector.of_seq"
(DenseVector.of_seq (seq { for i in 0 .. 99 -> float i / 100.0 }) |> should equal largev)
spec "DenseVector.ofList"
(DenseVector.ofList [ for i in 0 .. 99 -> float i / 100.0 ] |> should equal largev)
spec "DenseVector.ofSeq"
(DenseVector.ofSeq (seq { for i in 0 .. 99 -> float i / 100.0 }) |> should equal largev)
spec "DenseVector.rangef"
(DenseVector.rangef 0.0 0.01 0.99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> 0.01 * float i |] ) ))
spec "DenseVector.range"
@ -35,10 +35,10 @@ let VectorTests =
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 array_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.toArray"
(Vector.toArray smallv |> should array_equal [|0.3;0.3;0.3;0.3;0.3|])
spec "Vector.toList"
(Vector.toList 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
@ -127,9 +127,9 @@ let MatrixTests =
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))
(Matrix.foldByCol (+) 0.0 smallM |> should equal (DenseVector.ofList [0.6;0.6] :> Vector))
spec "Matrix.foldByRow"
(Matrix.foldByRow (+) 0.0 smallM |> should equal (DenseVector.of_list [0.6;0.6] :> Vector))
(Matrix.foldByRow (+) 0.0 smallM |> should equal (DenseVector.ofList [0.6;0.6] :> Vector))
]
@ -147,14 +147,14 @@ let DenseMatrixTests =
(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
spec "DenseMatrix.ofList"
(DenseMatrix.ofList [[0.3;0.3];[0.3;0.3]] |> should equal smallM)
spec "DenseMatrix.ofSeq"
(DenseMatrix.ofSeq (Seq.ofList [[0.3;0.3];[0.3;0.3]]) |> should equal smallM)
spec "DenseMatrix.ofArray2"
(DenseMatrix.ofArray2 (Array2D.create 2 2 0.3) |> should equal smallM)
spec "DenseMatrix.initDense"
(DenseMatrix.initDense 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)))

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

@ -38,7 +38,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
using Threading;
/// <summary>
/// A Matrix class with dense storage.
/// A Matrix class with dense storage. The underlying storage is a one dimensional array in column-major order.
/// </summary>
public class DenseMatrix : Matrix
{
@ -90,6 +90,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseMatrix"/> class from a one dimensional array. This constructor
/// will reference the one dimensional array and not copy it.
/// </summary>
/// <param name="rows">The number of rows.</param>
/// <param name="columns">The number of columns.</param
/// <param name="array">The one dimensional array to create this matrix from. This array should store the matrix in column-major order. <seealso cref="http://en.wikipedia.org/wiki/Row-major_order"/></param>
public DenseMatrix(int rows, int columns, double[] array)
: base(rows, columns)
{
Data = array;
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseMatrix"/> class from a 2D array. This constructor
/// will allocate a completely new memory block for storing the dense matrix.

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

@ -7,6 +7,10 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public class DenseMatrixTests : MatrixTests
{
protected double[] SquareMatrix = new double[] { -1.1, 0.0, 1.0, -4.4, -2.2, 1.1, 2.1, 5.5, -3.3, 2.2, 6.2, 6.6, -4.4, 3.3, 4.3, -7.7 };
protected int SquareMatrixRows = 4;
protected int SquareMatrixColumns = 4;
protected override Matrix CreateMatrix(int rows, int columns)
{
return new DenseMatrix(rows, columns);
@ -17,6 +21,39 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
return new DenseMatrix(data);
}
[Test]
public void CanCreateMatrixFrom1DArray()
{
Dictionary<string, Matrix> testData = new Dictionary<string, Matrix>();
testData.Add("Singular3x3", new DenseMatrix(3, 3, new double[] { 1, 1, 1, 1, 1, 1, 2, 2, 2 }));
testData.Add("Square3x3", new DenseMatrix(3, 3, new double[] { -1.1, 0.0, -4.4, -2.2, 1.1, 5.5, -3.3, 2.2, 6.6 }));
testData.Add("Square4x4", new DenseMatrix(4, 4, new double[] { -1.1, 0.0, 1.0, -4.4, -2.2, 1.1, 2.1, 5.5, -3.3, 2.2, 6.2, 6.6, -4.4, 3.3, 4.3, -7.7 }));
testData.Add("Tall3x2", new DenseMatrix(3, 2, new double[] { -1.1, 0.0, -4.4, -2.2, 1.1, 5.5 }));
testData.Add("Wide2x3", new DenseMatrix(2, 3, new double[] { -1.1, 0.0, -2.2, 1.1, -3.3, 2.2 }));
foreach (var name in testData.Keys)
{
Assert.AreEqual(testMatrices[name], testData[name]);
}
}
[Test]
public void MatrixFrom1DArrayIsReference()
{
var data = new double[] { 1, 1, 1, 1, 1, 1, 2, 2, 2 };
var matrix = new DenseMatrix(3, 3, data);
matrix[0, 0] = 10.0;
Assert.AreEqual(10.0, data[0]);
}
[Test]
public void MatrixFrom2DArrayIsCopy()
{
var matrix = new DenseMatrix(testData2D["Singular3x3"]);
matrix[0, 0] = 10.0;
Assert.AreEqual(1.0, testData2D["Singular3x3"][0, 0]);
}
[Test]
[Row("Singular3x3")]
[Row("Singular3x3")]
@ -24,14 +61,14 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[Row("Square4x4")]
[Row("Tall3x2")]
[Row("Wide2x3")]
public void CanCreateMatrixFromArray(string name)
public void CanCreateMatrixFrom2DArray(string name)
{
var matrix = new DenseMatrix(testData[name]);
for (var i = 0; i < testData[name].GetLength(0); i++)
var matrix = new DenseMatrix(testData2D[name]);
for (var i = 0; i < testData2D[name].GetLength(0); i++)
{
for (var j = 0; j < testData[name].GetLength(1); j++)
for (var j = 0; j < testData2D[name].GetLength(1); j++)
{
Assert.AreEqual(testData[name][i,j], matrix[i,j]);
Assert.AreEqual(testData2D[name][i, j], matrix[i, j]);
}
}
}

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

@ -8,7 +8,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
public abstract partial class MatrixTests
{
protected Dictionary<string, double[,]> testData;
protected Dictionary<string, double[,]> testData2D;
protected Dictionary<string, Matrix> testMatrices;
protected abstract Matrix CreateMatrix(int rows, int columns);
@ -17,17 +17,17 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[SetUp]
public void SetupDistributions()
{
testData = new Dictionary<string, double[,]>();
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 } });
testData2D = new Dictionary<string, double[,]>();
testData2D.Add("Singular3x3", new double[,] { { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 } });
testData2D.Add("Square3x3", new double[,] { { -1.1, -2.2, -3.3 }, { 0, 1.1, 2.2 }, { -4.4, 5.5, 6.6 } });
testData2D.Add("Square4x4", new double[,] { { -1.1, -2.2, -3.3, -4.4 }, { 0, 1.1, 2.2, 3.3 }, { 1.0, 2.1, 6.2, 4.3 }, { -4.4, 5.5, 6.6, -7.7 } });
testData2D.Add("Tall3x2", new double[,] { { -1.1, -2.2 }, { 0, 1.1 }, { -4.4, 5.5 } });
testData2D.Add("Wide2x3", new double[,] { { -1.1, -2.2, -3.3 }, { 0, 1.1, 2.2 } });
testMatrices = new Dictionary<string, Matrix>();
foreach(var name in testData.Keys)
foreach(var name in testData2D.Keys)
{
testMatrices.Add(name, CreateMatrix(testData[name]));
testMatrices.Add(name, CreateMatrix(testData2D[name]));
}
}
@ -40,7 +40,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[MultipleAsserts]
public void CanCloneMatrix(string name)
{
var matrix = CreateMatrix(testData[name]);
var matrix = CreateMatrix(testData2D[name]);
var clone = matrix.Clone();
Assert.AreNotSame(matrix, clone);
@ -64,7 +64,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[MultipleAsserts]
public void CanCloneMatrixUsingICloneable(string name)
{
var matrix = CreateMatrix(testData[name]);
var matrix = CreateMatrix(testData2D[name]);
var clone = (Matrix)((ICloneable)matrix).Clone();
Assert.AreNotSame(matrix, clone);
@ -102,9 +102,9 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[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));
var matrix1 = CreateMatrix(testData2D[name]);
var matrix2 = CreateMatrix(testData2D[name]);
var matrix3 = CreateMatrix(testData2D[name].GetLength(0), testData2D[name].GetLength(1));
Assert.IsTrue(matrix1.Equals(matrix1));
Assert.IsTrue(matrix1.Equals(matrix2));
Assert.IsFalse(matrix1.Equals(matrix3));
@ -128,7 +128,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[Row("Wide2x3")]
public void TestingForEqualityWithNonMatrixReturnsFalse(string name)
{
var matrix = CreateMatrix(testData[name]);
var matrix = CreateMatrix(testData2D[name]);
Assert.IsFalse(matrix.Equals(2));
}
@ -140,8 +140,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
[Row("Wide2x3")]
public void CanTestForEqualityUsingObjectEquals(string name)
{
var matrix1 = CreateMatrix(testData[name]);
var matrix2 = CreateMatrix(testData[name]);
var matrix1 = CreateMatrix(testData2D[name]);
var matrix2 = CreateMatrix(testData2D[name]);
Assert.IsTrue(matrix1.Equals((object)matrix2));
}

Loading…
Cancel
Save