Browse Source

Reworking common parallelization routines #92

v2
Christoph Ruegg 14 years ago
parent
commit
d3dc54b4c1
  1. 182
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs
  2. 178
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs
  3. 180
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs
  4. 178
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs
  5. 34
      src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs
  6. 26
      src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs
  7. 28
      src/Numerics/IntegralTransforms/Algorithms/DiscreteHartleyTransform.Naive.cs
  8. 45
      src/Numerics/LinearAlgebra/Complex/DenseVector.cs
  9. 4
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs
  10. 4
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs
  11. 2
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  12. 10
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  13. 45
      src/Numerics/LinearAlgebra/Complex32/DenseVector.cs
  14. 4
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.cs
  15. 4
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseLU.cs
  16. 2
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  17. 10
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  18. 26
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  19. 34
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  20. 2
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  21. 24
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  22. 34
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  23. 2
      src/Numerics/LinearAlgebra/Single/SparseMatrix.cs
  24. 78
      src/Numerics/Random/Palf.cs
  25. 236
      src/Numerics/Threading/CommonParallel.cs

182
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs

@ -76,7 +76,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
} }
else else
{ {
@ -90,7 +96,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index])); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
} }
else else
{ {
@ -128,7 +140,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; }); CommonParallel.For(0, x.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
} }
else else
{ {
@ -207,7 +225,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
} }
else else
{ {
@ -252,7 +276,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
} }
else else
{ {
@ -297,7 +327,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
} }
else else
{ {
@ -342,7 +378,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
} }
else else
{ {
@ -1395,17 +1437,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
if (Control.ParallelizeOperation(columnsB * 10)) CommonParallel.For(0, columnsB, (u, v) =>
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{ {
DoCholeskySolve(a, orderA, b, index); for (int i = u; i < v; i++)
} {
} DoCholeskySolve(a, orderA, b, i);
}
});
} }
/// <summary> /// <summary>
@ -1553,7 +1591,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
} }
CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = Complex.One); CommonParallel.For(0, rowsR, (a, b) =>
{
for (int i = a; i < b; i++)
{
q[(i*rowsR) + i] = Complex.One;
}
});
var minmn = Math.Min(rowsR, columnsR); var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++) for (var i = 0; i < minmn; i++)
@ -1762,14 +1806,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var tmp = column * rowCount; var tmp = column * rowCount;
var index = tmp + row; var index = tmp + row;
CommonParallel.For( CommonParallel.For(row, rowCount, (u, v) =>
row,
rowCount,
i =>
{ {
var iIndex = tmp + i; for (int i = u; i < v; i++)
work[iIndex - row] = a[iIndex]; {
a[iIndex] = Complex.Zero; var iIndex = tmp + i;
work[iIndex - row] = a[iIndex];
a[iIndex] = Complex.Zero;
}
}); });
var norm = Complex.Zero; var norm = Complex.Zero;
@ -1793,11 +1837,23 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
a[index] = -norm; a[index] = -norm;
CommonParallel.For(0, rowCount - row, i => work[tmp + i] /= norm); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] /= norm;
}
});
work[tmp] += 1.0; work[tmp] += 1.0;
var s = (1.0 / work[tmp]).SquareRoot(); var s = (1.0 / work[tmp]).SquareRoot();
CommonParallel.For(0, rowCount - row, i => work[tmp + i] = work[tmp + i].Conjugate() * s); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] = work[tmp + i].Conjugate()*s;
}
});
} }
#endregion #endregion
@ -1965,7 +2021,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
int rowsQ, columnsQ, rowsR, columnsR; int rowsQ, columnsQ, rowsR, columnsR;
if( method == QRMethod.Full) if (method == QRMethod.Full)
{ {
rowsQ = columnsQ = rowsR = rowsA; rowsQ = columnsQ = rowsR = rowsA;
columnsR = columnsA; columnsR = columnsA;
@ -1976,24 +2032,24 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
columnsQ = rowsR = columnsR = columnsA; columnsQ = rowsR = columnsR = columnsA;
} }
if (r.Length != rowsR * columnsR) if (r.Length != rowsR*columnsR)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
} }
if (q.Length != rowsQ * columnsQ) if (q.Length != rowsQ*columnsQ)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
} }
var sol = new Complex[b.Length]; var sol = new Complex[b.Length];
@ -2005,56 +2061,62 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var column = new Complex[rowsA]; var column = new Complex[rowsA];
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
CommonParallel.For(0, rowsA, k => column[k] = sol[jm + k]); CommonParallel.For(0, rowsA, (u, v) =>
CommonParallel.For(
0,
columnsA,
i =>
{ {
var im = i * rowsA; for (int k = u; k < v; k++)
var sum = Complex.Zero;
for (var k = 0; k < rowsA; k++)
{ {
sum += q[im + k].Conjugate() * column[k]; column[k] = sol[jm + k];
} }
});
CommonParallel.For(0, columnsA, (u, v) =>
{
for (int i = u; i < v; i++)
{
var im = i*rowsA;
sol[jm + i] = sum; var sum = Complex.Zero;
for (var k = 0; k < rowsA; k++)
{
sum += q[im + k].Conjugate()*column[k];
}
sol[jm + i] = sum;
}
}); });
} }
// Solve R*X = Y; // Solve R*X = Y;
for (var k = columnsA - 1; k >= 0; k--) for (var k = columnsA - 1; k >= 0; k--)
{ {
var km = k * rowsR; var km = k*rowsR;
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
sol[(j * rowsA) + k] /= r[km + k]; sol[(j*rowsA) + k] /= r[km + k];
} }
for (var i = 0; i < k; i++) for (var i = 0; i < k; i++)
{ {
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
sol[jm + i] -= sol[jm + k] * r[km + i]; sol[jm + i] -= sol[jm + k]*r[km + i];
} }
} }
} }
// Fill result matrix // Fill result matrix
CommonParallel.For( CommonParallel.For(0, columnsR, (u, v) =>
0,
columnsR,
row =>
{ {
for (var col = 0; col < columnsB; col++) for (int row = u; row < v; row++)
{ {
x[(col * columnsA) + row] = sol[row + (col * rowsA)]; for (var col = 0; col < columnsB; col++)
{
x[(col*columnsA) + row] = sol[row + (col*rowsA)];
}
} }
}); });
} }
/// <summary> /// <summary>
/// Computes the singular value decomposition of A. /// Computes the singular value decomposition of A.
@ -2787,7 +2849,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Copy stemp to s with size adjustment. We are using ported copy of linpack's svd code and it uses // Copy stemp to s with size adjustment. We are using ported copy of linpack's svd code and it uses
// a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed. // a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed.
// We should port lapack's svd routine to remove this problem. // We should port lapack's svd routine to remove this problem.
CommonParallel.For(0, Math.Min(rowsA, columnsA), index => s[index] = stemp[index]); Array.Copy(stemp, s, Math.Min(rowsA, columnsA));
// On return the first element of the work array stores the min size of the work array could have been // On return the first element of the work array stores the min size of the work array could have been
// work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns)); // work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns));

178
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs

@ -71,7 +71,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
} }
else else
{ {
@ -85,7 +91,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index])); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
} }
else else
{ {
@ -124,7 +136,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; }); CommonParallel.For(0, x.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
} }
else else
{ {
@ -204,7 +222,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
} }
else else
{ {
@ -249,7 +273,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
} }
else else
{ {
@ -294,7 +324,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
} }
else else
{ {
@ -339,7 +375,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
} }
else else
{ {
@ -1392,17 +1434,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
if (Control.ParallelizeOperation(columnsB * 10)) CommonParallel.For(0, columnsB, (u, v) =>
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{ {
DoCholeskySolve(a, orderA, b, index); for (int i = u; i < v; i++)
} {
} DoCholeskySolve(a, orderA, b, i);
}
});
} }
/// <summary> /// <summary>
@ -1550,7 +1588,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
} }
CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = Complex32.One); CommonParallel.For(0, rowsR, (a, b) =>
{
for (int i = a; i < b; i++)
{
q[(i*rowsR) + i] = Complex32.One;
}
});
var minmn = Math.Min(rowsR, columnsR); var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++) for (var i = 0; i < minmn; i++)
@ -1759,14 +1803,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var tmp = column * rowCount; var tmp = column * rowCount;
var index = tmp + row; var index = tmp + row;
CommonParallel.For( CommonParallel.For(row, rowCount, (u, v) =>
row,
rowCount,
i =>
{ {
var iIndex = tmp + i; for (int i = u; i < v; i++)
work[iIndex - row] = a[iIndex]; {
a[iIndex] = Complex32.Zero; var iIndex = tmp + i;
work[iIndex - row] = a[iIndex];
a[iIndex] = Complex32.Zero;
}
}); });
var norm = Complex32.Zero; var norm = Complex32.Zero;
@ -1790,11 +1834,23 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
a[index] = -norm; a[index] = -norm;
CommonParallel.For(0, rowCount - row, i => work[tmp + i] /= norm); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] /= norm;
}
});
work[tmp] += 1.0f; work[tmp] += 1.0f;
var s = (1.0f / work[tmp]).SquareRoot(); var s = (1.0f / work[tmp]).SquareRoot();
CommonParallel.For(0, rowCount - row, i => work[tmp + i] = work[tmp + i].Conjugate() * s); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] = work[tmp + i].Conjugate()*s;
}
});
} }
#endregion #endregion
@ -1973,24 +2029,24 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
columnsQ = rowsR = columnsR = columnsA; columnsQ = rowsR = columnsR = columnsA;
} }
if (r.Length != rowsR * columnsR) if (r.Length != rowsR*columnsR)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
} }
if (q.Length != rowsQ * columnsQ) if (q.Length != rowsQ*columnsQ)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
} }
var sol = new Complex32[b.Length]; var sol = new Complex32[b.Length];
@ -2002,53 +2058,59 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var column = new Complex32[rowsA]; var column = new Complex32[rowsA];
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
CommonParallel.For(0, rowsA, k => column[k] = sol[jm + k]); CommonParallel.For(0, rowsA, (u, v) =>
CommonParallel.For(
0,
columnsA,
i =>
{ {
var im = i * rowsA; for (int k = u; k < v; k++)
var sum = Complex32.Zero;
for (var k = 0; k < rowsA; k++)
{ {
sum += q[im + k].Conjugate() * column[k]; column[k] = sol[jm + k];
} }
});
CommonParallel.For(0, columnsA, (u, v) =>
{
for (int i = u; i < v; i++)
{
var im = i*rowsA;
sol[jm + i] = sum; var sum = Complex32.Zero;
for (var k = 0; k < rowsA; k++)
{
sum += q[im + k].Conjugate()*column[k];
}
sol[jm + i] = sum;
}
}); });
} }
// Solve R*X = Y; // Solve R*X = Y;
for (var k = columnsA - 1; k >= 0; k--) for (var k = columnsA - 1; k >= 0; k--)
{ {
var km = k * rowsR; var km = k*rowsR;
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
sol[(j * rowsA) + k] /= r[km + k]; sol[(j*rowsA) + k] /= r[km + k];
} }
for (var i = 0; i < k; i++) for (var i = 0; i < k; i++)
{ {
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
sol[jm + i] -= sol[jm + k] * r[km + i]; sol[jm + i] -= sol[jm + k]*r[km + i];
} }
} }
} }
// Fill result matrix // Fill result matrix
CommonParallel.For( CommonParallel.For(0, columnsR, (u, v) =>
0,
columnsR,
row =>
{ {
for (var col = 0; col < columnsB; col++) for (int row = u; row < v; row++)
{ {
x[(col * columnsA) + row] = sol[row + (col * rowsA)]; for (var col = 0; col < columnsB; col++)
{
x[(col*columnsA) + row] = sol[row + (col*rowsA)];
}
} }
}); });
} }
@ -2784,7 +2846,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Copy stemp to s with size adjustment. We are using ported copy of linpack's svd code and it uses // Copy stemp to s with size adjustment. We are using ported copy of linpack's svd code and it uses
// a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed. // a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed.
// We should port lapack's svd routine to remove this problem. // We should port lapack's svd routine to remove this problem.
CommonParallel.For(0, Math.Min(rowsA, columnsA), index => s[index] = stemp[index]); Array.Copy(stemp, s, Math.Min(rowsA, columnsA));
// On return the first element of the work array stores the min size of the work array could have been // On return the first element of the work array stores the min size of the work array could have been
// work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns)); // work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns));

180
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs

@ -70,7 +70,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
} }
else else
{ {
@ -84,7 +90,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index])); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
} }
else else
{ {
@ -122,7 +134,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; }); CommonParallel.For(0, x.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
} }
else else
{ {
@ -202,7 +220,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
} }
else else
{ {
@ -247,7 +271,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
} }
else else
{ {
@ -292,7 +322,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
} }
else else
{ {
@ -337,7 +373,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
} }
else else
{ {
@ -1280,17 +1322,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
if (Control.ParallelizeOperation(columnsB * 10)) CommonParallel.For(0, columnsB, (u, v) =>
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{ {
DoCholeskySolve(a, orderA, b, index); for (int i = u; i < v; i++)
} {
} DoCholeskySolve(a, orderA, b, i);
}
});
} }
/// <summary> /// <summary>
@ -1439,7 +1477,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
} }
CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = 1.0); CommonParallel.For(0, rowsR, (a, b) =>
{
for (int i = a; i < b; i++)
{
q[(i*rowsR) + i] = 1.0;
}
});
var minmn = Math.Min(rowsR, columnsR); var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++) for (var i = 0; i < minmn; i++)
@ -1647,14 +1691,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var tmp = column * rowCount; var tmp = column * rowCount;
var index = tmp + row; var index = tmp + row;
CommonParallel.For( CommonParallel.For(row, rowCount, (u, v) =>
row,
rowCount,
i =>
{ {
var iIndex = tmp + i; for (int i = u; i < v; i++)
work[iIndex - row] = a[iIndex]; {
a[iIndex] = 0.0; var iIndex = tmp + i;
work[iIndex - row] = a[iIndex];
a[iIndex] = 0.0;
}
}); });
var norm = 0.0; var norm = 0.0;
@ -1679,11 +1723,23 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
a[index] = -1.0 / scale; a[index] = -1.0 / scale;
CommonParallel.For(0, rowCount - row, i => work[tmp + i] *= scale); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] *= scale;
}
});
work[tmp] += 1.0; work[tmp] += 1.0;
var s = Math.Sqrt(1.0 / work[tmp]); var s = Math.Sqrt(1.0 / work[tmp]);
CommonParallel.For(0, rowCount - row, i => work[tmp + i] *= s); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] *= s;
}
});
} }
#endregion #endregion
@ -1850,7 +1906,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
int rowsQ, columnsQ, rowsR, columnsR; int rowsQ, columnsQ, rowsR, columnsR;
if( method == QRMethod.Full) if (method == QRMethod.Full)
{ {
rowsQ = columnsQ = rowsR = rowsA; rowsQ = columnsQ = rowsR = rowsA;
columnsR = columnsA; columnsR = columnsA;
@ -1861,82 +1917,88 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
columnsQ = rowsR = columnsR = columnsA; columnsQ = rowsR = columnsR = columnsA;
} }
if (r.Length != rowsR * columnsR) if (r.Length != rowsR*columnsR)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
} }
if (q.Length != rowsQ * columnsQ) if (q.Length != rowsQ*columnsQ)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
} }
var sol = new double[b.Length]; var sol = new double[b.Length];
// Copy B matrix to "sol", so B data will not be changed // Copy B matrix to "sol", so B data will not be changed
Buffer.BlockCopy(b, 0, sol, 0, b.Length * Constants.SizeOfDouble); Buffer.BlockCopy(b, 0, sol, 0, b.Length*Constants.SizeOfDouble);
// Compute Y = transpose(Q)*B // Compute Y = transpose(Q)*B
var column = new double[rowsA]; var column = new double[rowsA];
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
CommonParallel.For(0, rowsA, k => column[k] = sol[jm + k]); CommonParallel.For(0, rowsA, (u, v) =>
CommonParallel.For(
0,
columnsA,
i =>
{ {
var im = i * rowsA; for (int k = u; k < v; k++)
var sum = 0.0;
for (var k = 0; k < rowsA; k++)
{ {
sum += q[im + k] * column[k]; column[k] = sol[jm + k];
} }
});
CommonParallel.For(0, columnsA, (u, v) =>
{
for (int i = u; i < v; i++)
{
var im = i*rowsA;
var sum = 0.0;
for (var k = 0; k < rowsA; k++)
{
sum += q[im + k]*column[k];
}
sol[jm + i] = sum; sol[jm + i] = sum;
}
}); });
} }
// Solve R*X = Y; // Solve R*X = Y;
for (var k = columnsA - 1; k >= 0; k--) for (var k = columnsA - 1; k >= 0; k--)
{ {
var km = k * rowsR; var km = k*rowsR;
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
sol[(j * rowsA) + k] /= r[km + k]; sol[(j*rowsA) + k] /= r[km + k];
} }
for (var i = 0; i < k; i++) for (var i = 0; i < k; i++)
{ {
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
sol[jm + i] -= sol[jm + k] * r[km + i]; sol[jm + i] -= sol[jm + k]*r[km + i];
} }
} }
} }
// Fill result matrix // Fill result matrix
CommonParallel.For( CommonParallel.For(0, columnsR, (u, v) =>
0,
columnsR,
row =>
{ {
for (var col = 0; col < columnsB; col++) for (int row = u; row < v; row++)
{ {
x[(col * columnsA) + row] = sol[row + (col * rowsA)]; for (var col = 0; col < columnsB; col++)
{
x[(col*columnsA) + row] = sol[row + (col*rowsA)];
}
} }
}); });
} }

178
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs

@ -70,7 +70,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
} }
else else
{ {
@ -84,7 +90,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index])); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
} }
else else
{ {
@ -122,7 +134,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; }); CommonParallel.For(0, x.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
} }
else else
{ {
@ -202,7 +220,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
} }
else else
{ {
@ -247,7 +271,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
} }
else else
{ {
@ -292,7 +322,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
} }
else else
{ {
@ -337,7 +373,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (Control.ParallelizeOperation(x.Length)) if (Control.ParallelizeOperation(x.Length))
{ {
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; }); CommonParallel.For(0, y.Length, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
} }
else else
{ {
@ -1281,17 +1323,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
if (Control.ParallelizeOperation(columnsB * 10)) CommonParallel.For(0, columnsB, (u, v) =>
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{ {
DoCholeskySolve(a, orderA, b, index); for (int i = u; i < v; i++)
} {
} DoCholeskySolve(a, orderA, b, i);
}
});
} }
/// <summary> /// <summary>
@ -1439,7 +1477,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
} }
CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = 1.0f); CommonParallel.For(0, rowsR, (a, b) =>
{
for (int i = a; i < b; i++)
{
q[(i*rowsR) + i] = 1.0f;
}
});
var minmn = Math.Min(rowsR, columnsR); var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++) for (var i = 0; i < minmn; i++)
@ -1648,14 +1692,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var tmp = column * rowCount; var tmp = column * rowCount;
var index = tmp + row; var index = tmp + row;
CommonParallel.For( CommonParallel.For(row, rowCount, (u, v) =>
row,
rowCount,
i =>
{ {
var iIndex = tmp + i; for (int i = u; i < v; i++)
work[iIndex - row] = a[iIndex]; {
a[iIndex] = 0.0f; var iIndex = tmp + i;
work[iIndex - row] = a[iIndex];
a[iIndex] = 0.0f;
}
}); });
var norm = 0.0; var norm = 0.0;
@ -1680,11 +1724,23 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
} }
a[index] = -1.0f / scale; a[index] = -1.0f / scale;
CommonParallel.For(0, rowCount - row, i => work[tmp + i] *= scale); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] *= scale;
}
});
work[tmp] += 1.0f; work[tmp] += 1.0f;
var s = (float)Math.Sqrt(1.0 / work[tmp]); var s = (float)Math.Sqrt(1.0 / work[tmp]);
CommonParallel.For(0, rowCount - row, i => work[tmp + i] *= s); CommonParallel.For(0, rowCount - row, (u, v) =>
{
for (int i = u; i < v; i++)
{
work[tmp + i] *= s;
}
});
} }
#endregion #endregion
@ -1863,82 +1919,88 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
columnsQ = rowsR = columnsR = columnsA; columnsQ = rowsR = columnsR = columnsA;
} }
if (r.Length != rowsR * columnsR) if (r.Length != rowsR*columnsR)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
} }
if (q.Length != rowsQ * columnsQ) if (q.Length != rowsQ*columnsQ)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
} }
var sol = new float[b.Length]; var sol = new float[b.Length];
// Copy B matrix to "sol", so B data will not be changed // Copy B matrix to "sol", so B data will not be changed
Buffer.BlockCopy(b, 0, sol, 0, b.Length * Constants.SizeOfFloat); Buffer.BlockCopy(b, 0, sol, 0, b.Length*Constants.SizeOfFloat);
// Compute Y = transpose(Q)*B // Compute Y = transpose(Q)*B
var column = new float[rowsA]; var column = new float[rowsA];
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
CommonParallel.For(0, rowsA, k => column[k] = sol[jm + k]); CommonParallel.For(0, rowsA, (u, v) =>
CommonParallel.For(
0,
columnsA,
i =>
{ {
var im = i * rowsA; for (int k = u; k < v; k++)
var sum = 0.0f;
for (var k = 0; k < rowsA; k++)
{ {
sum += q[im + k] * column[k]; column[k] = sol[jm + k];
} }
});
CommonParallel.For(0, columnsA, (u, v) =>
{
for (int i = u; i < v; i++)
{
var im = i*rowsA;
var sum = 0.0f;
for (var k = 0; k < rowsA; k++)
{
sum += q[im + k]*column[k];
}
sol[jm + i] = sum; sol[jm + i] = sum;
}
}); });
} }
// Solve R*X = Y; // Solve R*X = Y;
for (var k = columnsA - 1; k >= 0; k--) for (var k = columnsA - 1; k >= 0; k--)
{ {
var km = k * rowsR; var km = k*rowsR;
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
sol[(j * rowsA) + k] /= r[km + k]; sol[(j*rowsA) + k] /= r[km + k];
} }
for (var i = 0; i < k; i++) for (var i = 0; i < k; i++)
{ {
for (var j = 0; j < columnsB; j++) for (var j = 0; j < columnsB; j++)
{ {
var jm = j * rowsA; var jm = j*rowsA;
sol[jm + i] -= sol[jm + k] * r[km + i]; sol[jm + i] -= sol[jm + k]*r[km + i];
} }
} }
} }
// Fill result matrix // Fill result matrix
CommonParallel.For( CommonParallel.For(0, columnsR, (u, v) =>
0,
columnsR,
row =>
{ {
for (var col = 0; col < columnsB; col++) for (int row = u; row < v; row++)
{ {
x[(col * columnsA) + row] = sol[row + (col * rowsA)]; for (var col = 0; col < columnsB; col++)
{
x[(col*columnsA) + row] = sol[row + (col*rowsA)];
}
} }
}); });
} }

34
src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// //
// Copyright (c) 2009-2010 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -47,24 +47,24 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
/// <returns>Corresponding frequency-space vector.</returns> /// <returns>Corresponding frequency-space vector.</returns>
internal static Complex[] Naive(Complex[] samples, int exponentSign) internal static Complex[] Naive(Complex[] samples, int exponentSign)
{ {
var w0 = exponentSign * Constants.Pi2 / samples.Length; var w0 = exponentSign*Constants.Pi2/samples.Length;
var spectrum = new Complex[samples.Length]; var spectrum = new Complex[samples.Length];
CommonParallel.For( CommonParallel.For(0, samples.Length, (u, v) =>
0, {
samples.Length, for (int i = u; i < v; i++)
index => {
{ var wk = w0*i;
var wk = w0 * index; var sum = Complex.Zero;
var sum = Complex.Zero; for (var n = 0; n < samples.Length; n++)
for (var n = 0; n < samples.Length; n++) {
{ var w = n*wk;
var w = n * wk; sum += samples[n]*new Complex(Math.Cos(w), Math.Sin(w));
sum += samples[n] * new Complex(Math.Cos(w), Math.Sin(w)); }
}
spectrum[index] = sum; spectrum[i] = sum;
}); }
});
return spectrum; return spectrum;
} }
@ -95,4 +95,4 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
return timeSpace; return timeSpace;
} }
} }
} }

26
src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// //
// Copyright (c) 2009-2010 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -46,7 +46,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
/// </summary> /// </summary>
/// <typeparam name="T">Sample type</typeparam> /// <typeparam name="T">Sample type</typeparam>
/// <param name="samples">Sample vector</param> /// <param name="samples">Sample vector</param>
private static void Radix2Reorder<T>(T[] samples) static void Radix2Reorder<T>(T[] samples)
{ {
var j = 0; var j = 0;
for (var i = 0; i < samples.Length - 1; i++) for (var i = 0; i < samples.Length - 1; i++)
@ -64,8 +64,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
{ {
m >>= 1; m >>= 1;
j ^= m; j ^= m;
} } while ((j & m) == 0);
while ((j & m) == 0);
} }
} }
@ -76,17 +75,17 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
/// <param name="exponentSign">Fourier series exponent sign.</param> /// <param name="exponentSign">Fourier series exponent sign.</param>
/// <param name="levelSize">Level Group Size.</param> /// <param name="levelSize">Level Group Size.</param>
/// <param name="k">Index inside of the level.</param> /// <param name="k">Index inside of the level.</param>
private static void Radix2Step(Complex[] samples, int exponentSign, int levelSize, int k) static void Radix2Step(Complex[] samples, int exponentSign, int levelSize, int k)
{ {
// Twiddle Factor // Twiddle Factor
var exponent = (exponentSign * k) * Constants.Pi / levelSize; var exponent = (exponentSign*k)*Constants.Pi/levelSize;
var w = new Complex(Math.Cos(exponent), Math.Sin(exponent)); var w = new Complex(Math.Cos(exponent), Math.Sin(exponent));
var step = levelSize << 1; var step = levelSize << 1;
for (var i = k; i < samples.Length; i += step) for (var i = k; i < samples.Length; i += step)
{ {
var ai = samples[i]; var ai = samples[i];
var t = w * samples[i + levelSize]; var t = w*samples[i + levelSize];
samples[i] = ai + t; samples[i] = ai + t;
samples[i + levelSize] = ai - t; samples[i + levelSize] = ai - t;
} }
@ -133,10 +132,13 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
{ {
var size = levelSize; var size = levelSize;
CommonParallel.For( CommonParallel.For(0, size, (u, v) =>
0, {
size, for (int i = u; i < v; i++)
index => Radix2Step(samples, exponentSign, size, index)); {
Radix2Step(samples, exponentSign, size, i);
}
});
} }
} }
@ -164,4 +166,4 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
InverseScaleByOptions(options, samples); InverseScaleByOptions(options, samples);
} }
} }
} }

28
src/Numerics/IntegralTransforms/Algorithms/DiscreteHartleyTransform.Naive.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// //
// Copyright (c) 2009-2010 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -45,23 +45,23 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
/// <returns>Corresponding frequency-space vector.</returns> /// <returns>Corresponding frequency-space vector.</returns>
internal static double[] Naive(double[] samples) internal static double[] Naive(double[] samples)
{ {
var w0 = Constants.Pi2 / samples.Length; var w0 = Constants.Pi2/samples.Length;
var spectrum = new double[samples.Length]; var spectrum = new double[samples.Length];
CommonParallel.For( CommonParallel.For(0, samples.Length, (u, v) =>
0,
samples.Length,
index =>
{ {
var wk = w0 * index; for (int i = u; i < v; i++)
var sum = 0.0;
for (var n = 0; n < samples.Length; n++)
{ {
var w = n * wk; var wk = w0*i;
sum += samples[n] * Constants.Sqrt2 * Math.Cos(w - Constants.PiOver4); var sum = 0.0;
} for (var n = 0; n < samples.Length; n++)
{
var w = n*wk;
sum += samples[n]*Constants.Sqrt2*Math.Cos(w - Constants.PiOver4);
}
spectrum[index] = sum; spectrum[i] = sum;
}
}); });
return spectrum; return spectrum;
@ -93,4 +93,4 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
return timeSpace; return timeSpace;
} }
} }
} }

45
src/Numerics/LinearAlgebra/Complex/DenseVector.cs

@ -233,10 +233,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] + scalar); {
dense._values[i] = _values[i] + scalar;
}
});
} }
} }
@ -292,10 +295,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] - scalar); {
dense._values[i] = _values[i] - scalar;
}
});
} }
} }
@ -625,14 +631,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
} }
var matrix = new DenseMatrix(u.Count, v.Count); var matrix = new DenseMatrix(u.Count, v.Count);
CommonParallel.For( CommonParallel.For(0, u.Count, (a, b) =>
0,
u.Count,
i =>
{ {
for (var j = 0; j < v.Count; j++) for (int i = a; i < b; i++)
{ {
matrix.At(i, j, u._values[i] * v._values[j]); for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u._values[i]*v._values[j]);
}
} }
}); });
return matrix; return matrix;
@ -860,10 +866,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return; return;
} }
CommonParallel.For( CommonParallel.For(0, _length, (a, b) =>
0, {
_length, for (int i = a; i < b; i++)
index => resultDense._values[index] = _values[index].Conjugate()); {
resultDense._values[i] = _values[i].Conjugate();
}
});
} }
} }
} }

4
src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs

@ -120,7 +120,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor; var dfactor = (DenseMatrix)CholeskyFactor;
@ -169,7 +169,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor; var dfactor = (DenseMatrix)CholeskyFactor;

4
src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs

@ -121,7 +121,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// LU solve by overwriting result. // LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors; var dfactors = (DenseMatrix)Factors;
@ -170,7 +170,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// LU solve by overwriting result. // LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors; var dfactors = (DenseMatrix)Factors;

2
src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

@ -805,7 +805,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
CopyTo(sparseResult); CopyTo(sparseResult);
} }
CommonParallel.For(0, NonZerosCount, index => sparseResult._storage.Values[index] *= scalar); Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
} }
} }

10
src/Numerics/LinearAlgebra/Complex/SparseVector.cs

@ -202,8 +202,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
if (_storage.ValueCount != 0) if (_storage.ValueCount != 0)
{ {
CommonParallel.For(0, _storage.ValueCount, index => targetSparse._storage.Values[index] = _storage.Values[index].Conjugate()); CommonParallel.For(0, _storage.ValueCount, (a, b) =>
Buffer.BlockCopy(_storage.Indices, 0, targetSparse._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt); {
for (int i = a; i < b; i++)
{
targetSparse._storage.Values[i] = _storage.Values[i].Conjugate();
}
});
Buffer.BlockCopy(_storage.Indices, 0, targetSparse._storage.Indices, 0, _storage.ValueCount*Constants.SizeOfInt);
} }
} }

45
src/Numerics/LinearAlgebra/Complex32/DenseVector.cs

@ -232,10 +232,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] + scalar); {
dense._values[i] = _values[i] + scalar;
}
});
} }
} }
@ -291,10 +294,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] - scalar); {
dense._values[i] = _values[i] - scalar;
}
});
} }
} }
@ -624,14 +630,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
} }
var matrix = new DenseMatrix(u.Count, v.Count); var matrix = new DenseMatrix(u.Count, v.Count);
CommonParallel.For( CommonParallel.For(0, u.Count, (a, b) =>
0,
u.Count,
i =>
{ {
for (var j = 0; j < v.Count; j++) for (int i = a; i < b; i++)
{ {
matrix.At(i, j, u._values[i] * v._values[j]); for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u._values[i]*v._values[j]);
}
} }
}); });
return matrix; return matrix;
@ -859,10 +865,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return; return;
} }
CommonParallel.For( CommonParallel.For(0, _length, (a, b) =>
0, {
_length, for (int i = a; i < b; i++)
index => resultDense._values[index] = _values[index].Conjugate()); {
resultDense._values[i] = _values[i].Conjugate();
}
});
} }
} }
} }

4
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.cs

@ -120,7 +120,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor; var dfactor = (DenseMatrix)CholeskyFactor;
@ -169,7 +169,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor; var dfactor = (DenseMatrix)CholeskyFactor;

4
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseLU.cs

@ -121,7 +121,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// LU solve by overwriting result. // LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors; var dfactors = (DenseMatrix)Factors;
@ -170,7 +170,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
} }
// Copy the contents of input to result. // Copy the contents of input to result.
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// LU solve by overwriting result. // LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors; var dfactors = (DenseMatrix)Factors;

2
src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

@ -804,7 +804,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
CopyTo(sparseResult); CopyTo(sparseResult);
} }
CommonParallel.For(0, NonZerosCount, index => sparseResult._storage.Values[index] *= scalar); Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
} }
} }

10
src/Numerics/LinearAlgebra/Complex32/SparseVector.cs

@ -202,8 +202,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
if (_storage.ValueCount != 0) if (_storage.ValueCount != 0)
{ {
CommonParallel.For(0, _storage.ValueCount, index => targetSparse._storage.Values[index] = _storage.Values[index].Conjugate()); CommonParallel.For(0, _storage.ValueCount, (a, b) =>
Buffer.BlockCopy(_storage.Indices, 0, targetSparse._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt); {
for (int i = a; i < b; i++)
{
targetSparse._storage.Values[i] = _storage.Values[i].Conjugate();
}
});
Buffer.BlockCopy(_storage.Indices, 0, targetSparse._storage.Indices, 0, _storage.ValueCount*Constants.SizeOfInt);
} }
} }

26
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -559,23 +559,25 @@ namespace MathNet.Numerics.LinearAlgebra.Double
protected override void DoModulus(double divisor, Matrix<double> result) protected override void DoModulus(double divisor, Matrix<double> result)
{ {
var denseResult = result as DenseMatrix; var denseResult = result as DenseMatrix;
if (denseResult == null) if (denseResult == null)
{ {
base.DoModulus(divisor, result); base.DoModulus(divisor, result);
return;
} }
else
{
if (!ReferenceEquals(this, result))
{
CopyTo(result);
}
CommonParallel.For( if (!ReferenceEquals(this, result))
0, {
_values.Length, CopyTo(result);
index => denseResult._values[index] %= divisor);
} }
CommonParallel.For(0, _values.Length, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] %= divisor;
}
});
} }
/// <summary> /// <summary>

34
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -233,10 +233,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] + scalar); {
dense._values[i] = _values[i] + scalar;
}
});
} }
} }
@ -302,10 +305,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] - scalar); {
dense._values[i] = _values[i] - scalar;
}
});
} }
} }
@ -716,14 +722,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
} }
var matrix = new DenseMatrix(u.Count, v.Count); var matrix = new DenseMatrix(u.Count, v.Count);
CommonParallel.For( CommonParallel.For(0, u.Count, (a, b) =>
0,
u.Count,
i =>
{ {
for (var j = 0; j < v.Count; j++) for (int i = a; i < b; i++)
{ {
matrix.At(i, j, u._values[i] * v._values[j]); for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u._values[i]*v._values[j]);
}
} }
}); });
return matrix; return matrix;

2
src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

@ -803,7 +803,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
CopyTo(sparseResult); CopyTo(sparseResult);
} }
CommonParallel.For(0, _storage.ValueCount, index => sparseResult._storage.Values[index] *= scalar); Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
} }
} }

24
src/Numerics/LinearAlgebra/Single/DenseMatrix.cs

@ -559,23 +559,25 @@ namespace MathNet.Numerics.LinearAlgebra.Single
protected override void DoModulus(float divisor, Matrix<float> result) protected override void DoModulus(float divisor, Matrix<float> result)
{ {
var denseResult = result as DenseMatrix; var denseResult = result as DenseMatrix;
if (denseResult == null) if (denseResult == null)
{ {
base.DoModulus(divisor, result); base.DoModulus(divisor, result);
return;
} }
else
{
if (!ReferenceEquals(this, result))
{
CopyTo(result);
}
CommonParallel.For( if (!ReferenceEquals(this, result))
0, {
_values.Length, CopyTo(result);
index => denseResult._values[index] %= divisor);
} }
CommonParallel.For(0, _values.Length, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] %= divisor;
}
});
} }
/// <summary> /// <summary>

34
src/Numerics/LinearAlgebra/Single/DenseVector.cs

@ -232,10 +232,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] + scalar); {
dense._values[i] = _values[i] + scalar;
}
});
} }
} }
@ -291,10 +294,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single
} }
else else
{ {
CommonParallel.For( CommonParallel.For(0, _values.Length, (a, b) =>
0, {
_values.Length, for (int i = a; i < b; i++)
index => dense._values[index] = _values[index] - scalar); {
dense._values[i] = _values[i] - scalar;
}
});
} }
} }
@ -705,14 +711,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
} }
var matrix = new DenseMatrix(u.Count, v.Count); var matrix = new DenseMatrix(u.Count, v.Count);
CommonParallel.For( CommonParallel.For(0, u.Count, (a, b) =>
0,
u.Count,
i =>
{ {
for (var j = 0; j < v.Count; j++) for (int i = a; i < b; i++)
{ {
matrix.At(i, j, u._values[i] * v._values[j]); for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u._values[i]*v._values[j]);
}
} }
}); });
return matrix; return matrix;

2
src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

@ -802,7 +802,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
CopyTo(sparseResult); CopyTo(sparseResult);
} }
CommonParallel.For(0, NonZerosCount, index => sparseResult._storage.Values[index] *= scalar); Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
} }
} }

78
src/Numerics/Random/Palf.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// //
// Copyright (c) 2009-2010 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -48,17 +48,17 @@ namespace MathNet.Numerics.Random
/// <summary> /// <summary>
/// Default value for the ShortLag /// Default value for the ShortLag
/// </summary> /// </summary>
private const int DefaultShortLag = 418; const int DefaultShortLag = 418;
/// <summary> /// <summary>
/// Default value for the LongLag /// Default value for the LongLag
/// </summary> /// </summary>
private const int DefaultLongLag = 1279; const int DefaultLongLag = 1279;
/// <summary> /// <summary>
/// The multiplier to compute a double-precision floating point number [0, 1) /// The multiplier to compute a double-precision floating point number [0, 1)
/// </summary> /// </summary>
private const double IntToDoubleMultiplier = 1.0 / (int.MaxValue + 1.0); const double IntToDoubleMultiplier = 1.0/(int.MaxValue + 1.0);
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Palf"/> class using /// Initializes a new instance of the <see cref="Palf"/> class using
@ -67,7 +67,8 @@ namespace MathNet.Numerics.Random
/// <remarks>If the seed value is zero, it is set to one. Uses the /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// set whether the instance is thread safe.</remarks>
public Palf() : this((int)DateTime.Now.Ticks) public Palf()
: this((int) DateTime.Now.Ticks)
{ {
} }
@ -76,7 +77,8 @@ namespace MathNet.Numerics.Random
/// the current time as the seed. /// the current time as the seed.
/// </summary> /// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param> /// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Palf(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe, DefaultShortLag, DefaultLongLag) public Palf(bool threadSafe)
: this((int) DateTime.Now.Ticks, threadSafe, DefaultShortLag, DefaultLongLag)
{ {
} }
@ -87,7 +89,8 @@ namespace MathNet.Numerics.Random
/// <remarks>If the seed value is zero, it is set to one. Uses the /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// set whether the instance is thread safe.</remarks>
public Palf(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag) public Palf(int seed)
: this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag)
{ {
} }
@ -98,7 +101,8 @@ namespace MathNet.Numerics.Random
/// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param> /// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param>
/// <param name="shortLag">The ShortLag value</param> /// <param name="shortLag">The ShortLag value</param>
/// <param name="longLag">TheLongLag value</param> /// <param name="longLag">TheLongLag value</param>
public Palf(int seed, bool threadSafe, int shortLag, int longLag) : base(threadSafe) public Palf(int seed, bool threadSafe, int shortLag, int longLag)
: base(threadSafe)
{ {
if (shortLag < 1) if (shortLag < 1)
{ {
@ -116,54 +120,46 @@ namespace MathNet.Numerics.Random
} }
ShortLag = shortLag; ShortLag = shortLag;
// Align LongLag to number of worker threads. // Align LongLag to number of worker threads.
if (longLag % Control.NumberOfParallelWorkerThreads == 0) if (longLag%Control.NumberOfParallelWorkerThreads == 0)
{ {
LongLag = longLag; LongLag = longLag;
} }
else else
{ {
LongLag = ((longLag / Control.NumberOfParallelWorkerThreads) + 1) * Control.NumberOfParallelWorkerThreads; LongLag = ((longLag/Control.NumberOfParallelWorkerThreads) + 1)*Control.NumberOfParallelWorkerThreads;
} }
_x = new uint[LongLag]; _x = new uint[LongLag];
var gen = new MersenneTwister(seed, threadSafe); var gen = new MersenneTwister(seed, threadSafe);
for (var j = 0; j < LongLag; ++j) for (var j = 0; j < LongLag; ++j)
{ {
_x[j] = (uint)(gen.NextDouble() * uint.MaxValue); _x[j] = (uint) (gen.NextDouble()*uint.MaxValue);
} }
_i = LongLag; _i = LongLag;
} }
/// <summary> /// <summary>
/// Gets the short lag of the Lagged Fibonacci pseudo-random number generator. /// Gets the short lag of the Lagged Fibonacci pseudo-random number generator.
/// </summary> /// </summary>
public int ShortLag public int ShortLag { get; private set; }
{
get;
private set;
}
/// <summary> /// <summary>
/// Gets the long lag of the Lagged Fibonacci pseudo-random number generator. /// Gets the long lag of the Lagged Fibonacci pseudo-random number generator.
/// </summary> /// </summary>
public int LongLag public int LongLag { get; private set; }
{
get;
private set;
}
/// <summary> /// <summary>
/// Stores an array of <see cref="LongLag"/> random numbers /// Stores an array of <see cref="LongLag"/> random numbers
/// </summary> /// </summary>
private readonly uint[] _x; readonly uint[] _x;
/// <summary> /// <summary>
/// Stores an index for the random number array element that will be accessed next. /// Stores an index for the random number array element that will be accessed next.
/// </summary> /// </summary>
private int _i; int _i;
/// <summary> /// <summary>
/// Fills the array <see cref="_x"/> with <see cref="LongLag"/> new unsigned random numbers. /// Fills the array <see cref="_x"/> with <see cref="LongLag"/> new unsigned random numbers.
@ -172,22 +168,22 @@ namespace MathNet.Numerics.Random
/// Generated random numbers are 32-bit unsigned integers greater than or equal to 0 /// Generated random numbers are 32-bit unsigned integers greater than or equal to 0
/// and less than or equal to <see cref="Int32.MaxValue"/>. /// and less than or equal to <see cref="Int32.MaxValue"/>.
/// </remarks> /// </remarks>
private void Fill() void Fill()
{ {
CommonParallel.For( CommonParallel.For(0, Control.NumberOfParallelWorkerThreads, (u, v) =>
0,
Control.NumberOfParallelWorkerThreads,
index =>
{ {
// Two loops to avoid costly modulo operations for (int index = u; index < v; index++)
for (var j = index; j < ShortLag; j = j + Control.NumberOfParallelWorkerThreads)
{
_x[j] += _x[j + (LongLag - ShortLag)];
}
for (var j = ShortLag + index; j < LongLag; j = j + Control.NumberOfParallelWorkerThreads)
{ {
_x[j] += _x[j - ShortLag - index]; // Two loops to avoid costly modulo operations
for (var j = index; j < ShortLag; j = j + Control.NumberOfParallelWorkerThreads)
{
_x[j] += _x[j + (LongLag - ShortLag)];
}
for (var j = ShortLag + index; j < LongLag; j = j + Control.NumberOfParallelWorkerThreads)
{
_x[j] += _x[j - ShortLag - index];
}
} }
}); });
_i = 0; _i = 0;
@ -207,7 +203,7 @@ namespace MathNet.Numerics.Random
} }
var x = _x[_i++]; var x = _x[_i++];
return (int)(x >> 1) * IntToDoubleMultiplier; return (int) (x >> 1)*IntToDoubleMultiplier;
} }
} }
} }

236
src/Numerics/Threading/CommonParallel.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// //
// Copyright (c) 2009-2012 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -38,7 +38,7 @@ namespace MathNet.Numerics.Threading
using System.Collections.Generic; using System.Collections.Generic;
#else #else
using System.Linq; using System.Linq;
using MathNet.Numerics.Properties; using Properties;
#endif #endif
/// <summary> /// <summary>
@ -54,80 +54,91 @@ namespace MathNet.Numerics.Threading
/// <param name="body">The body to be invoked for each iteration.</param> /// <param name="body">The body to be invoked for each iteration.</param>
/// <exception cref="ArgumentNullException">The <paramref name="body"/> argument is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">The <paramref name="body"/> argument is <c>null</c>.</exception>
/// <exception cref="AggregateException">At least one invocation of the body threw an exception.</exception> /// <exception cref="AggregateException">At least one invocation of the body threw an exception.</exception>
[Obsolete("Scheduled for removal in v3.0.")]
public static void For(int fromInclusive, int toExclusive, Action<int> body) public static void For(int fromInclusive, int toExclusive, Action<int> body)
{ {
if (body == null) if (body == null) throw new ArgumentNullException("body");
{ if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
throw new ArgumentNullException("body");
}
// Special case: no action int rangeSize = (toExclusive - fromInclusive)/(Control.NumberOfParallelWorkerThreads*2);
if (fromInclusive >= toExclusive) rangeSize = Math.Max(rangeSize, 1);
{
return;
}
// Special case: single action, inline For(fromInclusive,
if (fromInclusive == (toExclusive - 1)) toExclusive,
rangeSize,
(start, stop) =>
{
for (var i = start; i < stop; i++)
{
body(i);
}
});
}
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
/// <param name="fromInclusive">The start index, inclusive.</param>
/// <param name="toExclusive">The end index, exclusive.</param>
/// <param name="body">The body to be invoked for each iteration range.</param>
public static void For(int fromInclusive, int toExclusive, Action<int, int> body)
{
For(fromInclusive, toExclusive, Math.Max(1, (toExclusive - fromInclusive)/Control.NumberOfParallelWorkerThreads), body);
}
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
/// <param name="fromInclusive">The start index, inclusive.</param>
/// <param name="toExclusive">The end index, exclusive.</param>
/// <param name="body">The body to be invoked for each iteration range.</param>
public static void For(int fromInclusive, int toExclusive, int rangeSize, Action<int, int> body)
{
if (body == null) throw new ArgumentNullException("body");
if (fromInclusive < 0) throw new ArgumentOutOfRangeException("fromInclusive");
if (fromInclusive > toExclusive) throw new ArgumentOutOfRangeException("toExclusive");
if (rangeSize < 1) throw new ArgumentOutOfRangeException("rangeSize");
var length = toExclusive - fromInclusive;
// Special case: nothing to do
if (length <= 0)
{ {
body(fromInclusive);
return; return;
} }
// Special case: straight execution without parallelism var maxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads;
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
// Special case: not worth to parallelize, inline
if (Control.DisableParallelization || maxDegreeOfParallelism < 2 || (rangeSize*2) > length)
{ {
for (var index = fromInclusive; index < toExclusive; index++) body(fromInclusive, toExclusive);
{
body(index);
}
return; return;
} }
// Common case
#if PORTABLE #if PORTABLE
var tasks = new Task[Control.NumberOfParallelWorkerThreads]; var tasks = new Task[Math.Min(maxDegreeOfParallelism, length/rangeSize)];
var size = (toExclusive - fromInclusive) / tasks.Length; rangeSize = (toExclusive - fromInclusive)/tasks.Length;
// partition the jobs into separate sets for each but the last worked thread // partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < tasks.Length - 1; i++) for (var i = 0; i < tasks.Length - 1; i++)
{ {
var start = fromInclusive + (i * size); var start = fromInclusive + (i*rangeSize);
var stop = fromInclusive + ((i + 1) * size); var stop = fromInclusive + ((i + 1)*rangeSize);
tasks[i] = Task.Factory.StartNew(() => tasks[i] = Task.Factory.StartNew(() => body(start, stop));
{
for (int j = start; j < stop; j++)
{
body(j);
}
});
} }
// add another set for last worker thread // add another set for last worker thread
tasks[tasks.Length - 1] = Task.Factory.StartNew(() => tasks[tasks.Length - 1] =
{ Task.Factory.StartNew(() => body(fromInclusive + ((tasks.Length - 1)*rangeSize), toExclusive));
for (int j = fromInclusive + ((tasks.Length - 1) * size); j < toExclusive; j++)
{
body(j);
}
});
Task.WaitAll(tasks); Task.WaitAll(tasks);
#else #else
Parallel.ForEach( Parallel.ForEach(
Partitioner.Create(fromInclusive, toExclusive), Partitioner.Create(fromInclusive, toExclusive, rangeSize),
new ParallelOptions new ParallelOptions {MaxDegreeOfParallelism = maxDegreeOfParallelism},
{ (range, loopState) => body(range.Item1, range.Item2));
MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads
},
(range, loopState) =>
{
for (var i = range.Item1; i < range.Item2; i++)
{
body(i);
}
});
#endif #endif
} }
@ -203,16 +214,16 @@ namespace MathNet.Numerics.Threading
Parallel.ForEach( Parallel.ForEach(
Partitioner.Create(0, array.Length), Partitioner.Create(0, array.Length),
new ParallelOptions new ParallelOptions
{ {
MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads
}, },
(range, loopState) => (range, loopState) =>
{
for (var i = range.Item1; i < range.Item2; i++)
{ {
body(i, array[i]); for (var i = range.Item1; i < range.Item2; i++)
} {
}); body(i, array[i]);
}
});
#endif #endif
} }
@ -237,6 +248,16 @@ namespace MathNet.Numerics.Threading
return; return;
} }
// Special case: straight execution without parallelism
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
{
for (int i = 0; i < actions.Length; i++)
{
actions[i]();
}
return;
}
// Common case // Common case
#if PORTABLE #if PORTABLE
var tasks = new Task[actions.Length]; var tasks = new Task[actions.Length];
@ -252,12 +273,11 @@ namespace MathNet.Numerics.Threading
} }
Task.WaitAll(tasks); Task.WaitAll(tasks);
#else #else
var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads;
Parallel.Invoke( Parallel.Invoke(
new ParallelOptions new ParallelOptions
{ {
MaxDegreeOfParallelism = maxThreads MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads
}, },
actions); actions);
#endif #endif
} }
@ -290,7 +310,7 @@ namespace MathNet.Numerics.Threading
// Special case: single action, inline // Special case: single action, inline
if (fromInclusive == (toExclusive - 1)) if (fromInclusive == (toExclusive - 1))
{ {
return reduce(new [] { select(fromInclusive) }); return reduce(new[] {select(fromInclusive)});
} }
// Special case: straight execution without parallelism // Special case: straight execution without parallelism
@ -346,25 +366,25 @@ namespace MathNet.Numerics.Threading
var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads; var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads;
Parallel.ForEach( Parallel.ForEach(
Partitioner.Create(fromInclusive, toExclusive), Partitioner.Create(fromInclusive, toExclusive),
new ParallelOptions { MaxDegreeOfParallelism = maxThreads }, new ParallelOptions {MaxDegreeOfParallelism = maxThreads},
() => new List<T>(), () => new List<T>(),
(range, loop, localData) => (range, loop, localData) =>
{
var mapped = new T[range.Item2 - range.Item1];
for (int k = 0; k < mapped.Length; k++)
{ {
mapped[k] = select(k + range.Item1); var mapped = new T[range.Item2 - range.Item1];
} for (int k = 0; k < mapped.Length; k++)
localData.Add(reduce(mapped)); {
return localData; mapped[k] = select(k + range.Item1);
}, }
localData.Add(reduce(mapped));
return localData;
},
localResult => localResult =>
{
lock (syncLock)
{ {
intermediateResults.Add(reduce(localResult.ToArray())); lock (syncLock)
} {
}); intermediateResults.Add(reduce(localResult.ToArray()));
}
});
return reduce(intermediateResults.ToArray()); return reduce(intermediateResults.ToArray());
#endif #endif
} }
@ -396,7 +416,7 @@ namespace MathNet.Numerics.Threading
// Special case: single action, inline // Special case: single action, inline
if (array.Length == 1) if (array.Length == 1)
{ {
return reduce(new[] { select(0, array[0]) }); return reduce(new[] {select(0, array[0])});
} }
// Special case: straight execution without parallelism // Special case: straight execution without parallelism
@ -452,25 +472,25 @@ namespace MathNet.Numerics.Threading
var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads; var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads;
Parallel.ForEach( Parallel.ForEach(
Partitioner.Create(0, array.Length), Partitioner.Create(0, array.Length),
new ParallelOptions { MaxDegreeOfParallelism = maxThreads }, new ParallelOptions {MaxDegreeOfParallelism = maxThreads},
() => new List<U>(), () => new List<U>(),
(range, loop, localData) => (range, loop, localData) =>
{
var mapped = new U[range.Item2 - range.Item1];
for (int k = 0; k < mapped.Length; k++)
{ {
mapped[k] = select(k + range.Item1, array[k + range.Item1]); var mapped = new U[range.Item2 - range.Item1];
} for (int k = 0; k < mapped.Length; k++)
localData.Add(reduce(mapped)); {
return localData; mapped[k] = select(k + range.Item1, array[k + range.Item1]);
}, }
localData.Add(reduce(mapped));
return localData;
},
localResult => localResult =>
{
lock (syncLock)
{ {
intermediateResults.Add(reduce(localResult.ToArray())); lock (syncLock)
} {
}); intermediateResults.Add(reduce(localResult.ToArray()));
}
});
return reduce(intermediateResults.ToArray()); return reduce(intermediateResults.ToArray());
#endif #endif
} }
@ -518,24 +538,24 @@ namespace MathNet.Numerics.Threading
public static U Aggregate<T, U>(T[] array, Func<int, T, U> select, Func<U, U, U> reducePair, U reduceDefault) public static U Aggregate<T, U>(T[] array, Func<int, T, U> select, Func<U, U, U> reducePair, U reduceDefault)
{ {
return Aggregate(array, select, results => return Aggregate(array, select, results =>
{
if (results == null || results.Length == 0)
{ {
return reduceDefault; if (results == null || results.Length == 0)
} {
return reduceDefault;
}
if (results.Length == 1) if (results.Length == 1)
{ {
return results[0]; return results[0];
} }
U result = results[0]; U result = results[0];
for (int i = 1; i < results.Length; i++) for (int i = 1; i < results.Length; i++)
{ {
result = reducePair(result, results[i]); result = reducePair(result, results[i]);
} }
return result; return result;
}); });
} }
} }
} }
Loading…
Cancel
Save