|
|
|
@ -428,6 +428,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra |
|
|
|
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.</remarks>
|
|
|
|
public virtual void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result) |
|
|
|
{ |
|
|
|
if (_variation == Variation.Experimental) |
|
|
|
{ |
|
|
|
MatrixMultiplyWithUpdateExperimental(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, rowsX, columnsX, y, rowsY, columnsY, 0.0, result); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// First check some basic requirement on the parameters of the matrix multiplication.
|
|
|
|
if (x == null) |
|
|
|
{ |
|
|
|
@ -508,6 +514,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra |
|
|
|
/// <param name="c">The c matrix.</param>
|
|
|
|
public virtual void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c) |
|
|
|
{ |
|
|
|
if (_variation == Variation.Experimental) |
|
|
|
{ |
|
|
|
MatrixMultiplyWithUpdateExperimental(transposeA, transposeB, alpha, a, rowsA, columnsA, b, rowsB, columnsB, beta, c); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int m; // The number of rows of matrix op(A) and of the matrix C.
|
|
|
|
int n; // The number of columns of matrix op(B) and of the matrix C.
|
|
|
|
int k; // The number of columns of matrix op(A) and the rows of the matrix op(B).
|
|
|
|
@ -777,6 +789,128 @@ namespace MathNet.Numerics.Providers.LinearAlgebra |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void MatrixMultiplyWithUpdateExperimental( |
|
|
|
Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, |
|
|
|
double[] b, |
|
|
|
int rowsB, int columnsB, double beta, double[] c) |
|
|
|
{ |
|
|
|
if (a == null) |
|
|
|
{ |
|
|
|
throw new ArgumentNullException("a"); |
|
|
|
} |
|
|
|
|
|
|
|
if (b == null) |
|
|
|
{ |
|
|
|
throw new ArgumentNullException("b"); |
|
|
|
} |
|
|
|
|
|
|
|
if (c == null) |
|
|
|
{ |
|
|
|
throw new ArgumentNullException("c"); |
|
|
|
} |
|
|
|
|
|
|
|
if (transposeA != Transpose.DontTranspose) |
|
|
|
{ |
|
|
|
var swap = rowsA; |
|
|
|
rowsA = columnsA; |
|
|
|
columnsA = swap; |
|
|
|
} |
|
|
|
|
|
|
|
if (transposeB != Transpose.DontTranspose) |
|
|
|
{ |
|
|
|
var swap = rowsB; |
|
|
|
rowsB = columnsB; |
|
|
|
columnsB = swap; |
|
|
|
} |
|
|
|
|
|
|
|
if (columnsA != rowsB) |
|
|
|
{ |
|
|
|
throw new ArgumentOutOfRangeException(string.Format("columnsA ({0}) != rowsB ({1})", columnsA, rowsB)); |
|
|
|
} |
|
|
|
|
|
|
|
if (rowsA * columnsA != a.Length) |
|
|
|
{ |
|
|
|
throw new ArgumentOutOfRangeException(string.Format("rowsA ({0}) * columnsA ({1}) != a.Length ({2})", rowsA, columnsA, a.Length)); |
|
|
|
} |
|
|
|
|
|
|
|
if (rowsB * columnsB != b.Length) |
|
|
|
{ |
|
|
|
throw new ArgumentOutOfRangeException(string.Format("rowsB ({0}) * columnsB ({1}) != b.Length ({2})", rowsB, columnsB, b.Length)); |
|
|
|
} |
|
|
|
|
|
|
|
if (rowsA * columnsB != c.Length) |
|
|
|
{ |
|
|
|
throw new ArgumentOutOfRangeException(string.Format("rowsA ({0}) * columnsB ({1}) != c.Length ({2})", rowsA, columnsB, c.Length)); |
|
|
|
} |
|
|
|
|
|
|
|
// handle degenerate cases
|
|
|
|
if (beta == 0.0) |
|
|
|
{ |
|
|
|
Array.Clear(c, 0, c.Length); |
|
|
|
} |
|
|
|
else if (beta != 1.0) |
|
|
|
{ |
|
|
|
ScaleArray(beta, c, c); |
|
|
|
} |
|
|
|
|
|
|
|
if (alpha == 0.0) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Extract column arrays
|
|
|
|
var columnDataB = new double[columnsB][]; |
|
|
|
for (int i = 0; i < columnDataB.Length; i++) |
|
|
|
{ |
|
|
|
var column = new double[rowsB]; |
|
|
|
GetColumn(transposeB, i, rowsB, columnsB, b, column); |
|
|
|
columnDataB[i] = column; |
|
|
|
} |
|
|
|
|
|
|
|
var shouldNotParallelize = rowsA + columnsB + columnsA < Control.ParallelizeOrder || Control.MaxDegreeOfParallelism < 2; |
|
|
|
if (shouldNotParallelize) |
|
|
|
{ |
|
|
|
var row = new double[columnsA]; |
|
|
|
for (int i = 0; i < rowsA; i++) |
|
|
|
{ |
|
|
|
GetRow(transposeA, i, rowsA, columnsA, a, row); |
|
|
|
for (int j = 0; j < columnsB; j++) |
|
|
|
{ |
|
|
|
var col = columnDataB[j]; |
|
|
|
double sum = 0; |
|
|
|
for (int ii = 0; ii < row.Length; ii++) |
|
|
|
{ |
|
|
|
sum += row[ii] * col[ii]; |
|
|
|
} |
|
|
|
|
|
|
|
c[j * rowsA + i] += alpha * sum; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
CommonParallel.For(0, rowsA, 1, (u, v) => |
|
|
|
{ |
|
|
|
var row = new double[columnsA]; |
|
|
|
for (int i = u; i < v; i++) |
|
|
|
{ |
|
|
|
GetRow(transposeA, i, rowsA, columnsA, a, row); |
|
|
|
for (int j = 0; j < columnsB; j++) |
|
|
|
{ |
|
|
|
var column = columnDataB[j]; |
|
|
|
double sum = 0; |
|
|
|
for (int ii = 0; ii < row.Length; ii++) |
|
|
|
{ |
|
|
|
sum += row[ii] * column[ii]; |
|
|
|
} |
|
|
|
|
|
|
|
c[j * rowsA + i] += alpha * sum; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Computes the LUP factorization of A. P*A = L*U.
|
|
|
|
/// </summary>
|
|
|
|
@ -1329,7 +1463,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
var work = columnsR > rowsR ? new double[rowsR * rowsR] : new double[rowsR * columnsR]; |
|
|
|
var work = columnsR > rowsR ? new double[rowsR * rowsR] : new double[rowsR * columnsR]; |
|
|
|
var minmn = Math.Min(rowsR, columnsR); |
|
|
|
for (var i = 0; i < minmn; i++) |
|
|
|
{ |
|
|
|
@ -1383,7 +1517,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra |
|
|
|
} |
|
|
|
|
|
|
|
var work = new double[rowsA*columnsA]; |
|
|
|
|
|
|
|
|
|
|
|
var minmn = Math.Min(rowsA, columnsA); |
|
|
|
for (var i = 0; i < minmn; i++) |
|
|
|
{ |
|
|
|
|