diff --git a/src/Numerics/Control.cs b/src/Numerics/Control.cs index e8538eb1..66db2b19 100644 --- a/src/Numerics/Control.cs +++ b/src/Numerics/Control.cs @@ -67,6 +67,8 @@ namespace MathNet.Numerics // Linear Algebra Provider LinearAlgebraProvider = new ManagedLinearAlgebraProvider(); + ExperimentalLinearAlgebraProvider = new Providers.ExperimentalLinearAlgebra.Managed.ManagedExperimentalLinearAlgebraProvider(); + #if !PORTABLE && NATIVEMKL try { @@ -77,6 +79,7 @@ namespace MathNet.Numerics #if NATIVEMKL case "MKL": LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(); + ExperimentalLinearAlgebraProvider = new Providers.ExperimentalLinearAlgebra.Mkl.MklExperimentalLinearAlgebraProvider(); break; #endif } @@ -85,11 +88,9 @@ namespace MathNet.Numerics { // We don't care about any failures here at all (because "auto") LinearAlgebraProvider = new ManagedLinearAlgebraProvider(); + ExperimentalLinearAlgebraProvider = new Providers.ExperimentalLinearAlgebra.Managed.ManagedExperimentalLinearAlgebraProvider(); } #endif - - // Experimental Linear Algebra Provider - ExperimentalLinearAlgebraProvider = new ReferenceExperimentalLinearAlgebraProvider(); } public static void UseSingleThread() @@ -111,12 +112,14 @@ namespace MathNet.Numerics public static void UseManaged() { LinearAlgebraProvider = new ManagedLinearAlgebraProvider(); + ExperimentalLinearAlgebraProvider = new Providers.ExperimentalLinearAlgebra.Managed.ManagedExperimentalLinearAlgebraProvider(); } #if NATIVEMKL public static void UseNativeMKL() { LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(); + ExperimentalLinearAlgebraProvider = new Providers.ExperimentalLinearAlgebra.Mkl.MklExperimentalLinearAlgebraProvider(); } [CLSCompliant(false)] @@ -126,6 +129,7 @@ namespace MathNet.Numerics Providers.LinearAlgebra.Mkl.MklAccuracy accuracy = Providers.LinearAlgebra.Mkl.MklAccuracy.High) { LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(consistency, precision, accuracy); + ExperimentalLinearAlgebraProvider = new Providers.ExperimentalLinearAlgebra.Mkl.MklExperimentalLinearAlgebraProvider(consistency, precision, accuracy); } #endif diff --git a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs index a2a6eb1a..4d2eb819 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs @@ -231,26 +231,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// The vector to add to this one. - /// The vector to store the result of the addition. - protected override void DoAdd(Vector other, Vector result) - { - var otherDense = other as DenseVector; - var resultDense = result as DenseVector; - - if (otherDense == null || resultDense == null) - { - base.DoAdd(other, result); - } - else - { - Control.LinearAlgebraProvider.AddArrays(_values, otherDense._values, resultDense._values); - } - } - /// /// Adds two Vectors together and returns the results. /// diff --git a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs index d81325c3..45626d3e 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs @@ -189,89 +189,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// - /// The vector to add to this one. - /// - /// - /// The vector to store the result of the addition. - /// - protected override void DoAdd(Vector other, Vector result) - { - var otherSparse = other as SparseVector; - if (otherSparse == null) - { - base.DoAdd(other, result); - return; - } - - var resultSparse = result as SparseVector; - if (resultSparse == null) - { - base.DoAdd(other, result); - return; - } - - // TODO (ruegg, 2011-10-11): Options to optimize? - - var otherStorage = otherSparse._storage; - if (ReferenceEquals(this, resultSparse)) - { - int i = 0, j = 0; - while (j < otherStorage.ValueCount) - { - if (i >= _storage.ValueCount || _storage.Indices[i] > otherStorage.Indices[j]) - { - var otherValue = otherStorage.Values[j]; - if (!Complex.Zero.Equals(otherValue)) - { - _storage.InsertAtIndexUnchecked(i++, otherStorage.Indices[j], otherValue); - } - j++; - } - else if (_storage.Indices[i] == otherStorage.Indices[j]) - { - // TODO: result can be zero, remove? - _storage.Values[i++] += otherStorage.Values[j++]; - } - else - { - i++; - } - } - } - else - { - result.Clear(); - int i = 0, j = 0, last = -1; - while (i < _storage.ValueCount || j < otherStorage.ValueCount) - { - if (j >= otherStorage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherStorage.Indices[j]) - { - var next = _storage.Indices[i]; - if (next != last) - { - last = next; - result.At(next, _storage.Values[i] + otherSparse.At(next)); - } - i++; - } - else - { - var next = otherStorage.Indices[j]; - if (next != last) - { - last = next; - result.At(next, At(next) + otherStorage.Values[j]); - } - j++; - } - } - } - } - /// /// Subtracts a scalar from each element of the vector and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Complex/Vector.cs b/src/Numerics/LinearAlgebra/Complex/Vector.cs index 6cda7da6..ca9fe7c7 100644 --- a/src/Numerics/LinearAlgebra/Complex/Vector.cs +++ b/src/Numerics/LinearAlgebra/Complex/Vector.cs @@ -89,12 +89,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// /// The vector to store the result of the addition. /// - protected override void DoAdd(Vector other, Vector result) + protected override sealed void DoAdd(Vector other, Vector result) { - for (var index = 0; index < Count; index++) - { - result.At(index, At(index) + other.At(index)); - } + Control.ExperimentalLinearAlgebraProvider.AddVectors(Storage, other.Storage, result.Storage); } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs index 5bba0a10..a1fa9c8c 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs @@ -226,26 +226,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// The vector to add to this one. - /// The vector to store the result of the addition. - protected override void DoAdd(Vector other, Vector result) - { - var otherDense = other as DenseVector; - var resultDense = result as DenseVector; - - if (otherDense == null || resultDense == null) - { - base.DoAdd(other, result); - } - else - { - Control.LinearAlgebraProvider.AddArrays(_values, otherDense._values, resultDense._values); - } - } - /// /// Adds two Vectors together and returns the results. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs index 48c2f13c..89ff871e 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs @@ -184,89 +184,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// - /// The vector to add to this one. - /// - /// - /// The vector to store the result of the addition. - /// - protected override void DoAdd(Vector other, Vector result) - { - var otherSparse = other as SparseVector; - if (otherSparse == null) - { - base.DoAdd(other, result); - return; - } - - var resultSparse = result as SparseVector; - if (resultSparse == null) - { - base.DoAdd(other, result); - return; - } - - // TODO (ruegg, 2011-10-11): Options to optimize? - - var otherStorage = otherSparse._storage; - if (ReferenceEquals(this, resultSparse)) - { - int i = 0, j = 0; - while (j < otherStorage.ValueCount) - { - if (i >= _storage.ValueCount || _storage.Indices[i] > otherStorage.Indices[j]) - { - var otherValue = otherStorage.Values[j]; - if (!Complex32.Zero.Equals(otherValue)) - { - _storage.InsertAtIndexUnchecked(i++, otherStorage.Indices[j], otherValue); - } - j++; - } - else if (_storage.Indices[i] == otherStorage.Indices[j]) - { - // TODO: result can be zero, remove? - _storage.Values[i++] += otherStorage.Values[j++]; - } - else - { - i++; - } - } - } - else - { - result.Clear(); - int i = 0, j = 0, last = -1; - while (i < _storage.ValueCount || j < otherStorage.ValueCount) - { - if (j >= otherStorage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherStorage.Indices[j]) - { - var next = _storage.Indices[i]; - if (next != last) - { - last = next; - result.At(next, _storage.Values[i] + otherSparse.At(next)); - } - i++; - } - else - { - var next = otherStorage.Indices[j]; - if (next != last) - { - last = next; - result.At(next, At(next) + otherStorage.Values[j]); - } - j++; - } - } - } - } - /// /// Subtracts a scalar from each element of the vector and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/Vector.cs b/src/Numerics/LinearAlgebra/Complex32/Vector.cs index 865296d5..d302151f 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Vector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Vector.cs @@ -84,12 +84,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// /// The vector to store the result of the addition. /// - protected override void DoAdd(Vector other, Vector result) + protected override sealed void DoAdd(Vector other, Vector result) { - for (var index = 0; index < Count; index++) - { - result.At(index, At(index) + other.At(index)); - } + Control.ExperimentalLinearAlgebraProvider.AddVectors(Storage, other.Storage, result.Storage); } /// diff --git a/src/Numerics/LinearAlgebra/Double/DenseVector.cs b/src/Numerics/LinearAlgebra/Double/DenseVector.cs index 12b96828..ed5125f1 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseVector.cs @@ -226,26 +226,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// The vector to add to this one. - /// The vector to store the result of the addition. - protected override void DoAdd(Vector other, Vector result) - { - var otherDense = other as DenseVector; - var resultDense = result as DenseVector; - - if (otherDense == null || resultDense == null) - { - base.DoAdd(other, result); - } - else - { - Control.LinearAlgebraProvider.AddArrays(_values, otherDense._values, resultDense._values); - } - } - /// /// Adds two Vectors together and returns the results. /// diff --git a/src/Numerics/LinearAlgebra/Double/SparseVector.cs b/src/Numerics/LinearAlgebra/Double/SparseVector.cs index 9ec18d65..5e4df7bd 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseVector.cs @@ -184,89 +184,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// - /// The vector to add to this one. - /// - /// - /// The vector to store the result of the addition. - /// - protected override void DoAdd(Vector other, Vector result) - { - var otherSparse = other as SparseVector; - if (otherSparse == null) - { - base.DoAdd(other, result); - return; - } - - var resultSparse = result as SparseVector; - if (resultSparse == null) - { - base.DoAdd(other, result); - return; - } - - // TODO (ruegg, 2011-10-11): Options to optimize? - - var otherStorage = otherSparse._storage; - if (ReferenceEquals(this, resultSparse)) - { - int i = 0, j = 0; - while (j < otherStorage.ValueCount) - { - if (i >= _storage.ValueCount || _storage.Indices[i] > otherStorage.Indices[j]) - { - var otherValue = otherStorage.Values[j]; - if (otherValue != 0.0) - { - _storage.InsertAtIndexUnchecked(i++, otherStorage.Indices[j], otherValue); - } - j++; - } - else if (_storage.Indices[i] == otherStorage.Indices[j]) - { - // TODO: result can be zero, remove? - _storage.Values[i++] += otherStorage.Values[j++]; - } - else - { - i++; - } - } - } - else - { - result.Clear(); - int i = 0, j = 0, last = -1; - while (i < _storage.ValueCount || j < otherStorage.ValueCount) - { - if (j >= otherStorage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherStorage.Indices[j]) - { - var next = _storage.Indices[i]; - if (next != last) - { - last = next; - result.At(next, _storage.Values[i] + otherSparse.At(next)); - } - i++; - } - else - { - var next = otherStorage.Indices[j]; - if (next != last) - { - last = next; - result.At(next, At(next) + otherStorage.Values[j]); - } - j++; - } - } - } - } - /// /// Subtracts a scalar from each element of the vector and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Double/Vector.cs b/src/Numerics/LinearAlgebra/Double/Vector.cs index 01e80270..ebfa29c9 100644 --- a/src/Numerics/LinearAlgebra/Double/Vector.cs +++ b/src/Numerics/LinearAlgebra/Double/Vector.cs @@ -82,12 +82,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// /// The vector to store the result of the addition. /// - protected override void DoAdd(Vector other, Vector result) + protected override sealed void DoAdd(Vector other, Vector result) { - for (var index = 0; index < Count; index++) - { - result.At(index, At(index) + other.At(index)); - } + Control.ExperimentalLinearAlgebraProvider.AddVectors(Storage, other.Storage, result.Storage); } /// diff --git a/src/Numerics/LinearAlgebra/Single/DenseVector.cs b/src/Numerics/LinearAlgebra/Single/DenseVector.cs index 4b69bd9f..d7ca99ec 100644 --- a/src/Numerics/LinearAlgebra/Single/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Single/DenseVector.cs @@ -225,26 +225,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// The vector to add to this one. - /// The vector to store the result of the addition. - protected override void DoAdd(Vector other, Vector result) - { - var otherDense = other as DenseVector; - var resultDense = result as DenseVector; - - if (otherDense == null || resultDense == null) - { - base.DoAdd(other, result); - } - else - { - Control.LinearAlgebraProvider.AddArrays(_values, otherDense._values, resultDense._values); - } - } - /// /// Adds two Vectors together and returns the results. /// diff --git a/src/Numerics/LinearAlgebra/Single/SparseVector.cs b/src/Numerics/LinearAlgebra/Single/SparseVector.cs index 2bc0fc85..841ca3e5 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseVector.cs @@ -185,89 +185,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single } } - /// - /// Adds another vector to this vector and stores the result into the result vector. - /// - /// - /// The vector to add to this one. - /// - /// - /// The vector to store the result of the addition. - /// - protected override void DoAdd(Vector other, Vector result) - { - var otherSparse = other as SparseVector; - if (otherSparse == null) - { - base.DoAdd(other, result); - return; - } - - var resultSparse = result as SparseVector; - if (resultSparse == null) - { - base.DoAdd(other, result); - return; - } - - // TODO (ruegg, 2011-10-11): Options to optimize? - - var otherStorage = otherSparse._storage; - if (ReferenceEquals(this, resultSparse)) - { - int i = 0, j = 0; - while (j < otherStorage.ValueCount) - { - if (i >= _storage.ValueCount || _storage.Indices[i] > otherStorage.Indices[j]) - { - var otherValue = otherStorage.Values[j]; - if (otherValue != 0.0f) - { - _storage.InsertAtIndexUnchecked(i++, otherStorage.Indices[j], otherValue); - } - j++; - } - else if (_storage.Indices[i] == otherStorage.Indices[j]) - { - // TODO: result can be zero, remove? - _storage.Values[i++] += otherStorage.Values[j++]; - } - else - { - i++; - } - } - } - else - { - result.Clear(); - int i = 0, j = 0, last = -1; - while (i < _storage.ValueCount || j < otherStorage.ValueCount) - { - if (j >= otherStorage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherStorage.Indices[j]) - { - var next = _storage.Indices[i]; - if (next != last) - { - last = next; - result.At(next, _storage.Values[i] + otherSparse.At(next)); - } - i++; - } - else - { - var next = otherStorage.Indices[j]; - if (next != last) - { - last = next; - result.At(next, At(next) + otherStorage.Values[j]); - } - j++; - } - } - } - } - /// /// Subtracts a scalar from each element of the vector and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Single/Vector.cs b/src/Numerics/LinearAlgebra/Single/Vector.cs index 0ff911fa..ec79e7c4 100644 --- a/src/Numerics/LinearAlgebra/Single/Vector.cs +++ b/src/Numerics/LinearAlgebra/Single/Vector.cs @@ -82,12 +82,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// /// The vector to store the result of the addition. /// - protected override void DoAdd(Vector other, Vector result) + protected override sealed void DoAdd(Vector other, Vector result) { - for (var index = 0; index < Count; index++) - { - result.At(index, At(index) + other.At(index)); - } + Control.ExperimentalLinearAlgebraProvider.AddVectors(Storage, other.Storage, result.Storage); } /// diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index b1417100..2cc47c17 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -149,6 +149,16 @@ + + + + + + + + + + diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Complex.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Complex.cs new file mode 100644 index 00000000..7251e60e --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Complex.cs @@ -0,0 +1,127 @@ +// +// 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-2014 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. +// + +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Threading; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Managed +{ + +#if !NOSYSNUMERICS + using Complex = System.Numerics.Complex; +#endif + + public partial class ManagedExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + CommonParallel.For(0, y.Length, 4096, (a, b) => + { + for (int i = a; i < b; i++) + { + result[i] = x[i] + y[i]; + } + }); + return; + } + + var xs = x as SparseVectorStorage; + var ys = y as SparseVectorStorage; + var rs = result as SparseVectorStorage; + if (xs != null && ys != null && rs != null) + { + + // NOTE: this algorithm could be improved, just here for demonstration with same behavior as before + + if (ReferenceEquals(xs, rs)) + { + int i = 0, j = 0; + while (j < ys.ValueCount) + { + if (i >= xs.ValueCount || xs.Indices[i] > ys.Indices[j]) + { + var yValues = ys.Values[j]; + if (!Complex.Zero.Equals(yValues)) + { + xs.InsertAtIndexUnchecked(i++, ys.Indices[j], yValues); + } + j++; + } + else if (xs.Indices[i] == ys.Indices[j]) + { + // TODO: result can be zero, remove? + xs.Values[i++] += ys.Values[j++]; + } + else + { + i++; + } + } + } + else + { + rs.Clear(); + int i = 0, j = 0, last = -1; + while (i < xs.ValueCount || j < ys.ValueCount) + { + if (j >= ys.ValueCount || i < xs.ValueCount && xs.Indices[i] <= ys.Indices[j]) + { + var next = xs.Indices[i]; + if (next != last) + { + last = next; + rs.At(next, xs.Values[i] + ys.At(next)); + } + i++; + } + else + { + var next = ys.Indices[j]; + if (next != last) + { + last = next; + rs.At(next, xs.At(next) + ys.Values[j]); + } + j++; + } + } + } + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Complex32.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Complex32.cs new file mode 100644 index 00000000..bdbf7734 --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Complex32.cs @@ -0,0 +1,122 @@ +// +// 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-2014 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. +// + +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Threading; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Managed +{ + public partial class ManagedExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + CommonParallel.For(0, y.Length, 4096, (a, b) => + { + for (int i = a; i < b; i++) + { + result[i] = x[i] + y[i]; + } + }); + return; + } + + var xs = x as SparseVectorStorage; + var ys = y as SparseVectorStorage; + var rs = result as SparseVectorStorage; + if (xs != null && ys != null && rs != null) + { + + // NOTE: this algorithm could be improved, just here for demonstration with same behavior as before + + if (ReferenceEquals(xs, rs)) + { + int i = 0, j = 0; + while (j < ys.ValueCount) + { + if (i >= xs.ValueCount || xs.Indices[i] > ys.Indices[j]) + { + var yValues = ys.Values[j]; + if (!Complex32.Zero.Equals(yValues)) + { + xs.InsertAtIndexUnchecked(i++, ys.Indices[j], yValues); + } + j++; + } + else if (xs.Indices[i] == ys.Indices[j]) + { + // TODO: result can be zero, remove? + xs.Values[i++] += ys.Values[j++]; + } + else + { + i++; + } + } + } + else + { + rs.Clear(); + int i = 0, j = 0, last = -1; + while (i < xs.ValueCount || j < ys.ValueCount) + { + if (j >= ys.ValueCount || i < xs.ValueCount && xs.Indices[i] <= ys.Indices[j]) + { + var next = xs.Indices[i]; + if (next != last) + { + last = next; + rs.At(next, xs.Values[i] + ys.At(next)); + } + i++; + } + else + { + var next = ys.Indices[j]; + if (next != last) + { + last = next; + rs.At(next, xs.At(next) + ys.Values[j]); + } + j++; + } + } + } + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Double.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Double.cs new file mode 100644 index 00000000..cf8edcbf --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Double.cs @@ -0,0 +1,122 @@ +// +// 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-2014 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. +// + +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Threading; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Managed +{ + public partial class ManagedExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + CommonParallel.For(0, y.Length, 4096, (a, b) => + { + for (int i = a; i < b; i++) + { + result[i] = x[i] + y[i]; + } + }); + return; + } + + var xs = x as SparseVectorStorage; + var ys = y as SparseVectorStorage; + var rs = result as SparseVectorStorage; + if (xs != null && ys != null && rs != null) + { + + // NOTE: this algorithm could be improved, just here for demonstration with same behavior as before + + if (ReferenceEquals(xs, rs)) + { + int i = 0, j = 0; + while (j < ys.ValueCount) + { + if (i >= xs.ValueCount || xs.Indices[i] > ys.Indices[j]) + { + var yValues = ys.Values[j]; + if (yValues != 0.0) + { + xs.InsertAtIndexUnchecked(i++, ys.Indices[j], yValues); + } + j++; + } + else if (xs.Indices[i] == ys.Indices[j]) + { + // TODO: result can be zero, remove? + xs.Values[i++] += ys.Values[j++]; + } + else + { + i++; + } + } + } + else + { + rs.Clear(); + int i = 0, j = 0, last = -1; + while (i < xs.ValueCount || j < ys.ValueCount) + { + if (j >= ys.ValueCount || i < xs.ValueCount && xs.Indices[i] <= ys.Indices[j]) + { + var next = xs.Indices[i]; + if (next != last) + { + last = next; + rs.At(next, xs.Values[i] + ys.At(next)); + } + i++; + } + else + { + var next = ys.Indices[j]; + if (next != last) + { + last = next; + rs.At(next, xs.At(next) + ys.Values[j]); + } + j++; + } + } + } + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Single.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Single.cs new file mode 100644 index 00000000..e36b266d --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.Single.cs @@ -0,0 +1,122 @@ +// +// 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-2014 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. +// + +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Threading; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Managed +{ + public partial class ManagedExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + CommonParallel.For(0, y.Length, 4096, (a, b) => + { + for (int i = a; i < b; i++) + { + result[i] = x[i] + y[i]; + } + }); + return; + } + + var xs = x as SparseVectorStorage; + var ys = y as SparseVectorStorage; + var rs = result as SparseVectorStorage; + if (xs != null && ys != null && rs != null) + { + + // NOTE: this algorithm could be improved, just here for demonstration with same behavior as before + + if (ReferenceEquals(xs, rs)) + { + int i = 0, j = 0; + while (j < ys.ValueCount) + { + if (i >= xs.ValueCount || xs.Indices[i] > ys.Indices[j]) + { + var yValues = ys.Values[j]; + if (yValues != 0.0f) + { + xs.InsertAtIndexUnchecked(i++, ys.Indices[j], yValues); + } + j++; + } + else if (xs.Indices[i] == ys.Indices[j]) + { + // TODO: result can be zero, remove? + xs.Values[i++] += ys.Values[j++]; + } + else + { + i++; + } + } + } + else + { + rs.Clear(); + int i = 0, j = 0, last = -1; + while (i < xs.ValueCount || j < ys.ValueCount) + { + if (j >= ys.ValueCount || i < xs.ValueCount && xs.Indices[i] <= ys.Indices[j]) + { + var next = xs.Indices[i]; + if (next != last) + { + last = next; + rs.At(next, xs.Values[i] + ys.At(next)); + } + i++; + } + else + { + var next = ys.Indices[j]; + if (next != last) + { + last = next; + rs.At(next, xs.At(next) + ys.Values[j]); + } + j++; + } + } + } + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.cs new file mode 100644 index 00000000..ab7ee2fd --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Managed/ManagedExperimentalLinearAlgebraProvider.cs @@ -0,0 +1,51 @@ +// +// 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-2014 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. +// + +using System; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Managed +{ + [Obsolete("Experimental with breaking changes expected between minor version. Do not use until properly released.")] + public partial class ManagedExperimentalLinearAlgebraProvider : ReferenceExperimentalLinearAlgebraProvider + { + /// + /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider + /// + public override void InitializeVerify() + { + base.InitializeVerify(); + } + + public override string ToString() + { + return "Managed"; + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Complex.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Complex.cs new file mode 100644 index 00000000..1c14c2cc --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Complex.cs @@ -0,0 +1,69 @@ +// +// 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-2014 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. +// + +using System; +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.LinearAlgebra.Mkl; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Mkl +{ + +#if !NOSYSNUMERICS + using Complex = System.Numerics.Complex; +#endif + + public partial class MklExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + if (xd.Length != yd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (xd.Length != rd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.z_vector_add(xd.Length, xd.Data, yd.Data, rd.Data); + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Complex32.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Complex32.cs new file mode 100644 index 00000000..57c58533 --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Complex32.cs @@ -0,0 +1,64 @@ +// +// 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-2014 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. +// + +using System; +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.LinearAlgebra.Mkl; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Mkl +{ + public partial class MklExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + if (xd.Length != yd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (xd.Length != rd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.c_vector_add(xd.Length, xd.Data, yd.Data, rd.Data); + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Double.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Double.cs new file mode 100644 index 00000000..e758c455 --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Double.cs @@ -0,0 +1,64 @@ +// +// 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-2014 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. +// + +using System; +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.LinearAlgebra.Mkl; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Mkl +{ + public partial class MklExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + if (xd.Length != yd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (xd.Length != rd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.d_vector_add(xd.Length, xd.Data, yd.Data, rd.Data); + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Single.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Single.cs new file mode 100644 index 00000000..928dc891 --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.Single.cs @@ -0,0 +1,64 @@ +// +// 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-2014 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. +// + +using System; +using MathNet.Numerics.LinearAlgebra.Storage; +using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.LinearAlgebra.Mkl; + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Mkl +{ + public partial class MklExperimentalLinearAlgebraProvider + { + public override void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + { + var xd = x as DenseVectorStorage; + var yd = y as DenseVectorStorage; + var rd = result as DenseVectorStorage; + if (xd != null && yd != null && rd != null) + { + if (xd.Length != yd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (xd.Length != rd.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.s_vector_add(xd.Length, xd.Data, yd.Data, rd.Data); + return; + } + + base.AddVectors(x, y, result); + } + } +} diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.cs new file mode 100644 index 00000000..269b8e52 --- /dev/null +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/Mkl/MklExperimentalLinearAlgebraProvider.cs @@ -0,0 +1,144 @@ +// +// 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-2014 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. +// + +using System; +using MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Managed; +using MathNet.Numerics.Providers.LinearAlgebra.Mkl; + +#if NATIVEMKL + +namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra.Mkl +{ + // TODO: Consider composition instead of inheritance + + /// + /// Intel's Math Kernel Library (MKL) linear algebra provider. + /// + public partial class MklExperimentalLinearAlgebraProvider : ManagedExperimentalLinearAlgebraProvider + { + int _nativeRevision; + bool _nativeIX86; + bool _nativeX64; + bool _nativeIA64; + + readonly MklConsistency _consistency; + readonly MklPrecision _precision; + readonly MklAccuracy _accuracy; + + /// + /// Sets the desired bit consistency on repeated identical computations on varying CPU architectures, + /// as a trade-off with performance. + /// + /// VML optimal precision and rounding. + /// VML accuracy mode. + [CLSCompliant(false)] + public MklExperimentalLinearAlgebraProvider( + MklConsistency consistency = MklConsistency.Auto, + MklPrecision precision = MklPrecision.Double, + MklAccuracy accuracy = MklAccuracy.High) + { + _consistency = consistency; + _precision = precision; + _accuracy = accuracy; + } + + public MklExperimentalLinearAlgebraProvider() + { + _consistency = MklConsistency.Auto; + _precision = MklPrecision.Double; + _accuracy = MklAccuracy.High; + } + + /// + /// Initialize and verify that the provided is indeed available. + /// If calling this method fails, consider to fall back to alternatives like the managed provider. + /// + public override void InitializeVerify() + { + // TODO: Choose x86 or x64 based on Environment.Is64BitProcess + + int a, b, linearAlgebra; + try + { + a = SafeNativeMethods.query_capability(0); + b = SafeNativeMethods.query_capability(1); + + _nativeIX86 = SafeNativeMethods.query_capability(8) > 0; + _nativeX64 = SafeNativeMethods.query_capability(9) > 0; + _nativeIA64 = SafeNativeMethods.query_capability(10) > 0; + + _nativeRevision = SafeNativeMethods.query_capability(64); + linearAlgebra = SafeNativeMethods.query_capability(128); + } + catch (DllNotFoundException e) + { + throw new NotSupportedException("MKL Native Provider not found.", e); + } + catch (BadImageFormatException e) + { + throw new NotSupportedException("MKL Native Provider found but failed to load. Please verify that the platform matches (x64 vs x32, Windows vs Linux).", e); + } + catch (EntryPointNotFoundException e) + { + // we currently accept this to continue to support the old version for a while. + // however, this is planned to be dropped for the final v3 release at latest. + // TODO: drop return statement and instead fail with the exception below + return; + + throw new NotSupportedException("MKL Native Provider found but does not support capability querying and is therefore not compatible. Try to upgrade to a newer version.", e); + } + + if (a != 0 || b != -1 || linearAlgebra <=0 || _nativeRevision < 4) + { + throw new NotSupportedException("MKL Native Provider found but too old or not compatible."); + } + + // set numerical consistency, precision and accuracy modes, if supported + if (SafeNativeMethods.query_capability(65) > 0) + { + SafeNativeMethods.set_consistency_mode((int)_consistency); + SafeNativeMethods.set_vml_mode((uint)_precision | (uint)_accuracy); + } + + // set threading settings, if supported + if (SafeNativeMethods.query_capability(66) > 0) + { + SafeNativeMethods.set_max_threads(Control.MaxDegreeOfParallelism); + } + } + + public override string ToString() + { + return string.Format("Intel MKL ({1}; revision {0})", _nativeRevision, _nativeIX86 ? "x86" : _nativeX64 ? "x64" : _nativeIA64 ? "IA64" : "unknown"); + } + } +} + +#endif diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex.cs index 344798a5..099d127d 100644 --- a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex.cs +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex.cs @@ -40,7 +40,7 @@ namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra public partial class ReferenceExperimentalLinearAlgebraProvider { - public void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + public virtual void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) { x.Map2To(result, y, (u, v) => u+v, Zeros.AllowSkip, ExistingData.Clear); } diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex32.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex32.cs index 109b16db..a8f758b6 100644 --- a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex32.cs +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Complex32.cs @@ -35,7 +35,7 @@ namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra { public partial class ReferenceExperimentalLinearAlgebraProvider { - public void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + public virtual void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) { x.Map2To(result, y, (u, v) => u+v, Zeros.AllowSkip, ExistingData.Clear); } diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Double.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Double.cs index ab8ab1b2..546368db 100644 --- a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Double.cs +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Double.cs @@ -35,7 +35,7 @@ namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra { public partial class ReferenceExperimentalLinearAlgebraProvider { - public void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + public virtual void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) { x.Map2To(result, y, (u,v) => u+v, Zeros.AllowSkip, ExistingData.Clear); } diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Single.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Single.cs index 2ddbf2b5..dcecb4f0 100644 --- a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Single.cs +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.Single.cs @@ -35,7 +35,7 @@ namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra { public partial class ReferenceExperimentalLinearAlgebraProvider { - public void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) + public virtual void AddVectors(VectorStorage x, VectorStorage y, VectorStorage result) { x.Map2To(result, y, (u, v) => u+v, Zeros.AllowSkip, ExistingData.Clear); } diff --git a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.cs b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.cs index 3a0f6f67..8db9fdb9 100644 --- a/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/ExperimentalLinearAlgebra/ReferenceExperimentalLinearAlgebraProvider.cs @@ -1,4 +1,35 @@ -using System; +// +// 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-2014 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. +// + + +using System; namespace MathNet.Numerics.Providers.ExperimentalLinearAlgebra {