diff --git a/src/Numerics/LinearAlgebra/Double/DenseVector.cs b/src/Numerics/LinearAlgebra/Double/DenseVector.cs index b0dbd63e..1936c557 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseVector.cs @@ -31,12 +31,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double { using System; - using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; - using System.Threading.Tasks; using NumberTheory; using Properties; + using Threading; /// /// A vector using dense storage. @@ -93,15 +92,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double var vector = other as DenseVector; if (vector == null) { - Parallel.ForEach( - Partitioner.Create(0, this.Data.Length), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - this[index] = other[index]; - } - }); + CommonParallel.For( + 0, + this.Data.Length, + index => this[index] = other[index]); } else { @@ -292,15 +286,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double var otherVector = target as DenseVector; if (otherVector == null) { - Parallel.ForEach( - Partitioner.Create(0, this.Data.Length), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - target[index] = this.Data[index]; - } - }); + CommonParallel.For( + 0, + this.Data.Length, + index => this[index] = this.Data[index]); } else { @@ -319,15 +308,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.Data.Length), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - this.Data[index] += scalar; - } - }); + CommonParallel.For( + 0, + this.Data.Length, + index => this.Data[index] += scalar); } /// @@ -480,15 +464,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.Data.Length), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - this.Data[index] -= scalar; - } - }); + CommonParallel.For( + 0, + this.Data.Length, + index => this.Data[index] -= scalar); } /// @@ -637,15 +616,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double public override Vector Negate() { var result = new DenseVector(this.Count); - Parallel.ForEach( - Partitioner.Create(0, this.Data.Length), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - result[index] = -this.Data[index]; - } - }); + CommonParallel.For( + 0, + this.Data.Length, + index => result[index] = -this.Data[index]); return result; } @@ -787,6 +761,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double public override double Norm() { var sum = 0.0; + for (var i = 0; i < this.Data.Length; i++) { sum = SpecialFunctions.Hypotenuse(sum, this.Data[i]); @@ -801,30 +776,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// Scalar ret = sum(abs(this[i])) public override double Norm1() { - var sum = 0.0; - var syncLock = new object(); - - Parallel.ForEach( - Partitioner.Create(0, this.Count), - () => 0.0, - (range, loop, localData) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - localData += Math.Abs(this.Data[i]); - } - - return localData; - }, - localResult => - { - lock (syncLock) - { - sum += localResult; - } - }); - - return sum; + return CommonParallel.Aggregate( + 0, + this.Count, + index => Math.Abs(this.Data[index])); } /// @@ -849,28 +804,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return this.Norm(); } - var sum = 0.0; - var syncLock = new object(); - - Parallel.ForEach( - Partitioner.Create(0, this.Count), - () => 0.0, - (range, loop, localData) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - localData += Math.Pow(Math.Abs(this.Data[i]), p); - } - - return localData; - }, - localResult => - { - lock (syncLock) - { - sum += localResult; - } - }); + var sum = CommonParallel.Aggregate( + 0, + this.Count, + index => Math.Pow(Math.Abs(this.Data[index]), p)); return Math.Pow(sum, 1.0 / p); } @@ -881,7 +818,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// Scalar ret = max(abs(this[i])) public override double NormInfinity() { - double max = 0; + return CommonParallel.Select( + 0, + this.Count, + (index, localData) => localData = Math.Max(localData, Math.Abs(this.Data[index])), + Math.Max); + /*double max = 0; var syncLock = new object(); @@ -905,7 +847,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double } }); - return max; + return max;*/ } #endregion diff --git a/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs b/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs index 8d1eaef1..745894f5 100644 --- a/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs +++ b/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs @@ -31,9 +31,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double { using System; - using System.Collections.Concurrent; - using System.Threading.Tasks; using Properties; + using Threading; /// /// Defines the base class for Matrix classes. @@ -58,16 +57,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions); } - Parallel.ForEach( - Partitioner.Create(0, this.RowCount), - (range, loopState) => + CommonParallel.For( + 0, + this.RowCount, + i => { - for (var i = range.Item1; i < range.Item2; i++) + for (var j = 0; j < this.ColumnCount; j++) { - for (var j = 0; j < this.ColumnCount; j++) - { - this.At(i, j, this.At(i, j) + other.At(i, j)); - } + this.At(i, j, this.At(i, j) + other.At(i, j)); } }); } @@ -90,16 +87,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions); } - Parallel.ForEach( - Partitioner.Create(0, this.RowCount), - (range, loopState) => + CommonParallel.For( + 0, + this.RowCount, + i => { - for (var i = range.Item1; i < range.Item2; i++) + for (var j = 0; j < this.ColumnCount; j++) { - for (var j = 0; j < this.ColumnCount; j++) - { - this.At(i, j, this.At(i, j) - other.At(i, j)); - } + this.At(i, j, this.At(i, j) - other.At(i, j)); } }); } @@ -115,16 +110,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.RowCount), - (range, loopState) => + CommonParallel.For( + 0, + this.RowCount, + i => { - for (var i = range.Item1; i < range.Item2; i++) + for (var j = 0; j < this.ColumnCount; j++) { - for (var j = 0; j < this.ColumnCount; j++) - { - this.At(i, j, this.At(i, j) * scalar); - } + this.At(i, j, this.At(i, j) * scalar); } }); } @@ -210,21 +203,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double } else { - Parallel.ForEach( - Partitioner.Create(0, this.RowCount), - (range, loopState) => + CommonParallel.For( + 0, + this.RowCount, + i => { - for (var i = range.Item1; i < range.Item2; i++) + double s = 0; + for (var j = 0; j != this.ColumnCount; j++) { - double s = 0; - for (var j = 0; j != this.ColumnCount; j++) - { - s += this.At(i, j) * rightSide[j]; - } - - result[i] = s; + s += this.At(i, j) * rightSide[j]; } - }); + + result[i] = s; + }); } } @@ -281,21 +272,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double } else { - Parallel.ForEach( - Partitioner.Create(0, this.ColumnCount), - (range, loopState) => + CommonParallel.For( + 0, + this.RowCount, + j => { - for (var j = range.Item1; j < range.Item2; j++) + double s = 0; + for (var i = 0; i != leftSide.Count; i++) { - double s = 0; - for (var i = 0; i != leftSide.Count; i++) - { - s += leftSide[i] * this.At(i, j); - } - - result[j] = s; + s += leftSide[i] * this.At(i, j); } - }); + + result[j] = s; + }); } } @@ -338,24 +327,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double } else { - Parallel.ForEach( - Partitioner.Create(0, this.RowCount), - (range, loopState) => + CommonParallel.For( + 0, + this.RowCount, + j => { - for (var j = range.Item1; j < range.Item2; j++) + for (var i = 0; i != other.ColumnCount; i++) { - for (var i = 0; i != other.ColumnCount; i++) + double s = 0; + for (var l = 0; l < this.ColumnCount; l++) { - double s = 0; - for (var l = 0; l < this.ColumnCount; l++) - { - s += this.At(j, l) * other.At(l, i); - } - - result.At(j, i, s); + s += this.At(j, l) * other.At(l, i); } + + result.At(j, i, s); } - }); + }); } } diff --git a/src/Numerics/LinearAlgebra/Double/Vector.cs b/src/Numerics/LinearAlgebra/Double/Vector.cs index e92fa825..774358ce 100644 --- a/src/Numerics/LinearAlgebra/Double/Vector.cs +++ b/src/Numerics/LinearAlgebra/Double/Vector.cs @@ -32,11 +32,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double { using System; using System.Collections; - using System.Collections.Concurrent; using System.Collections.Generic; using System.Text; - using System.Threading.Tasks; using Properties; + using Threading; /// /// Defines the base class for Vector classes. @@ -133,15 +132,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.Count), - (range, loopState) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - this[i] += scalar; - } - }); + CommonParallel.For( + 0, + this.Count, + index => this[index] += scalar); } /// @@ -217,15 +211,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other"); } - Parallel.ForEach( - Partitioner.Create(0, this.Count), - (range, loopState) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - this[i] += other[i]; - } - }); + CommonParallel.For( + 0, + this.Count, + index => this[index] += other[index]); } /// @@ -287,15 +276,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.Count), - (range, loopState) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - this[i] -= scalar; - } - }); + CommonParallel.For( + 0, + this.Count, + index => this[index] -= scalar); } /// @@ -371,15 +355,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other"); } - Parallel.ForEach( - Partitioner.Create(0, this.Count), - (range, loopState) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - this[i] -= other[i]; - } - }); + CommonParallel.For( + 0, + this.Count, + index => this[index] -= other[index]); } /// @@ -441,15 +420,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.Count), - (range, loopState) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - this[i] *= scalar; - } - }); + CommonParallel.For( + 0, + this.Count, + index => this[index] *= scalar); } /// @@ -810,29 +784,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double throw new ArgumentOutOfRangeException("p"); } - var sum = 0.0; - var syncLock = new object(); - - Parallel.ForEach( - Partitioner.Create(0, this.Count), - () => 0.0, - (range, loop, localData) => - { - for (var i = range.Item1; i < range.Item2; i++) - { - localData += Math.Pow(Math.Abs(this[i]), p); - } - - return localData; - }, - localResult => - { - lock (syncLock) - { - sum += localResult; - } - }); - + var sum = CommonParallel.Aggregate( + 0, + this.Count, + index => Math.Pow(Math.Abs(this[index]), p)); + return Math.Pow(sum, 1.0 / p); } @@ -844,6 +800,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// public virtual double NormInfinity() { + return CommonParallel.Select( + 0, + this.Count, + (index, localData) => localData = Math.Max(localData, Math.Abs(this[index])), + Math.Max); + + /* var max = 0.0; var syncLock = new object(); @@ -867,7 +830,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double } }); - return max; + return max;*/ } /// @@ -935,15 +898,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double return; } - Parallel.ForEach( - Partitioner.Create(0, this.Count), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - target[index] = this[index]; - } - }); + CommonParallel.For( + 0, + this.Count, + index => target[index] = this[index]); } /// @@ -993,27 +951,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double var tmpVector = destination.CreateVector(destination.Count); this.CopyTo(tmpVector); - Parallel.ForEach( - Partitioner.Create(0, count), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - destination[destinationOffset + index] = tmpVector[offset + index]; - } - }); + CommonParallel.For( + 0, + count, + index => destination[destinationOffset + index] = tmpVector[offset + index]); } else { - Parallel.ForEach( - Partitioner.Create(0, count), - (range, loopState) => - { - for (var index = range.Item1; index < range.Item2; index++) - { - destination[destinationOffset + index] = this[offset + index]; - } - }); + CommonParallel.For( + 0, + count, + index => destination[destinationOffset + index] = this[offset + index]); } } diff --git a/src/Numerics/Threading/CommonParallel.cs b/src/Numerics/Threading/CommonParallel.cs index 8a9c5e8c..0984ebb3 100644 --- a/src/Numerics/Threading/CommonParallel.cs +++ b/src/Numerics/Threading/CommonParallel.cs @@ -149,5 +149,57 @@ namespace MathNet.Numerics.Threading { Parallel.Invoke(actions); } + + /// + /// Selects an item (such as Max or Min). + /// + /// Starting index of the loop. + /// Ending index of the loop + /// The function to select items over a subset. + /// The function to select the item of selection from the subsets. + /// The selected value. + public static double Select(int fromInclusive, int toExclusive, Func body, Func localFinally) + { + double ret = 0; + var syncLock = new object(); + +#if SILVERLIGHT + Parallel.For( + fromInclusive, + toExclusive, + () => 0.0, + (i, localData) => localData += body(i, localData), + localResult => + { + lock (syncLock) + { + ret = localFinally(ret, localResult); + } + }); +#else + Parallel.ForEach( + Partitioner.Create(fromInclusive, toExclusive), + new ParallelOptions { MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads }, + () => 0.0, + (range, loop, localData) => + { + for (var i = range.Item1; i < range.Item2; i++) + { + localData = body(i, localData); + } + + return localData; + }, + localResult => + { + lock (syncLock) + { + ret = localFinally(ret, localResult); + } + }); +#endif + + return ret; + } } } \ No newline at end of file diff --git a/src/Silverlight/Silverlight.csproj b/src/Silverlight/Silverlight.csproj index 2aa1d3cf..ab10abe5 100644 --- a/src/Silverlight/Silverlight.csproj +++ b/src/Silverlight/Silverlight.csproj @@ -215,6 +215,30 @@ IPrecisionSupport.cs + + LinearAlgebra\Double\DenseMatrix.cs + + + LinearAlgebra\Double\DenseVector.cs + + + LinearAlgebra\Double\Factorization\Cholesky.cs + + + LinearAlgebra\Double\Factorization\DenseCholesky.cs + + + LinearAlgebra\Double\Factorization\ExtensionMethods.cs + + + LinearAlgebra\Double\Matrix.Arithmetic.cs + + + LinearAlgebra\Double\Matrix.cs + + + LinearAlgebra\Double\Vector.cs + NumberTheory\IntegerTheory.cs