diff --git a/src/FSharp/FSharp.fsproj b/src/FSharp/FSharp.fsproj index 485af929..8c68a2e8 100644 --- a/src/FSharp/FSharp.fsproj +++ b/src/FSharp/FSharp.fsproj @@ -62,7 +62,6 @@ - @@ -74,6 +73,8 @@ + + diff --git a/src/FSharp/LinearAlgebra.Double.Matrix.fs b/src/FSharp/LinearAlgebra.Double.Matrix.fs index 2fd25abf..ee4fdd9a 100644 --- a/src/FSharp/LinearAlgebra.Double.Matrix.fs +++ b/src/FSharp/LinearAlgebra.Double.Matrix.fs @@ -36,161 +36,14 @@ open MathNet.Numerics.LinearAlgebra [] module Matrix = - /// Transform a vector into a 2D array. - let inline toArray2 (A: #Matrix) = A.ToArray() - - /// In-place map of every matrix element using a function. - let inline mapInPlace (f: float -> float) (A: #Matrix) = - A.MapInplace((fun x -> f x), true) - - /// In-place map of every matrix element using a position dependent function. - let inline mapiInPlace (f: int -> int -> float -> float) (A: #Matrix) = - A.MapIndexedInplace((fun i j x -> f i j x), true) - - /// In-place map of every matrix element using a function. - /// Zero-values may be skipped (relevant mostly for sparse matrices). - let inline mapnzInPlace (f: float -> float) (A: #Matrix) = - A.MapInplace((fun x -> f x), false) - - /// In-place map of every matrix element using a position dependent function. - /// Zero-values may be skipped (relevant mostly for sparse matrices). - let inline mapinzInPlace (f: int -> int -> float -> float) (A: #Matrix) = - A.MapIndexedInplace((fun i j x -> f i j x), false) - - /// In-place map every matrix column using the given position dependent function. - let inline mapColsInPlace (f: int -> Vector -> Vector) (A: #Matrix) = - for j = 0 to A.ColumnCount-1 do - A.SetColumn(j, f j (A.Column(j))) - - /// In-place map every matrix row using the given position dependent function. - let inline mapRowsInPlace (f: int -> Vector -> Vector) (A: #Matrix) = - for i = 0 to A.RowCount-1 do - A.SetRow(i, f i (A.Row(i))) - - /// Map every matrix element using the given function. - let inline map (f: float -> float) (A: #Matrix) = - let A = A.Clone() - A.MapInplace((fun x -> f x), true) - A - - /// Map every matrix element using the given function. - /// Zero-values may be skipped (relevant mostly for sparse matrices). - let inline mapnz (f: float -> float) (A: #Matrix) = - let A = A.Clone() - A.MapInplace((fun x -> f x), false) - A - - /// Map every matrix element using the given position dependent function. - let inline mapi (f: int -> int -> float -> float) (A: #Matrix) = - let A = A.Clone() - A.MapIndexedInplace((fun i j x -> f i j x), true) - A - - /// Map every matrix element using the given position dependent function. - /// Zero-values may be skipped (relevant mostly for sparse matrices). - let inline mapinz (f: int -> int -> float -> float) (A: #Matrix) = - let A = A.Clone() - A.MapIndexedInplace((fun i j x -> f i j x), false) - A - - /// Map every matrix column using the given position dependent function. - let inline mapCols (f: int -> Vector -> Vector) (A: #Matrix) = - let A = A.Clone() - mapColsInPlace f A - A - - /// Map every matrix row using the given position dependent function. - let inline mapRows (f: int -> Vector -> Vector) (A: #Matrix) = - let A = A.Clone() - mapRowsInPlace f A - A - - /// Fold a function over all matrix elements. - let inline fold (f: 'a -> float -> 'a) (acc0: 'a) (A: #Matrix) = - let n = A.RowCount - let m = A.ColumnCount - let mutable acc = acc0 - for i=0 to n-1 do - for j=0 to m-1 do - acc <- f acc (A.At(i,j)) - acc - - /// Fold a function over all matrix elements in reverse order. - let inline foldBack (f: float -> 'a -> 'a) (acc0: 'a) (A: #Matrix) = - let n = A.RowCount - let m = A.ColumnCount - let mutable acc = acc0 - for i in n-1 .. -1 .. 0 do - for j in m-1 .. -1 .. 0 do - acc <- f (A.At(i,j)) acc - acc - - /// Fold a matrix by applying a given function to all matrix elements. - let inline foldi (f: int -> int -> 'a -> float -> 'a) (acc0: 'a) (A: #Matrix) = - let n = A.RowCount - let m = A.ColumnCount - let mutable acc = acc0 - for i=0 to n-1 do - for j=0 to m-1 do - acc <- f i j acc (A.At(i,j)) - acc - - /// Checks whether a predicate holds for all elements of a matrix. - let inline forall (p: float -> bool) (A: #Matrix) = - let mutable b = true - let mutable i = 0 - let mutable j = 0 - while b && i < A.RowCount do - b <- b && (p (A.At(i,j))) - j <- j+1 - if j = A.ColumnCount then i <- i+1; j <- 0 - b - - /// Chechks whether a predicate holds for at least one element of a matrix. - let inline exists (p: float -> bool) (A: #Matrix) = - let mutable b = false - let mutable i = 0 - let mutable j = 0 - while not(b) && i < A.RowCount do - b <- b || (p (A.At(i,j))) - j <- j+1 - if j = A.ColumnCount then i <- i+1; j <- 0 - b - - /// Checks whether a position dependent predicate holds for all elements of a matrix. - let inline foralli (p: int -> int -> float -> bool) (A: #Matrix) = - let mutable b = true - let mutable i = 0 - let mutable j = 0 - while b && i < A.RowCount do - b <- b && (p i j (A.At(i,j))) - j <- j+1 - if j = A.ColumnCount then i <- i+1; j <- 0 - b - - /// Checks whether a position dependent predicate holds for at least one element of a matrix. - let inline existsi (p: int -> int -> float -> bool) (A: #Matrix) = - let mutable b = false - let mutable i = 0 - let mutable j = 0 - while not(b) && i < A.RowCount do - b <- b || (p i j (A.At(i,j))) - j <- j+1 - if j = A.ColumnCount then i <- i+1; j <- 0 - b - - /// In-place assignment. - let inline inplaceAssign (f: int -> int -> float) (A: #Matrix) = - A.MapIndexedInplace((fun i j x -> f i j), true) - /// Creates a sequence that iterates the non-zero entries in the matrix. - let inline nonZeroEntries (A: #Matrix) = + let inline nonZeroEntries (A: #Matrix<_>) = seq { for i in 0 .. A.RowCount-1 do for j in 0 .. A.ColumnCount-1 do if A.At(i,j) <> 0.0 then yield (i, j, A.At(i,j)) } /// Returns the sum of all elements of a matrix. - let inline sum (A: #Matrix) = + let inline sum (A: #Matrix<_>) = let mutable f = 0.0 for i=0 to A.RowCount-1 do for j=0 to A.ColumnCount-1 do @@ -198,39 +51,13 @@ module Matrix = f /// Returns the sum of the results generated by applying a position dependent function to each column of the matrix. - let inline sumColsBy (f: int -> Vector -> 'a) (A: #Matrix) = + let inline sumColsBy (f: int -> Vector -> 'a) (A: #Matrix<_>) = A.ColumnEnumerator() |> Seq.map (fun (j,col) -> f j col) |> Seq.reduce (+) /// Returns the sum of the results generated by applying a position dependent function to each row of the matrix. - let inline sumRowsBy (f: int -> Vector -> 'a) (A: #Matrix) = + let inline sumRowsBy (f: int -> Vector -> 'a) (A: #Matrix<_>) = A.RowEnumerator() |> Seq.map (fun (i,row) -> f i row) |> Seq.reduce (+) - /// Iterates over all elements of a matrix. - let inline iter (f: float -> unit) (A: #Matrix) = - for i=0 to A.RowCount-1 do - for j=0 to A.ColumnCount-1 do - f (A.At(i,j)) - - /// Iterates over all elements of a matrix using the element indices. - let inline iteri (f: int -> int -> float -> unit) (A: #Matrix) = - for i=0 to A.RowCount-1 do - for j=0 to A.ColumnCount-1 do - f i j (A.At(i,j)) - - /// Fold one column. - let inline foldCol (f: 'a -> float -> 'a) acc (A: #Matrix) k = - let mutable macc = acc - for i=0 to A.RowCount-1 do - macc <- f macc (A.Item(i,k)) - macc - - /// Fold one row. - let inline foldRow (f: 'a -> float -> 'a) acc (A: #Matrix) k = - let mutable macc = acc - for i=0 to A.ColumnCount-1 do - macc <- f macc (A.Item(k,i)) - macc - /// Fold all columns into one row vector. let inline foldByCol (f: float -> float -> float) acc (A: #Matrix) = let v = new DenseVector(A.ColumnCount) diff --git a/src/FSharp/LinearAlgebra.Double.Vector.fs b/src/FSharp/LinearAlgebra.Double.Vector.fs index 4c2606ad..a6d6b7b3 100644 --- a/src/FSharp/LinearAlgebra.Double.Vector.fs +++ b/src/FSharp/LinearAlgebra.Double.Vector.fs @@ -36,162 +36,6 @@ open MathNet.Numerics.LinearAlgebra [] module Vector = - /// Transform a vector into an array. - let inline toArray (v: #Vector) = v.ToArray() - - /// Transform a vector into a list. - let inline toList (v: #Vector) = List.init v.Count v.At - - /// In-place mutation by applying a function to every element of the vector. - let inline mapInPlace (f: float -> float) (v: #Vector) = - v.MapInplace((fun x -> f x), true) - - /// In-place mutation by applying a function to every element of the vector. - let inline mapiInPlace (f: int -> float -> float) (v: #Vector) = - v.MapIndexedInplace((fun i x -> f i x), true) - - /// In-place mutation by applying a function to every element of the vector. - /// Zero-values may be skipped (relevant mostly for sparse vectors). - let inline mapnzInPlace (f: float -> float) (v: #Vector) = - v.MapInplace((fun x -> f x), false) - - /// In-place mutation by applying a function to every element of the vector. - /// Zero-values may be skipped (relevant mostly for sparse vectors). - let inline mapinzInPlace (f: int -> float -> float) (v: #Vector) = - v.MapIndexedInplace((fun i x -> f i x), false) - - /// Maps a vector to a new vector by applying a function to every element. - let inline map f (v: #Vector) = - let w = v.Clone() - w.MapInplace((fun x -> f x), true) - w - - /// Maps a vector to a new vector by applying a function to every element. - /// Zero-values may be skipped (relevant mostly for sparse vectors). - let inline mapnz f (v: #Vector) = - let w = v.Clone() - w.MapInplace((fun x -> f x), false) - w - - /// Maps a vector to a new vector by applying a function to every element. - let inline mapi (f: int -> float -> float) (v: #Vector) = - let w = v.Clone() - w.MapIndexedInplace((fun i x -> f i x), true) - w - - /// Maps a vector to a new vector by applying a function to every element. - /// Zero-values may be skipped (relevant mostly for sparse vectors). - let inline mapinz (f: int -> float -> float) (v: #Vector) = - let w = v.Clone() - w.MapIndexedInplace((fun i x -> f i x), false) - w - - /// In-place vector addition. - let inline addInPlace (v: #Vector) (w: #Vector) = v.Add(w, v) - - /// In place vector subtraction. - let inline subInPlace (v: #Vector) (w: #Vector) = v.Subtract(w, v) - - /// Applies a function to all elements of the vector. - let inline iter (f: float -> unit) (v: #Vector) = - for i=0 to v.Count-1 do - f (v.At i) - - /// Applies a function to all elements of the vector. - let inline iteri (f: int -> float -> unit) (v: #Vector) = - for i=0 to v.Count-1 do - f i (v.At i) - - - /// Fold all entries of a vector. - let inline fold (f: 'a -> float -> 'a) (acc0: 'a) (v: #Vector) = - let mutable acc = acc0 - for i=0 to v.Count-1 do - acc <- f acc (v.At i) - acc - - /// Fold all entries of a vector in reverse order. - let inline foldBack (f: float -> 'a -> 'a) (acc0: 'a) (v: #Vector) = - let mutable acc = acc0 - for i=2 to v.Count do - acc <- f (v.At (v.Count - i)) acc - acc - - /// Fold all entries of a vector using a position dependent folding function. - let inline foldi (f: int -> 'a -> float -> 'a) (acc0: 'a) (v: #Vector) = - let mutable acc = acc0 - for i=0 to v.Count-1 do - acc <- f i acc (v.At i) - acc - - /// Checks whether a predicate is satisfied for every element in the vector. - let inline forall (p: float -> bool) (v: #Vector) = - let mutable b = true - let mutable i = 0 - while b && i < v.Count do - b <- b && (p (v.At i)) - i <- i+1 - b - - /// Checks whether there is an entry in the vector that satisfies a given predicate. - let inline exists (p: float -> bool) (v: #Vector) = - let mutable b = false - let mutable i = 0 - while not(b) && i < v.Count do - b <- b || (p (v.At i)) - i <- i+1 - b - - /// Checks whether a predicate is true for all entries in a vector. - let inline foralli (p: int -> float -> bool) (v: #Vector) = - let mutable b = true - let mutable i = 0 - while b && i < v.Count do - b <- b && (p i (v.At i)) - i <- i+1 - b - - /// Checks whether there is an entry in the vector that satisfies a given position dependent predicate. - let inline existsi (p: int -> float -> bool) (v: #Vector) = - let mutable b = false - let mutable i = 0 - while not(b) && i < v.Count do - b <- b || (p i (v.At i)) - i <- i+1 - b - - /// Scans a vector; like fold but returns the intermediate result. - let inline scan (f: float -> float -> float) (v: #Vector) = - let w = v.Clone() - let mutable p = v.Item(0) - for i=1 to v.Count-1 do - p <- f p (v.At i) - w.At(i, p) - w - - /// Scans a vector in reverse order; like foldBack but returns the intermediate result. - let inline scanBack (f: float -> float -> float) (v: #Vector) = - let w = v.Clone() - let mutable p = v.At (v.Count-1) - for i=2 to v.Count do - p <- f (v.At (v.Count - i)) p - w.At(v.Count - i, p) - w - - /// Reduces a vector: the result of this function will be f(...f(f(v[0],v[1]), v[2]),..., v[n]). - let inline reduce (f: float -> float -> float) (v: #Vector) = - let mutable p = v.Item(0) - for i=1 to v.Count-1 do - p <- f p (v.At i) - p - - /// Reduces a vector in reverse order: the result of this function will be f(v[1], ..., f(v[n-2], f(v[n-1],v[n]))...). - let inline reduceBack (f: float -> float -> float) (v: #Vector) = - let mutable p = v.Item(v.Count-1) - for i=2 to v.Count do - p <- f (v.At (v.Count - i)) p - p - /// 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) diff --git a/src/FSharp/LinearAlgebra.Double.fs b/src/FSharp/LinearAlgebra.Double.fs index 77dd36cd..5f3adb33 100644 --- a/src/FSharp/LinearAlgebra.Double.fs +++ b/src/FSharp/LinearAlgebra.Double.fs @@ -37,7 +37,7 @@ open MathNet.Numerics.LinearAlgebra module Utility = /// Construct a dense matrix from a list of floating point numbers. - let inline matrix (lst: list>) = DenseMatrix.ofList lst :> Matrix + let inline matrix (lst: list>) = DenseMatrix.ofList lst /// Construct a dense vector from a list of floating point numbers. - let inline vector (lst: list) = DenseVector.ofList lst :> Vector + let inline vector (lst: list) = DenseVector.ofList lst diff --git a/src/FSharp/LinearAlgebra.Matrix.fs b/src/FSharp/LinearAlgebra.Matrix.fs new file mode 100644 index 00000000..d2846fd5 --- /dev/null +++ b/src/FSharp/LinearAlgebra.Matrix.fs @@ -0,0 +1,268 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// Copyright (c) 2009-2013 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 + +/// Module that contains implementation of useful F#-specific extension members for generic matrices +[] +module MatrixExtensions = + + // A type extension for the generic matrix type that + // adds the 'GetSlice' method to allow m.[r1 .. r2, c1 .. c2] syntax + type MathNet.Numerics.LinearAlgebra. + Matrix<'T when 'T : struct and 'T : (new : unit -> 'T) + and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable + and 'T :> System.ValueType> with + + /// Gets a submatrix using a specified column range and + /// row range (all indices are optional) + /// This method can be used via the x.[r1 .. r2, c1 .. c2 ] syntax + member x.GetSlice(rstart, rfinish, cstart, cfinish) = + let cstart = defaultArg cstart 0 + let rstart = defaultArg rstart 0 + let cfinish = defaultArg cfinish (x.ColumnCount - 1) + let rfinish = defaultArg rfinish (x.RowCount - 1) + x.SubMatrix(rstart, rfinish - rstart + 1, cstart, cfinish - cstart + 1) + + /// Sets a submatrix using a specified column range and + /// row range (all indices are optional) + /// This method can be used via the x.[r1 .. r2, c1 .. c2 ] <- m syntax + member x.SetSlice(rstart, rfinish, cstart, cfinish, values) = + let cstart = defaultArg cstart 0 + let rstart = defaultArg rstart 0 + let cfinish = defaultArg cfinish (x.ColumnCount - 1) + let rfinish = defaultArg rfinish (x.RowCount - 1) + x.SetSubMatrix(rstart, rfinish - rstart + 1, cstart, cfinish - cstart + 1, values) + + /// Gets a row subvector using a specified row index and column range. + /// This method can be used via the x.[r, c1 .. c2] syntax (F#3.1) + member x.GetSlice(r, cstart, cfinish) = + let cstart = defaultArg cstart 0 + let cfinish = defaultArg cfinish (x.ColumnCount - 1) + x.Row(r, cstart, cfinish - cstart + 1) + + /// Gets a column subvector using a specified row index and column range. + /// This method can be used via the x.[r1 .. r2, c] syntax (F#3.1) + member x.GetSlice(rstart, rfinish, c) = + let rstart = defaultArg rstart 0 + let rfinish = defaultArg rfinish (x.RowCount - 1) + x.Column(c, rstart, rfinish - rstart + 1) + + /// Sets a row subvector using a specified row index and column range. + /// This method can be used via the x.[r, c1 .. c2] <- v syntax (F#3.1) + member x.SetSlice(r, cstart, cfinish, values) = + let cstart = defaultArg cstart 0 + let cfinish = defaultArg cfinish (x.ColumnCount - 1) + x.SetRow(r, cstart, cfinish - cstart + 1, values) + + /// Sets a column subvector using a specified row index and column range. + /// This method can be used via the x.[r1 .. r2, c] <- v syntax (F#3.1) + member x.SetSlice(rstart, rfinish, c, values) = + let rstart = defaultArg rstart 0 + let rfinish = defaultArg rfinish (x.RowCount - 1) + x.SetColumn(c, rstart, rfinish - rstart + 1, values) + + +/// A module which implements functional matrix operations. +[] +module Matrix = + + /// Transform a vector into a 2D array. + let inline toArray2 (A: #Matrix<_>) = A.ToArray() + + /// In-place map of every matrix element using a function. + let inline mapInPlace f (A: #Matrix<_>) = + A.MapInplace((fun x -> f x), true) + + /// In-place map of every matrix element using a position dependent function. + let inline mapiInPlace f (A: #Matrix<_>) = + A.MapIndexedInplace((fun i j x -> f i j x), true) + + /// In-place map of every matrix element using a function. + /// Zero-values may be skipped (relevant mostly for sparse matrices). + let inline mapnzInPlace f (A: #Matrix<_>) = + A.MapInplace((fun x -> f x), false) + + /// In-place map of every matrix element using a position dependent function. + /// Zero-values may be skipped (relevant mostly for sparse matrices). + let inline mapinzInPlace f (A: #Matrix<_>) = + A.MapIndexedInplace((fun i j x -> f i j x), false) + + /// In-place map every matrix column using the given position dependent function. + let inline mapColsInPlace (f: int -> Vector<'a> -> Vector<'a>) (A: #Matrix<_>) = + for j = 0 to A.ColumnCount-1 do + A.SetColumn(j, f j (A.Column(j))) + + /// In-place map every matrix row using the given position dependent function. + let inline mapRowsInPlace (f: int -> Vector<'a> -> Vector<'a>) (A: #Matrix<_>) = + for i = 0 to A.RowCount-1 do + A.SetRow(i, f i (A.Row(i))) + + /// Map every matrix element using the given function. + let inline map f (A: #Matrix<_>) = + let A = A.Clone() + A.MapInplace((fun x -> f x), true) + A + + /// Map every matrix element using the given function. + /// Zero-values may be skipped (relevant mostly for sparse matrices). + let inline mapnz f (A: #Matrix<_>) = + let A = A.Clone() + A.MapInplace((fun x -> f x), false) + A + + /// Map every matrix element using the given position dependent function. + let inline mapi f (A: #Matrix<_>) = + let A = A.Clone() + A.MapIndexedInplace((fun i j x -> f i j x), true) + A + + /// Map every matrix element using the given position dependent function. + /// Zero-values may be skipped (relevant mostly for sparse matrices). + let inline mapinz f (A: #Matrix<_>) = + let A = A.Clone() + A.MapIndexedInplace((fun i j x -> f i j x), false) + A + + /// Map every matrix column using the given position dependent function. + let inline mapCols (f: int -> Vector<'a> -> Vector<'a>) (A: #Matrix<_>) = + let A = A.Clone() + mapColsInPlace f A + A + + /// Map every matrix row using the given position dependent function. + let inline mapRows (f: int -> Vector<'a> -> Vector<'a>) (A: #Matrix<_>) = + let A = A.Clone() + mapRowsInPlace f A + A + + /// Fold a function over all matrix elements. + let inline fold f acc0 (A: #Matrix<_>) = + let n = A.RowCount + let m = A.ColumnCount + let mutable acc = acc0 + for i=0 to n-1 do + for j=0 to m-1 do + acc <- f acc (A.At(i,j)) + acc + + /// Fold a function over all matrix elements in reverse order. + let inline foldBack f acc0 (A: #Matrix<_>) = + let n = A.RowCount + let m = A.ColumnCount + let mutable acc = acc0 + for i in n-1 .. -1 .. 0 do + for j in m-1 .. -1 .. 0 do + acc <- f (A.At(i,j)) acc + acc + + /// Fold a matrix by applying a given function to all matrix elements. + let inline foldi f acc0 (A: #Matrix<_>) = + let n = A.RowCount + let m = A.ColumnCount + let mutable acc = acc0 + for i=0 to n-1 do + for j=0 to m-1 do + acc <- f i j acc (A.At(i,j)) + acc + + /// Checks whether a predicate holds for all elements of a matrix. + let inline forall p (A: #Matrix<_>) = + let mutable b = true + let mutable i = 0 + let mutable j = 0 + while b && i < A.RowCount do + b <- b && (p (A.At(i,j))) + j <- j+1 + if j = A.ColumnCount then i <- i+1; j <- 0 + b + + /// Chechks whether a predicate holds for at least one element of a matrix. + let inline exists p (A: #Matrix<_>) = + let mutable b = false + let mutable i = 0 + let mutable j = 0 + while not(b) && i < A.RowCount do + b <- b || (p (A.At(i,j))) + j <- j+1 + if j = A.ColumnCount then i <- i+1; j <- 0 + b + + /// Checks whether a position dependent predicate holds for all elements of a matrix. + let inline foralli p (A: #Matrix<_>) = + let mutable b = true + let mutable i = 0 + let mutable j = 0 + while b && i < A.RowCount do + b <- b && (p i j (A.At(i,j))) + j <- j+1 + if j = A.ColumnCount then i <- i+1; j <- 0 + b + + /// Checks whether a position dependent predicate holds for at least one element of a matrix. + let inline existsi p (A: #Matrix<_>) = + let mutable b = false + let mutable i = 0 + let mutable j = 0 + while not(b) && i < A.RowCount do + b <- b || (p i j (A.At(i,j))) + j <- j+1 + if j = A.ColumnCount then i <- i+1; j <- 0 + b + + /// In-place assignment. + let inline inplaceAssign f (A: #Matrix<_>) = + A.MapIndexedInplace((fun i j x -> f i j), true) + + /// Iterates over all elements of a matrix. + let inline iter f (A: #Matrix<_>) = + for i=0 to A.RowCount-1 do + for j=0 to A.ColumnCount-1 do + f (A.At(i,j)) + + /// Iterates over all elements of a matrix using the element indices. + let inline iteri f (A: #Matrix<_>) = + for i=0 to A.RowCount-1 do + for j=0 to A.ColumnCount-1 do + f i j (A.At(i,j)) + + /// Fold one column. + let inline foldCol f acc (A: #Matrix<_>) k = + let mutable macc = acc + for i=0 to A.RowCount-1 do + macc <- f macc (A.Item(i,k)) + macc + + /// Fold one row. + let inline foldRow f acc (A: #Matrix<_>) k = + let mutable macc = acc + for i=0 to A.ColumnCount-1 do + macc <- f macc (A.Item(k,i)) + macc diff --git a/src/FSharp/LinearAlgebra.Vector.fs b/src/FSharp/LinearAlgebra.Vector.fs new file mode 100644 index 00000000..1b2ebf60 --- /dev/null +++ b/src/FSharp/LinearAlgebra.Vector.fs @@ -0,0 +1,220 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// Copyright (c) 2009-2013 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 + +/// Module that contains implementation of useful F#-specific extension members for generic vectors +[] +module VectorExtensions = + + // A type extension for the generic vector type that + // adds the 'GetSlice' method to allow vec.[a .. b] syntax + type MathNet.Numerics.LinearAlgebra. + Vector<'T when 'T : struct and 'T : (new : unit -> 'T) + and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable + and 'T :> System.ValueType> with + + /// Gets a slice of a vector starting at a specified index + /// and ending at a specified index (both indices are optional) + /// This method can be used via the x.[start .. finish] syntax + member x.GetSlice(start, finish) = + let start = defaultArg start 0 + let finish = defaultArg finish (x.Count - 1) + x.SubVector(start, finish - start + 1) + + /// Sets a slice of a vector starting at a specified index + /// and ending at a specified index (both indices are optional) + /// This method can be used via the x.[start .. finish] <- v syntax + member x.SetSlice(start, finish, values) = + let start = defaultArg start 0 + let finish = defaultArg finish (x.Count - 1) + x.SetSubVector(start, finish - start + 1, values) + + +/// A module which implements functional vector operations. +[] +module Vector = + + /// Transform a vector into an array. + let inline toArray (v: #Vector<_>) = v.ToArray() + + /// Transform a vector into a list. + let inline toList (v: #Vector<_>) = List.init v.Count v.At + + /// In-place mutation by applying a function to every element of the vector. + let inline mapInPlace f (v: #Vector<_>) = + v.MapInplace((fun x -> f x), true) + + /// In-place mutation by applying a function to every element of the vector. + let inline mapiInPlace f (v: #Vector<_>) = + v.MapIndexedInplace((fun i x -> f i x), true) + + /// In-place mutation by applying a function to every element of the vector. + /// Zero-values may be skipped (relevant mostly for sparse vectors). + let inline mapnzInPlace f (v: #Vector<_>) = + v.MapInplace((fun x -> f x), false) + + /// In-place mutation by applying a function to every element of the vector. + /// Zero-values may be skipped (relevant mostly for sparse vectors). + let inline mapinzInPlace (f: int -> float -> float) (v: #Vector) = + v.MapIndexedInplace((fun i x -> f i x), false) + + /// Maps a vector to a new vector by applying a function to every element. + let inline map f (v: #Vector<_>) = + let w = v.Clone() + w.MapInplace((fun x -> f x), true) + w + + /// Maps a vector to a new vector by applying a function to every element. + /// Zero-values may be skipped (relevant mostly for sparse vectors). + let inline mapnz f (v: #Vector<_>) = + let w = v.Clone() + w.MapInplace((fun x -> f x), false) + w + + /// Maps a vector to a new vector by applying a function to every element. + let inline mapi f (v: #Vector<_>) = + let w = v.Clone() + w.MapIndexedInplace((fun i x -> f i x), true) + w + + /// Maps a vector to a new vector by applying a function to every element. + /// Zero-values may be skipped (relevant mostly for sparse vectors). + let inline mapinz f (v: #Vector<_>) = + let w = v.Clone() + w.MapIndexedInplace((fun i x -> f i x), false) + w + + /// In-place vector addition. + let inline addInPlace (v: #Vector<_>) (w: #Vector<_>) = v.Add(w, v) + + /// In place vector subtraction. + let inline subInPlace (v: #Vector<_>) (w: #Vector<_>) = v.Subtract(w, v) + + /// Applies a function to all elements of the vector. + let inline iter f (v: #Vector<_>) = + for i=0 to v.Count-1 do + f (v.At i) + + /// Applies a function to all elements of the vector. + let inline iteri f (v: #Vector<_>) = + for i=0 to v.Count-1 do + f i (v.At i) + + + /// Fold all entries of a vector. + let inline fold f acc0 (v: #Vector<_>) = + let mutable acc = acc0 + for i=0 to v.Count-1 do + acc <- f acc (v.At i) + acc + + /// Fold all entries of a vector in reverse order. + let inline foldBack f acc0 (v: #Vector<_>) = + let mutable acc = acc0 + for i=2 to v.Count do + acc <- f (v.At (v.Count - i)) acc + acc + + /// Fold all entries of a vector using a position dependent folding function. + let inline foldi f acc0 (v: #Vector<_>) = + let mutable acc = acc0 + for i=0 to v.Count-1 do + acc <- f i acc (v.At i) + acc + + /// Checks whether a predicate is satisfied for every element in the vector. + let inline forall p (v: #Vector<_>) = + let mutable b = true + let mutable i = 0 + while b && i < v.Count do + b <- b && (p (v.At i)) + i <- i+1 + b + + /// Checks whether there is an entry in the vector that satisfies a given predicate. + let inline exists p (v: #Vector<_>) = + let mutable b = false + let mutable i = 0 + while not(b) && i < v.Count do + b <- b || (p (v.At i)) + i <- i+1 + b + + /// Checks whether a predicate is true for all entries in a vector. + let inline foralli p (v: #Vector<_>) = + let mutable b = true + let mutable i = 0 + while b && i < v.Count do + b <- b && (p i (v.At i)) + i <- i+1 + b + + /// Checks whether there is an entry in the vector that satisfies a given position dependent predicate. + let inline existsi p (v: #Vector<_>) = + let mutable b = false + let mutable i = 0 + while not(b) && i < v.Count do + b <- b || (p i (v.At i)) + i <- i+1 + b + + /// Scans a vector; like fold but returns the intermediate result. + let inline scan f (v: #Vector<_>) = + let w = v.Clone() + let mutable p = v.Item(0) + for i=1 to v.Count-1 do + p <- f p (v.At i) + w.At(i, p) + w + + /// Scans a vector in reverse order; like foldBack but returns the intermediate result. + let inline scanBack f (v: #Vector<_>) = + let w = v.Clone() + let mutable p = v.At (v.Count-1) + for i=2 to v.Count do + p <- f (v.At (v.Count - i)) p + w.At(v.Count - i, p) + w + + /// Reduces a vector: the result of this function will be f(...f(f(v[0],v[1]), v[2]),..., v[n]). + let inline reduce f (v: #Vector<_>) = + let mutable p = v.Item(0) + for i=1 to v.Count-1 do + p <- f p (v.At i) + p + + /// Reduces a vector in reverse order: the result of this function will be f(v[1], ..., f(v[n-2], f(v[n-1],v[n]))...). + let inline reduceBack f (v: #Vector<_>) = + let mutable p = v.Item(v.Count-1) + for i=2 to v.Count do + p <- f (v.At (v.Count - i)) p + p + diff --git a/src/FSharp/LinearAlgebra.fs b/src/FSharp/LinearAlgebra.fs deleted file mode 100644 index e348f464..00000000 --- a/src/FSharp/LinearAlgebra.fs +++ /dev/null @@ -1,115 +0,0 @@ -// -// Math.NET Numerics, part of the Math.NET Project -// http://numerics.mathdotnet.com -// http://github.com/mathnet/mathnet-numerics -// http://mathnetnumerics.codeplex.com -// -// Copyright (c) 2009-2013 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 - -// Module that contains implementation of useful F#-specific -// extension members for generic Matrix and Vector types -[] -module FSharpExtensions = - - // A type extension for the generic vector type that - // adds the 'GetSlice' method to allow vec.[a .. b] syntax - type MathNet.Numerics.LinearAlgebra. - Vector<'T when 'T : struct and 'T : (new : unit -> 'T) - and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable - and 'T :> System.ValueType> with - - /// Gets a slice of a vector starting at a specified index - /// and ending at a specified index (both indices are optional) - /// This method can be used via the x.[start .. finish] syntax - member x.GetSlice(start, finish) = - let start = defaultArg start 0 - let finish = defaultArg finish (x.Count - 1) - x.SubVector(start, finish - start + 1) - - /// Sets a slice of a vector starting at a specified index - /// and ending at a specified index (both indices are optional) - /// This method can be used via the x.[start .. finish] <- v syntax - member x.SetSlice(start, finish, values) = - let start = defaultArg start 0 - let finish = defaultArg finish (x.Count - 1) - x.SetSubVector(start, finish - start + 1, values) - - - // A type extension for the generic matrix type that - // adds the 'GetSlice' method to allow m.[r1 .. r2, c1 .. c2] syntax - type MathNet.Numerics.LinearAlgebra. - Matrix<'T when 'T : struct and 'T : (new : unit -> 'T) - and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable - and 'T :> System.ValueType> with - - /// Gets a submatrix using a specified column range and - /// row range (all indices are optional) - /// This method can be used via the x.[r1 .. r2, c1 .. c2 ] syntax - member x.GetSlice(rstart, rfinish, cstart, cfinish) = - let cstart = defaultArg cstart 0 - let rstart = defaultArg rstart 0 - let cfinish = defaultArg cfinish (x.ColumnCount - 1) - let rfinish = defaultArg rfinish (x.RowCount - 1) - x.SubMatrix(rstart, rfinish - rstart + 1, cstart, cfinish - cstart + 1) - - /// Sets a submatrix using a specified column range and - /// row range (all indices are optional) - /// This method can be used via the x.[r1 .. r2, c1 .. c2 ] <- m syntax - member x.SetSlice(rstart, rfinish, cstart, cfinish, values) = - let cstart = defaultArg cstart 0 - let rstart = defaultArg rstart 0 - let cfinish = defaultArg cfinish (x.ColumnCount - 1) - let rfinish = defaultArg rfinish (x.RowCount - 1) - x.SetSubMatrix(rstart, rfinish - rstart + 1, cstart, cfinish - cstart + 1, values) - - /// Gets a row subvector using a specified row index and column range. - /// This method can be used via the x.[r, c1 .. c2] syntax (F#3.1) - member x.GetSlice(r, cstart, cfinish) = - let cstart = defaultArg cstart 0 - let cfinish = defaultArg cfinish (x.ColumnCount - 1) - x.Row(r, cstart, cfinish - cstart + 1) - - /// Gets a column subvector using a specified row index and column range. - /// This method can be used via the x.[r1 .. r2, c] syntax (F#3.1) - member x.GetSlice(rstart, rfinish, c) = - let rstart = defaultArg rstart 0 - let rfinish = defaultArg rfinish (x.RowCount - 1) - x.Column(c, rstart, rfinish - rstart + 1) - - /// Sets a row subvector using a specified row index and column range. - /// This method can be used via the x.[r, c1 .. c2] <- v syntax (F#3.1) - member x.SetSlice(r, cstart, cfinish, values) = - let cstart = defaultArg cstart 0 - let cfinish = defaultArg cfinish (x.ColumnCount - 1) - x.SetRow(r, cstart, cfinish - cstart + 1, values) - - /// Sets a column subvector using a specified row index and column range. - /// This method can be used via the x.[r1 .. r2, c] <- v syntax (F#3.1) - member x.SetSlice(rstart, rfinish, c, values) = - let rstart = defaultArg rstart 0 - let rfinish = defaultArg rfinish (x.RowCount - 1) - x.SetColumn(c, rstart, rfinish - rstart + 1, values)