diff --git a/src/FSharp/Fit.fs b/src/FSharp/Fit.fs index 4a15502c..4497b7ad 100644 --- a/src/FSharp/Fit.fs +++ b/src/FSharp/Fit.fs @@ -62,7 +62,7 @@ module Fit = let linear functions (x:_[]) (y:float[]) = functions |> List.map (fun f -> List.init (Array.length x) (fun i -> f x.[i])) - |> DenseMatrix.ofColumnsList (Array.length x) (List.length functions) + |> DenseMatrix.ofColumnList (Array.length x) (List.length functions) |> fun m -> m.QR(QRMethod.Thin).Solve(DenseVector(y)).ToArray() |> List.ofArray diff --git a/src/FSharp/LinearAlgebra.Double.Matrix.fs b/src/FSharp/LinearAlgebra.Double.Matrix.fs index 5508935c..6ad192b4 100644 --- a/src/FSharp/LinearAlgebra.Double.Matrix.fs +++ b/src/FSharp/LinearAlgebra.Double.Matrix.fs @@ -36,6 +36,8 @@ open MathNet.Numerics.LinearAlgebra [] module Matrix = + // TODO: generalize or reconsider + /// Returns the sum of all elements of a matrix. let inline sum (A: #Matrix) = A |> Matrix.foldnz (+) 0.0 @@ -75,19 +77,28 @@ module DenseMatrix = /// Create a matrix with the given dimension and set all values to x. let inline create (rows: int) (cols: int) x = DenseMatrix.Create(rows, cols, fun i j -> x) :> _ Matrix + /// Create a matrix with the given dimension and set all diagonal values to x. All other values are zero. + let inline createDiag (rows: int) (cols: int) x = + let A = DenseMatrix(rows,cols) + for i=0 to min (rows-1) (cols-1) do A.At(i,i,x) + A :> _ Matrix + /// Initialize a matrix by calling a construction function for every element. let inline init (rows: int) (cols: int) (f: int -> int -> float) = DenseMatrix.Create(rows, cols, fun i j -> f i j) :> _ Matrix + /// Initialize a matrix by calling a construction function for every diagonal element. All other values are zero. + let inline initDiag (rows: int) (cols: int) (f: int -> float) = + let A = DenseMatrix(rows,cols) + for i=0 to min (rows-1) (cols-1) do A.At(i,i,f i) + A :> _ Matrix + + /// Create an identity matrix with the given dimension. + let inline identity (rows: int) (cols: int) = createDiag rows cols 1.0 + + /// Create a matrix from a 2D array of floating point numbers. let inline ofArray2 array = DenseMatrix.OfArray(array) :> _ Matrix - /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. - /// If the dimensions are known, consider to use ofRowSeq instead to avoid multiple enumeration. - let inline ofSeq (fss: #seq<#seq>) = - let n = Seq.length fss - let m = Seq.length (Seq.head fss) - DenseMatrix.OfRowsCovariant(n, m, fss) :> _ Matrix - /// Create a matrix from a list of float lists. Every list in the master list specifies a row. /// If the dimensions are known, consider to use ofRowList instead to avoid multiple enumeration. let inline ofList (fll: float list list) = @@ -96,38 +107,39 @@ module DenseMatrix = DenseMatrix.OfRowsCovariant(n, m, fll) :> _ Matrix /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. - let inline ofRows (rows: int) (cols: int) (fss: #seq<#seq>) = DenseMatrix.OfRowsCovariant(rows, cols, fss) :> _ Matrix + /// If the dimensions are known, consider to use ofRowSeq instead to avoid multiple enumeration. + let inline ofSeq (fss: #seq<#seq>) = + let n = Seq.length fss + let m = Seq.length (Seq.head fss) + DenseMatrix.OfRowsCovariant(n, m, fss) :> _ Matrix - /// Create a matrix from a list of float lists. Every list in the master list specifies a row. - let inline ofRowsList (rows: int) (cols: int) (fll: float list list) = DenseMatrix.OfRowsCovariant(rows, cols, fll) :> _ Matrix /// Create a matrix from a list of row vectors. - let inline ofRowVectors (vectors: #Vector list) = DenseMatrix.OfRowVectors(vectors |> Array.ofList |> box |> unbox) :> _ Matrix + let inline ofRows (vectors: #Vector list) = DenseMatrix.OfRowVectors(vectors |> Array.ofList |> box |> unbox) :> _ Matrix - /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a column. - let inline ofColumns (rows: int) (cols: int) (fss: #seq<#seq>) = DenseMatrix.OfColumnsCovariant(rows, cols, fss) :> _ Matrix + /// Create a matrix from a list of float lists. Every list in the master list specifies a row. + let inline ofRowList (rows: int) (cols: int) (fll: float list list) = DenseMatrix.OfRowsCovariant(rows, cols, fll) :> _ Matrix - /// Create a matrix from a list of float lists. Every list in the master list specifies a column. - let inline ofColumnsList (rows: int) (cols: int) (fll: float list list) = DenseMatrix.OfColumnsCovariant(rows, cols, fll) :> _ Matrix + /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. + let inline ofRowSeq (rows: int) (cols: int) (fss: #seq<#seq>) = DenseMatrix.OfRowsCovariant(rows, cols, fss) :> _ Matrix /// Create a matrix from a list of column vectors. - let inline ofColumnVectors (vectors: #Vector list) = DenseMatrix.OfColumnVectors(vectors |> Array.ofList |> box |> unbox) :> _ Matrix + let inline ofColumns (vectors: #Vector list) = DenseMatrix.OfColumnVectors(vectors |> Array.ofList |> box |> unbox) :> _ Matrix - /// Create a matrix with a given dimension from an indexed sequences of row, column, value tuples. - let inline ofSeqi (rows: int) (cols: int) (fs: #seq) = DenseMatrix.OfIndexed(rows, cols, fs) :> _ Matrix + /// Create a matrix from a list of float lists. Every list in the master list specifies a column. + let inline ofColumnList (rows: int) (cols: int) (fll: float list list) = DenseMatrix.OfColumnsCovariant(rows, cols, fll) :> _ Matrix + + /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a column. + let inline ofColumnSeq (rows: int) (cols: int) (fss: #seq<#seq>) = DenseMatrix.OfColumnsCovariant(rows, cols, fss) :> _ Matrix /// Create a matrix with a given dimension from an indexed list of row, column, value tuples. let inline ofListi (rows: int) (cols: int) (fl: list) = DenseMatrix.OfIndexed(rows, cols, Seq.ofList fl) :> _ Matrix - /// Create a square matrix with constant diagonal entries. - let inline constDiag (n: int) (f: float) = - let A = DenseMatrix(n,n) - for i=0 to n-1 do - A.At(i,i,f) - A :> _ Matrix + /// Create a matrix with a given dimension from an indexed sequences of row, column, value tuples. + let inline ofSeqi (rows: int) (cols: int) (fs: #seq) = DenseMatrix.OfIndexed(rows, cols, fs) :> _ Matrix /// Create a square matrix with the vector elements on the diagonal. - let inline diag (v: #Vector) = + let inline ofDiag (v: #Vector) = let n = v.Count let A = DenseMatrix(n,n) A.SetDiagonal(v) @@ -152,9 +164,25 @@ module SparseMatrix = /// Create an all-zero matrix with the given dimension. let inline zeroCreate (rows: int) (cols: int) = SparseMatrix(rows, cols) :> _ Matrix + /// Create a matrix with the given dimension and set all diagonal values to x. All other values are zero. + let inline createDiag (rows: int) (cols: int) x = + let A = SparseMatrix(rows,cols) + for i=0 to min (rows-1) (cols-1) do A.At(i,i,x) + A :> _ Matrix + /// Initialize a matrix by calling a construction function for every element. let inline init (rows: int) (cols: int) (f: int -> int -> float) = SparseMatrix.Create(rows, cols, fun n m -> f n m) :> _ Matrix + /// Initialize a matrix by calling a construction function for every diagonal element. All other values are zero. + let inline initDiag (rows: int) (cols: int) (f: int -> float) = + let A = SparseMatrix(rows,cols) + for i=0 to min (rows-1) (cols-1) do A.At(i,i,f i) + A :> _ Matrix + + /// Create an identity matrix with the given dimension. + let inline identity (rows: int) (cols: int) = createDiag rows cols 1.0 + + /// Create a matrix from a 2D array of floating point numbers. let inline ofArray2 array = SparseMatrix.OfArray(array) :> _ Matrix @@ -166,33 +194,33 @@ module SparseMatrix = [] let inline ofList (rows: int) (cols: int) (fl: list) = SparseMatrix.OfIndexed(rows, cols, Seq.ofList fl) :> _ Matrix - /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. - let inline ofRows (rows: int) (cols: int) (fss: #seq<#seq>) = SparseMatrix.OfRowsCovariant(rows, cols, fss) :> _ Matrix + + /// Create a matrix from a list of row vectors. + let inline ofRows (vectors: #Vector list) = SparseMatrix.OfRowVectors(vectors |> Array.ofList |> box |> unbox) :> _ Matrix /// Create a matrix from a list of float lists. Every list in the master list specifies a row. - let inline ofRowsList (rows: int) (cols: int) (fll: float list list) = SparseMatrix.OfRowsCovariant(rows, cols, fll) :> _ Matrix + let inline ofRowList (rows: int) (cols: int) (fll: float list list) = SparseMatrix.OfRowsCovariant(rows, cols, fll) :> _ Matrix - /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a column. - let inline ofColumns (rows: int) (cols: int) (fss: #seq<#seq>) = SparseMatrix.OfColumnsCovariant(rows, cols, fss) :> _ Matrix + /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. + let inline ofRowSeq (rows: int) (cols: int) (fss: #seq<#seq>) = SparseMatrix.OfRowsCovariant(rows, cols, fss) :> _ Matrix + + /// Create a matrix from a list of column vectors. + let inline ofColumns (vectors: #Vector list) = SparseMatrix.OfColumnVectors(vectors |> Array.ofList |> box |> unbox) :> _ Matrix /// Create a matrix from a list of float lists. Every list in the master list specifies a column. - let inline ofColumnsList (rows: int) (cols: int) (fll: float list list) = SparseMatrix.OfColumnsCovariant(rows, cols, fll) :> _ Matrix + let inline ofColumnList (rows: int) (cols: int) (fll: float list list) = SparseMatrix.OfColumnsCovariant(rows, cols, fll) :> _ Matrix - /// Create a matrix with a given dimension from an indexed sequences of row, column, value tuples. - let inline ofSeqi (rows: int) (cols: int) (fs: #seq) = SparseMatrix.OfIndexed(rows, cols, fs) :> _ Matrix + /// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a column. + let inline ofColumnSeq (rows: int) (cols: int) (fss: #seq<#seq>) = SparseMatrix.OfColumnsCovariant(rows, cols, fss) :> _ Matrix /// Create a matrix with a given dimension from an indexed list of row, column, value tuples. let inline ofListi (rows: int) (cols: int) (fl: list) = SparseMatrix.OfIndexed(rows, cols, Seq.ofList fl) :> _ Matrix - /// Create a square matrix with constant diagonal entries. - let inline constDiag (n: int) (f: float) = - let A = SparseMatrix(n,n) - for i=0 to n-1 do - A.At(i,i,f) - A :> _ Matrix + /// Create a matrix with a given dimension from an indexed sequences of row, column, value tuples. + let inline ofSeqi (rows: int) (cols: int) (fs: #seq) = SparseMatrix.OfIndexed(rows, cols, fs) :> _ Matrix /// Create a square matrix with the vector elements on the diagonal. - let inline diag (v: #Vector) = + let inline ofDiag (v: #Vector) = let n = v.Count let A = SparseMatrix(n,n) A.SetDiagonal(v) diff --git a/src/FSharp/LinearAlgebra.Double.Vector.fs b/src/FSharp/LinearAlgebra.Double.Vector.fs index a6d6b7b3..202c4b8c 100644 --- a/src/FSharp/LinearAlgebra.Double.Vector.fs +++ b/src/FSharp/LinearAlgebra.Double.Vector.fs @@ -36,6 +36,8 @@ open MathNet.Numerics.LinearAlgebra [] module Vector = + // TODO: generalize or reconsider + /// Creates a new vector and inserts the given value at the given index. let inline insert index value (v: #Vector) = let newV = new DenseVector(v.Count + 1) @@ -77,17 +79,12 @@ module DenseVector = /// Create a vector with a given dimension from an indexed sequences of index, value pairs. let inline ofSeqi (n: int) (fs: #seq) = DenseVector.OfIndexedEnumerable(n, fs) :> _ Vector + /// Create a vector with integer entries in the given range. + let inline range (start: int) (step: int) (stop: int) = raw [| for i in start..step..stop -> float i |] + /// Create a vector with evenly spaced entries: e.g. rangef -1.0 0.5 1.0 = [-1.0 -0.5 0.0 0.5 1.0] - let inline rangef (start: float) (step: float) (stop: float) = - let n = (int ((stop - start) / step)) + 1 - let v = DenseVector(n) - for i=0 to n-1 do - v.At(i, (float i) * step + start) - v :> _ Vector + let inline rangef (start: float) (step: float) (stop: float) = raw [| start..step..stop |] - /// Create a vector with integer entries in the given range. - let inline range (start: int) (stop: int) = - DenseVector([| for i in [start .. stop] -> float i |]) :> _ Vector /// A module which implements functional sparse vector operations. [] diff --git a/src/FSharpExamples/Matrices.fsx b/src/FSharpExamples/Matrices.fsx index a465d04f..8dec98b1 100644 --- a/src/FSharpExamples/Matrices.fsx +++ b/src/FSharpExamples/Matrices.fsx @@ -53,16 +53,20 @@ let d1 = DenseMatrix.init 3 4 (fun i j -> float i / 100.0 + float j) let d2 = SparseMatrix.init 3 4 (fun i j -> if i=j then float i / 100.0 + float j else 0.0) // Matrices can also be constructed from sequences of rows or of columns -let e1 = DenseMatrix.ofRows 20 10 (seq { for i in 1 .. 20 do yield Array.init 10 (fun j -> float j + 100.0 * float i) }) -let e2 = SparseMatrix.ofRows 20 10 (seq { for i in 1 .. 20 do yield Array.init 10 (fun j -> if i%5 = 0 then float j + 100.0 * float i else 0.0) }) -let e3 = DenseMatrix.ofColumns 20 10 (seq { for j in 1 .. 10 do yield Array.init 20 (fun i -> float j + 100.0 * float i) }) -let e4 = SparseMatrix.ofColumns 20 10 (seq { for j in 1 .. 10 do yield Array.init 20 (fun i -> if i%5 = 0 then float j + 100.0 * float i else 0.0) }) +let e1 = DenseMatrix.ofRowSeq 20 10 (seq { for i in 1 .. 20 do yield Array.init 10 (fun j -> float j + 100.0 * float i) }) +let e2 = SparseMatrix.ofRowSeq 20 10 (seq { for i in 1 .. 20 do yield Array.init 10 (fun j -> if i%5 = 0 then float j + 100.0 * float i else 0.0) }) +let e3 = DenseMatrix.ofColumnSeq 20 10 (seq { for j in 1 .. 10 do yield Array.init 20 (fun i -> float j + 100.0 * float i) }) +let e4 = SparseMatrix.ofColumnSeq 20 10 (seq { for j in 1 .. 10 do yield Array.init 20 (fun i -> if i%5 = 0 then float j + 100.0 * float i else 0.0) }) // Or from F# lists -let f1 = DenseMatrix.ofRowsList 20 10 [ for i in 1 .. 20 -> List.init 10 (fun j -> float j + 100.0 * float i) ] -let f2 = SparseMatrix.ofRowsList 20 10 [ for i in 1 .. 20 -> List.init 10 (fun j -> if i%5 = 0 then float j + 100.0 * float i else 0.0) ] -let f3 = DenseMatrix.ofColumnsList 20 10 [ for j in 1 .. 10 -> List.init 20 (fun i -> float j + 100.0 * float i) ] -let f4 = SparseMatrix.ofColumnsList 20 10 [ for j in 1 .. 10 -> List.init 20 (fun i -> if i%5 = 0 then float j + 100.0 * float i else 0.0) ] +let f1 = DenseMatrix.ofRowList 20 10 [ for i in 1 .. 20 -> List.init 10 (fun j -> float j + 100.0 * float i) ] +let f2 = SparseMatrix.ofRowList 20 10 [ for i in 1 .. 20 -> List.init 10 (fun j -> if i%5 = 0 then float j + 100.0 * float i else 0.0) ] +let f3 = DenseMatrix.ofColumnList 20 10 [ for j in 1 .. 10 -> List.init 20 (fun i -> float j + 100.0 * float i) ] +let f4 = SparseMatrix.ofColumnList 20 10 [ for j in 1 .. 10 -> List.init 20 (fun i -> if i%5 = 0 then float j + 100.0 * float i else 0.0) ] + +// Or from row or column vectors +let m1 = DenseMatrix.ofRows [DenseVector.create 3 1.0; DenseVector.create 3 2.0] +let m2 = DenseMatrix.ofColumns [DenseVector.create 3 1.0; DenseVector.create 3 2.0] // Or from indexed lists or sequences where all other values are zero (useful mostly for sparse data) let g1 = DenseMatrix.ofListi 20 10 [(4,3,20.0); (18,9,3.0); (2,1,100.0)] diff --git a/src/FSharpUnitTests/DenseMatrixTests.fs b/src/FSharpUnitTests/DenseMatrixTests.fs index b3eaf756..f27a5f33 100644 --- a/src/FSharpUnitTests/DenseMatrixTests.fs +++ b/src/FSharpUnitTests/DenseMatrixTests.fs @@ -53,28 +53,28 @@ module DenseMatrixTests = DenseMatrix.ofList [[0.3;0.3];[0.3;0.3];[0.3;0.3]] |> should equal smallM [] - let ``DenseMatrix.ofRows`` () = - DenseMatrix.ofRows 3 2 (Seq.ofList [[0.3;0.3];[0.3;0.3];[0.3;0.3]]) |> should equal smallM + let ``DenseMatrix.ofRowSeq`` () = + DenseMatrix.ofRowSeq 3 2 (Seq.ofList [[0.3;0.3];[0.3;0.3];[0.3;0.3]]) |> should equal smallM [] - let ``DenseMatrix.ofRowsList`` () = - DenseMatrix.ofRowsList 3 2 [[0.3;0.3];[0.3;0.3];[0.3;0.3]] |> should equal smallM + let ``DenseMatrix.ofRowList`` () = + DenseMatrix.ofRowList 3 2 [[0.3;0.3];[0.3;0.3];[0.3;0.3]] |> should equal smallM [] - let ``DenseMatrix.ofRowVectors`` () = - DenseMatrix.ofRowVectors [vector [0.3;0.3]; vector [0.3;0.3]; vector [0.3;0.3]] |> should equal smallM + let ``DenseMatrix.ofRows`` () = + DenseMatrix.ofRows [vector [0.3;0.3]; vector [0.3;0.3]; vector [0.3;0.3]] |> should equal smallM [] - let ``DenseMatrix.ofColumn`` () = - DenseMatrix.ofColumns 3 2 (Seq.ofList [[0.3;0.3;0.3];[0.3;0.3;0.3]]) |> should equal smallM + let ``DenseMatrix.ofColumnSeq`` () = + DenseMatrix.ofColumnSeq 3 2 (Seq.ofList [[0.3;0.3;0.3];[0.3;0.3;0.3]]) |> should equal smallM [] - let ``DenseMatrix.ofColumnsList`` () = - DenseMatrix.ofColumnsList 3 2 [[0.3;0.3;0.3];[0.3;0.3;0.3]] |> should equal smallM + let ``DenseMatrix.ofColumnList`` () = + DenseMatrix.ofColumnList 3 2 [[0.3;0.3;0.3];[0.3;0.3;0.3]] |> should equal smallM [] - let ``DenseMatrix.ofColumnVectors`` () = - DenseMatrix.ofColumnVectors [vector [0.3;0.3;0.3]; vector [0.3;0.3;0.3]] |> should equal smallM + let ``DenseMatrix.ofColumns`` () = + DenseMatrix.ofColumns [vector [0.3;0.3;0.3]; vector [0.3;0.3;0.3]] |> should equal smallM [] let ``DenseMatrix.ofSeqi`` () = @@ -87,17 +87,17 @@ module DenseMatrixTests = |> DenseMatrix.ofListi 100 120 |> should equal largeM [] - let ``DenseMatrix.constDiag`` () = - DenseMatrix.constDiag 100 2.0 |> should equal (2.0 * (DenseMatrix.Identity 100)) + let ``DenseMatrix.createDiag`` () = + DenseMatrix.createDiag 100 100 2.0 |> should equal (2.0 * (DenseMatrix.Identity 100)) [] - let ``DenseMatrix.diag`` () = - DenseMatrix.diag (DenseVector.Create(100, fun i -> 2.0)) |> should equal (2.0 * (DenseMatrix.Identity 100)) + let ``DenseMatrix.ofDiag`` () = + DenseMatrix.ofDiag (DenseVector.Create(100, fun i -> 2.0)) |> should equal (2.0 * (DenseMatrix.Identity 100)) [] - let ``DenseMatrix.init_row`` () = + let ``DenseMatrix.initRow`` () = DenseMatrix.initRow 100 120 (fun i -> (DenseVector.init 120 (fun j -> float i * 100.0 + float j))) |> should equal largeM [] - let ``DenseMatrix.init_col`` () = + let ``DenseMatrix.initCol`` () = DenseMatrix.initCol 100 120 (fun j -> (DenseVector.init 100 (fun i -> float i * 100.0 + float j))) |> should equal largeM diff --git a/src/FSharpUnitTests/DenseVectorTests.fs b/src/FSharpUnitTests/DenseVectorTests.fs index 87549ec3..b70788ec 100644 --- a/src/FSharpUnitTests/DenseVectorTests.fs +++ b/src/FSharpUnitTests/DenseVectorTests.fs @@ -57,4 +57,4 @@ module DenseVectorTests = [] let ``DenseVector.range`` () = - DenseVector.range 0 99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> float i |] ) ) + DenseVector.range 0 1 99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> float i |] ) ) diff --git a/src/FSharpUnitTests/SparseMatrixTests.fs b/src/FSharpUnitTests/SparseMatrixTests.fs index 57b94432..86e0fb79 100644 --- a/src/FSharpUnitTests/SparseMatrixTests.fs +++ b/src/FSharpUnitTests/SparseMatrixTests.fs @@ -25,20 +25,20 @@ module SparseMatrixTests = SparseMatrix.ofArray2 (Array2D.init 4 6 (fun i j -> if i = 1 && j = 2 then 1.0 else 0.0)) |> should equal smallM [] - let ``SparseMatrix.ofRows`` () = - SparseMatrix.ofRows 4 6 (Seq.ofList [[0.;0.;0.;0.;0.;0.];[0.;0.;1.;0.;0.;0.];[0.;0.;0.;0.;0.;0.];[0.;0.;0.;0.;0.;0.]]) |> should equal smallM + let ``SparseMatrix.ofRowSeq`` () = + SparseMatrix.ofRowSeq 4 6 (Seq.ofList [[0.;0.;0.;0.;0.;0.];[0.;0.;1.;0.;0.;0.];[0.;0.;0.;0.;0.;0.];[0.;0.;0.;0.;0.;0.]]) |> should equal smallM [] - let ``SparseMatrix.ofRowsList`` () = - SparseMatrix.ofRowsList 4 6 [[0.;0.;0.;0.;0.;0.];[0.;0.;1.;0.;0.;0.];[0.;0.;0.;0.;0.;0.];[0.;0.;0.;0.;0.;0.]] |> should equal smallM + let ``SparseMatrix.ofRowList`` () = + SparseMatrix.ofRowList 4 6 [[0.;0.;0.;0.;0.;0.];[0.;0.;1.;0.;0.;0.];[0.;0.;0.;0.;0.;0.];[0.;0.;0.;0.;0.;0.]] |> should equal smallM [] - let ``SparseMatrix.ofColumns`` () = - SparseMatrix.ofColumns 4 6 (Seq.ofList [[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;1.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.]]) |> should equal smallM + let ``SparseMatrix.ofColumnSeq`` () = + SparseMatrix.ofColumnSeq 4 6 (Seq.ofList [[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;1.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.]]) |> should equal smallM [] let ``SparseMatrix.ofColumnList`` () = - SparseMatrix.ofColumnsList 4 6 [[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;1.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.]] |> should equal smallM + SparseMatrix.ofColumnList 4 6 [[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;1.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.];[0.;0.;0.;0.]] |> should equal smallM [] let ``SparseMatrix.ofSeqi`` () = @@ -50,11 +50,11 @@ module SparseMatrixTests = [] let ``SparseMatrix.constDiag`` () = - SparseMatrix.constDiag 100 2.0 |> should equal (2.0 * (SparseMatrix.Identity 100)) + SparseMatrix.createDiag 100 100 2.0 |> should equal (2.0 * (SparseMatrix.Identity 100)) [] let ``SparseMatrix.diag`` () = - SparseMatrix.diag (DenseVector.Create(100, fun i -> 2.0)) |> should equal (2.0 * (SparseMatrix.Identity 100)) + SparseMatrix.ofDiag (DenseVector.Create(100, fun i -> 2.0)) |> should equal (2.0 * (SparseMatrix.Identity 100)) [] let ``SparseMatrix.init_row`` () = diff --git a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs index a2c2eab3..fc316714 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs @@ -162,6 +162,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given column vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfColumnVectors(params Vector[] columns) + { + var storage = new VectorStorage[columns.Length]; + for (int i = 0; i < columns.Length; i++) + { + storage[i] = columns[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable columns. /// Each enumerable in the master enumerable specifies a column. @@ -186,6 +201,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given row vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfRowVectors(params Vector[] rows) + { + var storage = new VectorStorage[rows.Length]; + for (int i = 0; i < rows.Length; i++) + { + storage[i] = rows[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable rows. /// Each enumerable in the master enumerable specifies a row. diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs index 836a780a..9a62af35 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs @@ -157,6 +157,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given column vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfColumnVectors(params Vector[] columns) + { + var storage = new VectorStorage[columns.Length]; + for (int i = 0; i < columns.Length; i++) + { + storage[i] = columns[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable columns. /// Each enumerable in the master enumerable specifies a column. @@ -181,6 +196,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given row vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfRowVectors(params Vector[] rows) + { + var storage = new VectorStorage[rows.Length]; + for (int i = 0; i < rows.Length; i++) + { + storage[i] = rows[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable rows. /// Each enumerable in the master enumerable specifies a row. diff --git a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs index 4de87a06..5e5a703e 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs @@ -155,6 +155,21 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given column vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfColumnVectors(params Vector[] columns) + { + var storage = new VectorStorage[columns.Length]; + for (int i = 0; i < columns.Length; i++) + { + storage[i] = columns[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable columns. /// Each enumerable in the master enumerable specifies a column. @@ -179,6 +194,21 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given row vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfRowVectors(params Vector[] rows) + { + var storage = new VectorStorage[rows.Length]; + for (int i = 0; i < rows.Length; i++) + { + storage[i] = rows[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable rows. /// Each enumerable in the master enumerable specifies a row. diff --git a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs index 7c1546e1..0ce2ae3c 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs @@ -155,6 +155,21 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given column vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfColumnVectors(params Vector[] columns) + { + var storage = new VectorStorage[columns.Length]; + for (int i = 0; i < columns.Length; i++) + { + storage[i] = columns[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable columns. /// Each enumerable in the master enumerable specifies a column. @@ -179,6 +194,21 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowEnumerables(rows, columns, data)); } + /// + /// Create a new sparse matrix as a copy of the given row vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public static SparseMatrix OfRowVectors(params Vector[] rows) + { + var storage = new VectorStorage[rows.Length]; + for (int i = 0; i < rows.Length; i++) + { + storage[i] = rows[i].Storage; + } + return new SparseMatrix(SparseCompressedRowMatrixStorage.OfRowVectors(storage)); + } + /// /// Create a new sparse matrix as a copy of the given enumerable of enumerable rows. /// Each enumerable in the master enumerable specifies a row. diff --git a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs index 995ee7f6..d9cb7b1d 100644 --- a/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs @@ -138,43 +138,8 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return storage; } - public static DenseColumnMajorMatrixStorage OfIndexedEnumerable(int rows, int columns, IEnumerable> data) - { - if (data == null) - { - throw new ArgumentNullException("data"); - } - - var array = new T[rows * columns]; - foreach (var item in data) - { - array[(item.Item2 * rows) + item.Item1] = item.Item3; - } - return new DenseColumnMajorMatrixStorage(rows, columns, array); - } - - public static DenseColumnMajorMatrixStorage OfColumnMajorEnumerable(int rows, int columns, IEnumerable data) - { - if (data == null) - { - throw new ArgumentNullException("data"); - } - - var arrayData = data as T[]; - if (arrayData != null) - { - var copy = new T[arrayData.Length]; - Array.Copy(arrayData, copy, arrayData.Length); - return new DenseColumnMajorMatrixStorage(rows, columns, copy); - } - - var array = System.Linq.Enumerable.ToArray(data); - return new DenseColumnMajorMatrixStorage(rows, columns, array); - } - public static DenseColumnMajorMatrixStorage OfColumnVectors(VectorStorage[] data) { - if (data == null) throw new ArgumentNullException("data"); int columns = data.Length; int rows = data[0].Length; var array = new T[rows * columns]; @@ -189,7 +154,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage else { // FALL BACK - int offset = j*rows; + int offset = j * rows; for (int i = 0; i < rows; i++) { array[offset + i] = column.At(i); @@ -201,13 +166,12 @@ namespace MathNet.Numerics.LinearAlgebra.Storage public static DenseColumnMajorMatrixStorage OfRowVectors(VectorStorage[] data) { - if (data == null) throw new ArgumentNullException("data"); int rows = data.Length; int columns = data[0].Length; var array = new T[rows * columns]; for (int j = 0; j < columns; j++) { - int offset = j*rows; + int offset = j * rows; for (int i = 0; i < rows; i++) { array[offset + i] = data[i].At(j); @@ -216,11 +180,34 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return new DenseColumnMajorMatrixStorage(rows, columns, array); } + public static DenseColumnMajorMatrixStorage OfIndexedEnumerable(int rows, int columns, IEnumerable> data) + { + var array = new T[rows * columns]; + foreach (var item in data) + { + array[(item.Item2 * rows) + item.Item1] = item.Item3; + } + return new DenseColumnMajorMatrixStorage(rows, columns, array); + } + + public static DenseColumnMajorMatrixStorage OfColumnMajorEnumerable(int rows, int columns, IEnumerable data) + { + var arrayData = data as T[]; + if (arrayData != null) + { + var copy = new T[arrayData.Length]; + Array.Copy(arrayData, copy, arrayData.Length); + return new DenseColumnMajorMatrixStorage(rows, columns, copy); + } + + var array = System.Linq.Enumerable.ToArray(data); + return new DenseColumnMajorMatrixStorage(rows, columns, array); + } + public static DenseColumnMajorMatrixStorage OfColumnEnumerables(int rows, int columns, IEnumerable data) // NOTE: flexible typing to 'backport' generic covariance. where TColumn : IEnumerable { - if (data == null) throw new ArgumentNullException("data"); var array = new T[rows*columns]; using (var columnIterator = data.GetEnumerator()) { @@ -255,7 +242,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage // NOTE: flexible typing to 'backport' generic covariance. where TRow : IEnumerable { - if (data == null) throw new ArgumentNullException("data"); var array = new T[rows*columns]; using (var rowIterator = data.GetEnumerator()) { diff --git a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs index 1c1ffc86..7dfed791 100644 --- a/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs @@ -31,6 +31,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography.X509Certificates; using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Storage @@ -373,11 +374,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage public static SparseCompressedRowMatrixStorage OfArray(T[,] array) { - if (array == null) - { - throw new ArgumentNullException("array"); - } - var storage = new SparseCompressedRowMatrixStorage(array.GetLength(0), array.GetLength(1)); var rowPointers = storage.RowPointers; var columnIndices = new List(); @@ -429,13 +425,65 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return storage; } - public static SparseCompressedRowMatrixStorage OfIndexedEnumerable(int rows, int columns, IEnumerable> data) + public static SparseCompressedRowMatrixStorage OfRowVectors(VectorStorage[] data) { - if (data == null) + var storage = new SparseCompressedRowMatrixStorage(data.Length, data[0].Length); + var rowPointers = storage.RowPointers; + var columnIndices = new List(); + var values = new List(); + + // TODO PERF: Optimize for sparse and dense cases + for (int row = 0; row < storage.RowCount; row++) { - throw new ArgumentNullException("data"); + var vector = data[row]; + rowPointers[row] = values.Count; + for (int col = 0; col < storage.ColumnCount; col++) + { + var x = vector.At(col); + if (!Zero.Equals(x)) + { + values.Add(x); + columnIndices.Add(col); + } + } } + storage.ColumnIndices = columnIndices.ToArray(); + storage.Values = values.ToArray(); + storage.ValueCount = values.Count; + return storage; + } + + public static SparseCompressedRowMatrixStorage OfColumnVectors(VectorStorage[] data) + { + var storage = new SparseCompressedRowMatrixStorage(data[0].Length, data.Length); + var rowPointers = storage.RowPointers; + var columnIndices = new List(); + var values = new List(); + + // TODO PERF: Optimize for sparse and dense cases + for (int row = 0; row < storage.RowCount; row++) + { + rowPointers[row] = values.Count; + for (int col = 0; col < storage.ColumnCount; col++) + { + var x = data[col].At(row); + if (!Zero.Equals(x)) + { + values.Add(x); + columnIndices.Add(col); + } + } + } + + storage.ColumnIndices = columnIndices.ToArray(); + storage.Values = values.ToArray(); + storage.ValueCount = values.Count; + return storage; + } + + public static SparseCompressedRowMatrixStorage OfIndexedEnumerable(int rows, int columns, IEnumerable> data) + { var trows = new List>[rows]; foreach (var item in data) { @@ -478,8 +526,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage // NOTE: flexible typing to 'backport' generic covariance. where TRow : IEnumerable { - if (data == null) throw new ArgumentNullException("data"); - var storage = new SparseCompressedRowMatrixStorage(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List(); @@ -517,8 +563,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage // NOTE: flexible typing to 'backport' generic covariance. where TColumn : IEnumerable { - if (data == null) throw new ArgumentNullException("data"); - var trows = new List>[rows]; using (var columnIterator = data.GetEnumerator()) { @@ -570,11 +614,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage public static SparseCompressedRowMatrixStorage OfRowMajorEnumerable(int rows, int columns, IEnumerable data) { - if (data == null) - { - throw new ArgumentNullException("data"); - } - var storage = new SparseCompressedRowMatrixStorage(rows, columns); var rowPointers = storage.RowPointers; var columnIndices = new List(); @@ -605,10 +644,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage public static SparseCompressedRowMatrixStorage OfColumnMajorList(int rows, int columns, IList data) { - if (data == null) - { - throw new ArgumentNullException("data"); - } if (rows * columns != data.Count) { throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);