diff --git a/src/FSharp/Matrix.fs b/src/FSharp/Matrix.fs index 5a0d6f60..e783815e 100644 --- a/src/FSharp/Matrix.fs +++ b/src/FSharp/Matrix.fs @@ -46,6 +46,16 @@ module Matrix = acc <- f acc (A.Item(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 n-1 .. -1 .. 0 do + acc <- f (A.Item(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 diff --git a/src/FSharp/Vector.fs b/src/FSharp/Vector.fs index 62321c05..e8a08b24 100644 --- a/src/FSharp/Vector.fs +++ b/src/FSharp/Vector.fs @@ -93,6 +93,13 @@ module Vector = acc <- f acc (v.Item(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.Item(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 @@ -145,7 +152,7 @@ module Vector = w.[i] <- p w - /// Scans a vector; like fold but returns the intermediate result. + /// 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.Item(v.Count-1) @@ -161,7 +168,7 @@ module Vector = p <- f p (v.Item(i)) p - /// Reduces a vector: the result of this function will be f(v[1], ..., f(v[n-2], f(v[n-1],v[n]))...). + /// 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 diff --git a/src/FSharpUnitTests/Program.fs b/src/FSharpUnitTests/Program.fs index c7d5dfcd..48e6e899 100644 --- a/src/FSharpUnitTests/Program.fs +++ b/src/FSharpUnitTests/Program.fs @@ -75,7 +75,9 @@ let VectorTests = spec "Vector.mapi" (Vector.mapi (fun i x -> float i / 100.0) largev |> should equal largev) spec "Vector.fold" - (Vector.fold (fun a b -> a + b) 0.0 smallv |> should equal 1.5) + (Vector.fold (fun a b -> a - b) 0.0 smallv |> should equal -1.5) + spec "Vector.foldBack" + (Vector.foldBack (fun a b -> a - b) 0.0 smallv |> should equal 0.0) spec "Vector.foldi" (Vector.foldi (fun i a b -> a + b) 0.0 smallv |> should equal 1.5) spec "Vector.forall" @@ -90,9 +92,9 @@ let VectorTests = (Vector.scan (fun acc x -> acc + x) smallv |> should approximately_vector_equal 14 (new DenseVector( [|0.3;0.6;0.9;1.2;1.5|] ) :> Vector) ) spec "Vector.scanBack" (Vector.scanBack (fun x acc -> acc + x) smallv |> should approximately_vector_equal 14 (new DenseVector( [|1.5;1.2;0.9;0.6;0.3|] ) :> Vector) ) - spec "Vector.reduce_left" + spec "Vector.reduce" (Vector.reduce (fun acc x -> acc ** x) smallv |> should approximately_equal 14 0.990295218585507) - spec "Vector.reduce_right" + spec "Vector.reduceBack" (Vector.reduceBack (fun x acc -> x ** acc) smallv |> should approximately_equal 14 0.488911287726319) ] @@ -108,7 +110,9 @@ let MatrixTests = specs "Matrix" [ spec "Matrix.fold" - (Matrix.fold (fun a b -> a + b) 0.0 smallM |> should equal 1.2) + (Matrix.fold (fun a b -> a - b) 0.0 smallM |> should equal -1.2) + spec "Matrix.foldBack" + (Matrix.foldBack (fun a b -> a - b) 0.0 smallM |> should equal 0.0) spec "Matrix.foldi" (Matrix.foldi (fun i j acc x -> acc + x + float (i+j)) 0.0 smallM |> should equal 5.2) spec "Matrix.toArray2"