Browse Source

tweaked cholesky solve

fixed issue with LU solve for complex types using parallel element copy instead of Array.Copy
la-knuth
Marcus Cuda 15 years ago
parent
commit
08f1483e87
  1. 152
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs
  2. 152
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs
  3. 157
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs
  4. 154
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs
  5. 17
      src/Numerics/Control.cs

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

@ -67,35 +67,35 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (alpha.IsZero())
{
Array.Copy(y, result, y.Length);
y.Copy(result);
}
else if (alpha.IsOne())
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + x[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + (alpha * x[index]);
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
}
}
@ -119,21 +119,21 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
else if (alpha.IsOne())
{
Array.Copy(x, result, x.Length);
x.Copy(result);
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = alpha * x[index];
}
}
else
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
}
}
@ -202,17 +202,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] + y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
}
/// <summary>
@ -247,17 +247,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] - y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
}
/// <summary>
@ -292,17 +292,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] * y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
}
/// <summary>
@ -337,17 +337,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] / y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
}
/// <summary>
@ -1065,7 +1065,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
LUSolveFactored(order, a, order, ipiv, inverse);
CommonParallel.For(0, a.Length, index => a[index] = inverse[index]);
inverse.Copy(a);
}
/// <summary>
@ -1134,7 +1134,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var ipiv = new int[order];
var clone = new Complex[a.Length];
Array.Copy(a, 0, clone, 0, a.Length);
a.Copy(clone);
LUFactor(clone, order, ipiv);
LUSolveFactored(columnsOfB, clone, order, ipiv, b);
}
@ -1357,7 +1357,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
var clone = new Complex[a.Length];
Array.Copy(a, 0, clone, 0, a.Length);
a.Copy(clone);
CholeskyFactor(clone, orderA);
CholeskySolveFactored(clone, orderA, b, columnsB);
}
@ -1392,39 +1392,55 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
CommonParallel.For(
0,
columnsB,
c =>
if (Control.ParallelizeOperation(columnsB * 10))
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{
var cindex = c * orderA;
DoCholeskySolve(a, orderA, b, index);
}
}
}
// Solve L*Y = B;
Complex sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
/// <summary>
/// Solves A*X=B for X using a previously factored A matrix.
/// </summary>
/// <param name="a">The square, positive definite matrix A. Has to be different than <paramref name="b"/>.</param>
/// <param name="orderA">The number of rows and columns in A.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="index">The column to solve for.</param>
private static void DoCholeskySolve(Complex[] a, int orderA, Complex[] b, int index)
{
var cindex = index * orderA;
b[cindex + i] = sum / a[(i * orderA) + i];
}
// Solve L*Y = B;
Complex sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k].Conjugate() * b[cindex + k];
}
b[cindex + i] = sum / a[(i * orderA) + i];
}
b[cindex + i] = sum / a[iindex + i];
}
});
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k].Conjugate() * b[cindex + k];
}
b[cindex + i] = sum / a[iindex + i];
}
}
/// <summary>

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

@ -61,35 +61,35 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (alpha.IsZero())
{
Array.Copy(y, result, y.Length);
y.Copy(result);
}
else if (alpha.IsOne())
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + x[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + (alpha * x[index]);
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
}
}
@ -114,21 +114,21 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
else if (alpha.IsOne())
{
Array.Copy(x, result, x.Length);
x.Copy(result);
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = alpha * x[index];
}
}
else
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
}
}
@ -198,17 +198,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] + y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
}
/// <summary>
@ -243,17 +243,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] - y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
}
/// <summary>
@ -288,17 +288,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] * y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
}
/// <summary>
@ -333,17 +333,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] / y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
}
/// <summary>
@ -1061,7 +1061,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
LUSolveFactored(order, a, order, ipiv, inverse);
CommonParallel.For(0, a.Length, index => a[index] = inverse[index]);
inverse.Copy(a);
}
/// <summary>
@ -1130,7 +1130,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var ipiv = new int[order];
var clone = new Complex32[a.Length];
Array.Copy(a, 0, clone, 0, a.Length);
a.Copy(clone);
LUFactor(clone, order, ipiv);
LUSolveFactored(columnsOfB, clone, order, ipiv, b);
}
@ -1353,7 +1353,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
var clone = new Complex32[a.Length];
Array.Copy(a, 0, clone, 0, a.Length);
a.Copy(clone);
CholeskyFactor(clone, orderA);
CholeskySolveFactored(clone, orderA, b, columnsB);
}
@ -1388,39 +1388,55 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
CommonParallel.For(
0,
columnsB,
c =>
if (Control.ParallelizeOperation(columnsB * 10))
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{
var cindex = c * orderA;
DoCholeskySolve(a, orderA, b, index);
}
}
}
// Solve L*Y = B;
Complex32 sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
/// <summary>
/// Solves A*X=B for X using a previously factored A matrix.
/// </summary>
/// <param name="a">The square, positive definite matrix A. Has to be different than <paramref name="b"/>.</param>
/// <param name="orderA">The number of rows and columns in A.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="index">The column to solve for.</param>
private static void DoCholeskySolve(Complex32[] a, int orderA, Complex32[] b, int index)
{
var cindex = index * orderA;
b[cindex + i] = sum / a[(i * orderA) + i];
}
// Solve L*Y = B;
Complex32 sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k].Conjugate() * b[cindex + k];
}
b[cindex + i] = sum / a[(i * orderA) + i];
}
b[cindex + i] = sum / a[iindex + i];
}
});
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k].Conjugate() * b[cindex + k];
}
b[cindex + i] = sum / a[iindex + i];
}
}
/// <summary>

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

@ -61,35 +61,35 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (alpha == 0.0)
{
Buffer.BlockCopy(y, 0, result, 0, y.Length * Constants.SizeOfDouble);
y.Copy(result);
}
else if (alpha == 1.0)
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + x[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + (alpha * x[index]);
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
}
}
@ -113,21 +113,21 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
else if (alpha == 1.0)
{
Buffer.BlockCopy(x, 0, result, 0, x.Length * Constants.SizeOfDouble);
x.Copy(result);
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = alpha * x[index];
}
}
else
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
}
}
@ -197,16 +197,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] + y[index];
}
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] + y[index];
}
}
}
@ -242,17 +242,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] - y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
}
/// <summary>
@ -287,17 +287,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] * y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
}
/// <summary>
@ -332,17 +332,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] / y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
}
/// <summary>
@ -950,7 +950,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
LUSolveFactored(order, a, order, ipiv, inverse);
Buffer.BlockCopy(inverse, 0, a, 0, a.Length * Constants.SizeOfDouble);
inverse.Copy(a);
}
/// <summary>
@ -1019,7 +1019,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var ipiv = new int[order];
var clone = new double[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length * Constants.SizeOfDouble);
a.Copy(clone);
LUFactor(clone, order, ipiv);
LUSolveFactored(columnsOfB, clone, order, ipiv, b);
}
@ -1242,7 +1242,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
var clone = new double[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length * Constants.SizeOfDouble);
a.Copy(clone);
CholeskyFactor(clone, orderA);
CholeskySolveFactored(clone, orderA, b, columnsB);
}
@ -1277,40 +1277,55 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
if( )
CommonParallel.For(
0,
columnsB,
c =>
if (Control.ParallelizeOperation(columnsB * 10))
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{
var cindex = c * orderA;
DoCholeskySolve(a, orderA, b, index);
}
}
}
// Solve L*Y = B;
double sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
/// <summary>
/// Solves A*X=B for X using a previously factored A matrix.
/// </summary>
/// <param name="a">The square, positive definite matrix A. Has to be different than <paramref name="b"/>.</param>
/// <param name="orderA">The number of rows and columns in A.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="index">The column to solve for.</param>
private static void DoCholeskySolve(double[] a, int orderA, double[] b, int index)
{
var cindex = index * orderA;
b[cindex + i] = sum / a[(i * orderA) + i];
}
// Solve L*Y = B;
double sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k] * b[cindex + k];
}
b[cindex + i] = sum / a[(i * orderA) + i];
}
b[cindex + i] = sum / a[iindex + i];
}
});
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k] * b[cindex + k];
}
b[cindex + i] = sum / a[iindex + i];
}
}
/// <summary>
@ -1642,7 +1657,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
var clone = new double[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length * Constants.SizeOfDouble);
a.Copy(clone);
var q = new double[rows * rows];
QRFactor(clone, rows, columns, q, work);
QRSolveFactored(q, clone, rows, columns, null, b, columnsB, x);

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

@ -61,35 +61,35 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (alpha == 0.0)
{
Buffer.BlockCopy(y, 0, result, 0, y.Length * Constants.SizeOfFloat);
y.Copy(result);
}
else if (alpha == 1.0)
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + x[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
}
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = y[index] + (alpha * x[index]);
}
}
else
{
CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
}
}
}
@ -113,21 +113,21 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
else if (alpha == 1.0)
{
Buffer.BlockCopy(x, 0, result, 0, x.Length * Constants.SizeOfFloat);
x.Copy(result);
}
else
{
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = alpha * x[index];
}
}
else
{
CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
}
}
}
@ -197,17 +197,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] + y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] + y[index]; });
}
}
/// <summary>
@ -242,17 +242,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] - y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] - y[index]; });
}
}
/// <summary>
@ -287,17 +287,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] * y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] * y[index]; });
}
}
/// <summary>
@ -332,17 +332,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (x.Length < Control.ParallelizeElements || Control.DisableParallelization)
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
else
{
for (var index = 0; index < x.Length; index++)
{
result[index] = x[index] / y[index];
}
}
else
{
CommonParallel.For(0, y.Length, index => { result[index] = x[index] / y[index]; });
}
}
/// <summary>
@ -951,7 +951,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
LUSolveFactored(order, a, order, ipiv, inverse);
Buffer.BlockCopy(inverse, 0, a, 0, a.Length * Constants.SizeOfFloat);
inverse.Copy(a);
}
/// <summary>
@ -1020,7 +1020,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var ipiv = new int[order];
var clone = new float[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length * Constants.SizeOfFloat);
a.Copy(clone);
LUFactor(clone, order, ipiv);
LUSolveFactored(columnsOfB, clone, order, ipiv, b);
}
@ -1243,7 +1243,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
var clone = new float[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length * Constants.SizeOfFloat);
a.Copy(clone);
CholeskyFactor(clone, orderA);
CholeskySolveFactored(clone, orderA, b, columnsB);
}
@ -1278,39 +1278,55 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
CommonParallel.For(
0,
columnsB,
c =>
if (Control.ParallelizeOperation(columnsB * 10))
{
CommonParallel.For(0, columnsB, c => DoCholeskySolve(a, orderA, b, c));
}
else
{
for (var index = 0; index < columnsB; index++)
{
var cindex = c * orderA;
DoCholeskySolve(a, orderA, b, index);
}
}
}
// Solve L*Y = B;
float sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
/// <summary>
/// Solves A*X=B for X using a previously factored A matrix.
/// </summary>
/// <param name="a">The square, positive definite matrix A. Has to be different than <paramref name="b"/>.</param>
/// <param name="orderA">The number of rows and columns in A.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="index">The column to solve for.</param>
private static void DoCholeskySolve(float[] a, int orderA, float[] b, int index)
{
var cindex = index * orderA;
b[cindex + i] = sum / a[(i * orderA) + i];
}
// Solve L*Y = B;
float sum;
for (var i = 0; i < orderA; i++)
{
sum = b[cindex + i];
for (var k = i - 1; k >= 0; k--)
{
sum -= a[(k * orderA) + i] * b[cindex + k];
}
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k] * b[cindex + k];
}
b[cindex + i] = sum / a[(i * orderA) + i];
}
b[cindex + i] = sum / a[iindex + i];
}
});
// Solve L'*X = Y;
for (var i = orderA - 1; i >= 0; i--)
{
sum = b[cindex + i];
var iindex = i * orderA;
for (var k = i + 1; k < orderA; k++)
{
sum -= a[iindex + k] * b[cindex + k];
}
b[cindex + i] = sum / a[iindex + i];
}
}
/// <summary>
@ -1642,7 +1658,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
var clone = new float[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length * Constants.SizeOfFloat);
a.Copy(clone);
var q = new float[rows * rows];
QRFactor(clone, rows, columns, q, work);
QRSolveFactored(q, clone, rows, columns, null, b, columnsB, x);

17
src/Numerics/Control.cs

@ -59,7 +59,7 @@ namespace MathNet.Numerics
/// <summary>
/// The default cutoff point for order size for the matrix multiply in linear algebra provider.
/// </summary>
private static int _parallelizeElements = 256;
private static int _parallelizeElements = 300;
/// <summary>
/// Initializes static members of the Control class.
@ -99,7 +99,8 @@ namespace MathNet.Numerics
/// <value>The linear algebra provider.</value>
public static ILinearAlgebraProvider LinearAlgebraProvider
{
get; set;
get;
set;
}
/// <summary>
@ -169,7 +170,7 @@ namespace MathNet.Numerics
/// <summary>
/// Gets or sets the number of elements a vector or matrix must contain before we multiply threads.
/// </summary>
/// <value>Number of elements. Default is 256.</value>
/// <value>Number of elements. Default is 300.</value>
public static int ParallelizeElements
{
get
@ -185,5 +186,15 @@ namespace MathNet.Numerics
}
}
}
/// <summary>
/// Given the number elements, should the operation be parallelized.
/// </summary>
/// <param name="elements">The number elements to check.</param>
/// <returns><c>true</c> if the operation should be parallelized; <c>false</c> otherwise.</returns>
public static bool ParallelizeOperation(int elements)
{
return elements < ParallelizeElements || DisableParallelization || NumberOfParallelWorkerThreads < 2;
}
}
}

Loading…
Cancel
Save