diff --git a/src/FSharp/DenseMatrix.fs b/src/FSharp/DenseMatrix.fs index 7678caa7..e429da9c 100644 --- a/src/FSharp/DenseMatrix.fs +++ b/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>) = + let inline ofSeq (fss: #seq<#seq>) = 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) = + let inline initDense (n: int) (m: int) (es: #seq) = let A = new DenseMatrix(n,m) Seq.iter (fun (i,j,f) -> A.[i,j] <- f) es A diff --git a/src/FSharp/DenseVector.fs b/src/FSharp/DenseVector.fs index 84235dba..ddf594da 100644 --- a/src/FSharp/DenseVector.fs +++ b/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) = + let inline ofSeq (fs: #seq) = let n = Seq.length fs let v = DenseVector(n) fs |> Seq.iteri (fun i f -> v.[i] <- f) diff --git a/src/FSharp/Main.fs b/src/FSharp/Main.fs index 0afbd4b8..ede4b47d 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.ofList 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 + let inline vector (lst: list) = DenseVector.ofList lst :> Vector \ No newline at end of file diff --git a/src/FSharp/Vector.fs b/src/FSharp/Vector.fs index 2e25d8cd..0955eb3f 100644 --- a/src/FSharp/Vector.fs +++ b/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)) diff --git a/src/FSharpExamples/Apply.fs b/src/FSharpExamples/Apply.fs index a887d434..dc2c675b 100644 --- a/src/FSharpExamples/Apply.fs +++ b/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. // +module MathNet.Numerics.FSharp.Examples.Apply open MathNet.Numerics open MathNet.Numerics.LinearAlgebra.Double diff --git a/src/FSharpExamples/DenseVector.fs b/src/FSharpExamples/DenseVector.fs index 8a25fe46..48f9994f 100644 --- a/src/FSharpExamples/DenseVector.fs +++ b/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. // +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 diff --git a/src/FSharpExamples/Histogram.fs b/src/FSharpExamples/Histogram.fs index 65c58083..2d5203f5 100644 --- a/src/FSharpExamples/Histogram.fs +++ b/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. // +module MathNet.Numerics.FSharp.Examples.Histogram open MathNet.Numerics.Statistics diff --git a/src/FSharpUnitTests/FsUnit.fs b/src/FSharpUnitTests/FsUnit.fs index 84d2eeb2..9dba51e1 100644 --- a/src/FSharpUnitTests/FsUnit.fs +++ b/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() @@ -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() diff --git a/src/FSharpUnitTests/Program.fs b/src/FSharpUnitTests/Program.fs index 85dc1b6c..b27567df 100644 --- a/src/FSharpUnitTests/Program.fs +++ b/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))) diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs index 1ee92e67..19cdf881 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs @@ -38,7 +38,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double using Threading; /// - /// A Matrix class with dense storage. + /// A Matrix class with dense storage. The underlying storage is a one dimensional array in column-major order. /// public class DenseMatrix : Matrix { @@ -90,6 +90,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double } } + /// + /// Initializes a new instance of the class from a one dimensional array. This constructor + /// will reference the one dimensional array and not copy it. + /// + /// The number of rows. + /// The number of columns.The one dimensional array to create this matrix from. This array should store the matrix in column-major order. + public DenseMatrix(int rows, int columns, double[] array) + : base(rows, columns) + { + Data = array; + } + /// /// Initializes a new instance of the class from a 2D array. This constructor /// will allocate a completely new memory block for storing the dense matrix. diff --git a/src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs index f4b9afb8..3bd95a35 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/DenseMatrixTests.cs +++ b/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 testData = new Dictionary(); + 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]); } } } diff --git a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs index c3014dfb..41ed50a7 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.cs @@ -8,7 +8,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double { public abstract partial class MatrixTests { - protected Dictionary testData; + protected Dictionary testData2D; protected Dictionary 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(); - 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(); + 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(); - 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)); }