From d4c13af568ffeeacc9c7ec26fa6b139181288541 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sat, 26 Jul 2014 18:04:14 +0200 Subject: [PATCH] LA: F# Vector.map2 module function --- src/FSharp/LinearAlgebra.Vector.fs | 8 + .../Storage/SparseVectorStorage.cs | 1 - .../LinearAlgebraTests/VectorStorageTests.cs | 141 ++++++++++++++---- 3 files changed, 122 insertions(+), 28 deletions(-) diff --git a/src/FSharp/LinearAlgebra.Vector.fs b/src/FSharp/LinearAlgebra.Vector.fs index 301dae77..ab3b2e2d 100644 --- a/src/FSharp/LinearAlgebra.Vector.fs +++ b/src/FSharp/LinearAlgebra.Vector.fs @@ -161,6 +161,14 @@ module Vector = let inline mapiSkipZeros f (v: #Vector<_>) = v.MapIndexed((fun i x -> f i x), Zeros.AllowSkip) + /// Maps two vectors to a new vector by applying a function to every element pair. + let inline map2 f (u: #Vector<_>) (v: #Vector<_>) = u.Map2((fun x y -> f x y), v, Zeros.Include) + + /// Maps two vectors to a new vector by applying a function to every element pair. + /// Zero-Zero value-pairs may be skipped (relevant mostly for sparse vectors). + let inline map2SkipZeros f (u: #Vector<_>) (v: #Vector<_>) = u.Map2((fun x y -> f x y), v, Zeros.AllowSkip) + + /// Fold all entries of a vector in reverse order. let inline foldBack f state (v: #Vector<_>) = diff --git a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs index eb95135f..7ddc7501 100644 --- a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs @@ -897,7 +897,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage } else { - Debug.Assert(Indices[p] == otherIndices[q]); var value = f(Values[p], otherValues[q]); if (!Zero.Equals(value)) { diff --git a/src/UnitTests/LinearAlgebraTests/VectorStorageTests.cs b/src/UnitTests/LinearAlgebraTests/VectorStorageTests.cs index 87e6637d..79687772 100644 --- a/src/UnitTests/LinearAlgebraTests/VectorStorageTests.cs +++ b/src/UnitTests/LinearAlgebraTests/VectorStorageTests.cs @@ -38,7 +38,94 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests public class VectorStorageTests { [Test] - public void Map2SkipZeros() + public void MapToSkipZeros() + { + double[] a = { 1.0, 2.0, 0.0, 4.0 }; + var adense = DenseVectorStorage.OfEnumerable(a); + var asparse = SparseVectorStorage.OfEnumerable(a); + + var rdense = new DenseVectorStorage(a.Length); + var rsparse = new SparseVectorStorage(a.Length); + + var expected = new DenseVectorStorage(4, new[] { -1.0, -2.0, 0.0, -4.0 }); + + rdense.Clear(); + adense.MapTo(rdense, u => -u, Zeros.AllowSkip); + Assert.That(rdense.Equals(expected), "dense->dense"); + + rsparse.Clear(); + adense.MapTo(rsparse, u => -u, Zeros.AllowSkip); + Assert.That(rsparse.Equals(expected), "dense->sparse"); + + rdense.Clear(); + asparse.MapTo(rdense, u => -u, Zeros.AllowSkip); + Assert.That(rdense.Equals(expected), "sparse->dense"); + + rsparse.Clear(); + asparse.MapTo(rsparse, u => -u, Zeros.AllowSkip); + Assert.That(rsparse.Equals(expected), "sparse->sparse"); + } + + [Test] + public void MapToForceIncludeZeros() + { + double[] a = { 1.0, 2.0, 0.0, 4.0 }; + var adense = DenseVectorStorage.OfEnumerable(a); + var asparse = SparseVectorStorage.OfEnumerable(a); + + var rdense = new DenseVectorStorage(a.Length); + var rsparse = new SparseVectorStorage(a.Length); + + var expected = new DenseVectorStorage(4, new[] { 0.0, -1.0, 1.0, -3.0 }); + + rdense.Clear(); + adense.MapTo(rdense, u => -u + 1.0, Zeros.Include); + Assert.That(rdense.Equals(expected), "dense->dense"); + + rsparse.Clear(); + adense.MapTo(rsparse, u => -u + 1.0, Zeros.Include); + Assert.That(rsparse.Equals(expected), "dense->sparse"); + + rdense.Clear(); + asparse.MapTo(rdense, u => -u + 1.0, Zeros.Include); + Assert.That(rdense.Equals(expected), "sparse->dense"); + + rsparse.Clear(); + asparse.MapTo(rsparse, u => -u + 1.0, Zeros.Include); + Assert.That(rsparse.Equals(expected), "sparse->sparse"); + } + + [Test] + public void MapToAutoIncludeZeros() + { + double[] a = { 1.0, 2.0, 0.0, 4.0 }; + var adense = DenseVectorStorage.OfEnumerable(a); + var asparse = SparseVectorStorage.OfEnumerable(a); + + var rdense = new DenseVectorStorage(a.Length); + var rsparse = new SparseVectorStorage(a.Length); + + var expected = new DenseVectorStorage(4, new[] { 0.0, -1.0, 1.0, -3.0 }); + + rdense.Clear(); + adense.MapTo(rdense, u => -u + 1.0, Zeros.AllowSkip); + Assert.That(rdense.Equals(expected), "dense->dense"); + + rsparse.Clear(); + adense.MapTo(rsparse, u => -u + 1.0, Zeros.AllowSkip); + Assert.That(rsparse.Equals(expected), "dense->sparse"); + + rdense.Clear(); + asparse.MapTo(rdense, u => -u + 1.0, Zeros.AllowSkip); + Assert.That(rdense.Equals(expected), "sparse->dense"); + + rsparse.Clear(); + asparse.MapTo(rsparse, u => -u + 1.0, Zeros.AllowSkip); + Assert.That(rsparse.Equals(expected), "sparse->sparse"); + } + + [Test] + public void Map2ToSkipZeros() { double[] a = { 1.0, 2.0, 0.0, 4.0, 0.0, 6.0 }; double[] b = { 11.0, 12.0, 13.0, 0.0, 0.0, 16.0 }; @@ -53,40 +140,40 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests var expected = new DenseVectorStorage(6, new[] { 12.0, 14.0, 13.0, 4.0, 0.0, 22.0 }); rdense.Clear(); - adense.Map2To(rdense, bdense, (u, v) => u+v, Zeros.AllowSkip); + adense.Map2To(rdense, bdense, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "dense*dense->dense"); rsparse.Clear(); - adense.Map2To(rsparse, bdense, (u, v) => u+v, Zeros.AllowSkip); + adense.Map2To(rsparse, bdense, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "dense*dense->sparse"); rdense.Clear(); - adense.Map2To(rdense, bsparse, (u, v) => u+v, Zeros.AllowSkip); + adense.Map2To(rdense, bsparse, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "dense*sparse->dense"); rsparse.Clear(); - adense.Map2To(rsparse, bsparse, (u, v) => u+v, Zeros.AllowSkip); + adense.Map2To(rsparse, bsparse, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "dense*sparse->sparse"); rdense.Clear(); - asparse.Map2To(rdense, bdense, (u, v) => u+v, Zeros.AllowSkip); + asparse.Map2To(rdense, bdense, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "sparse*dense->dense"); rsparse.Clear(); - asparse.Map2To(rsparse, bdense, (u, v) => u+v, Zeros.AllowSkip); + asparse.Map2To(rsparse, bdense, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "sparse*dense->sparse"); rdense.Clear(); - asparse.Map2To(rdense, bsparse, (u, v) => u+v, Zeros.AllowSkip); + asparse.Map2To(rdense, bsparse, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "sparse*sparse->dense"); rsparse.Clear(); - asparse.Map2To(rsparse, bsparse, (u, v) => u+v, Zeros.AllowSkip); + asparse.Map2To(rsparse, bsparse, (u, v) => u + v, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "sparse*sparse->sparse"); } [Test] - public void Map2ForceIncludeZeros() + public void Map2ToForceIncludeZeros() { double[] a = { 1.0, 2.0, 0.0, 4.0, 0.0, 6.0 }; double[] b = { 11.0, 12.0, 13.0, 0.0, 0.0, 16.0 }; @@ -101,40 +188,40 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests var expected = new DenseVectorStorage(6, new[] { 13.0, 15.0, 14.0, 5.0, 1.0, 23.0 }); rdense.Clear(); - adense.Map2To(rdense, bdense, (u, v) => u+v+1.0, Zeros.Include); + adense.Map2To(rdense, bdense, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rdense.Equals(expected), "dense*dense->dense"); rsparse.Clear(); - adense.Map2To(rsparse, bdense, (u, v) => u+v+1.0, Zeros.Include); + adense.Map2To(rsparse, bdense, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rsparse.Equals(expected), "dense*dense->sparse"); rdense.Clear(); - adense.Map2To(rdense, bsparse, (u, v) => u+v+1.0, Zeros.Include); + adense.Map2To(rdense, bsparse, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rdense.Equals(expected), "dense*sparse->dense"); rsparse.Clear(); - adense.Map2To(rsparse, bsparse, (u, v) => u+v+1.0, Zeros.Include); + adense.Map2To(rsparse, bsparse, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rsparse.Equals(expected), "dense*sparse->sparse"); rdense.Clear(); - asparse.Map2To(rdense, bdense, (u, v) => u+v+1.0, Zeros.Include); + asparse.Map2To(rdense, bdense, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rdense.Equals(expected), "sparse*dense->dense"); rsparse.Clear(); - asparse.Map2To(rsparse, bdense, (u, v) => u+v+1.0, Zeros.Include); + asparse.Map2To(rsparse, bdense, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rsparse.Equals(expected), "sparse*dense->sparse"); rdense.Clear(); - asparse.Map2To(rdense, bsparse, (u, v) => u+v+1.0, Zeros.Include); + asparse.Map2To(rdense, bsparse, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rdense.Equals(expected), "sparse*sparse->dense"); rsparse.Clear(); - asparse.Map2To(rsparse, bsparse, (u, v) => u+v+1.0, Zeros.Include); + asparse.Map2To(rsparse, bsparse, (u, v) => u + v + 1.0, Zeros.Include); Assert.That(rsparse.Equals(expected), "sparse*sparse->sparse"); } [Test] - public void Map2AutoIncludeZeros() + public void Map2ToAutoIncludeZeros() { double[] a = { 1.0, 2.0, 0.0, 4.0, 0.0, 6.0 }; double[] b = { 11.0, 12.0, 13.0, 0.0, 0.0, 16.0 }; @@ -149,35 +236,35 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests var expected = new DenseVectorStorage(6, new[] { 13.0, 15.0, 14.0, 5.0, 1.0, 23.0 }); rdense.Clear(); - adense.Map2To(rdense, bdense, (u, v) => u+v+1.0, Zeros.AllowSkip); + adense.Map2To(rdense, bdense, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "dense*dense->dense"); rsparse.Clear(); - adense.Map2To(rsparse, bdense, (u, v) => u+v+1.0, Zeros.AllowSkip); + adense.Map2To(rsparse, bdense, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "dense*dense->sparse"); rdense.Clear(); - adense.Map2To(rdense, bsparse, (u, v) => u+v+1.0, Zeros.AllowSkip); + adense.Map2To(rdense, bsparse, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "dense*sparse->dense"); rsparse.Clear(); - adense.Map2To(rsparse, bsparse, (u, v) => u+v+1.0, Zeros.AllowSkip); + adense.Map2To(rsparse, bsparse, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "dense*sparse->sparse"); rdense.Clear(); - asparse.Map2To(rdense, bdense, (u, v) => u+v+1.0, Zeros.AllowSkip); + asparse.Map2To(rdense, bdense, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "sparse*dense->dense"); rsparse.Clear(); - asparse.Map2To(rsparse, bdense, (u, v) => u+v+1.0, Zeros.AllowSkip); + asparse.Map2To(rsparse, bdense, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "sparse*dense->sparse"); rdense.Clear(); - asparse.Map2To(rdense, bsparse, (u, v) => u+v+1.0, Zeros.AllowSkip); + asparse.Map2To(rdense, bsparse, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rdense.Equals(expected), "sparse*sparse->dense"); rsparse.Clear(); - asparse.Map2To(rsparse, bsparse, (u, v) => u+v+1.0, Zeros.AllowSkip); + asparse.Map2To(rsparse, bsparse, (u, v) => u + v + 1.0, Zeros.AllowSkip); Assert.That(rsparse.Equals(expected), "sparse*sparse->sparse"); } }