diff --git a/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs
index 04424c55..dd3e9a4e 100644
--- a/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs
+++ b/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs
@@ -267,17 +267,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(double[] x, int xRows, int xColumns, double[] y, int yRows, int yColumns, double[] result)
+ public void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, xRows, xColumns, y, yRows, yColumns, 0.0, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, rowsX, columnsX, y, rowsY, columnsY, 0.0, result);
}
///
@@ -287,15 +287,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a,
- int aRows, int aColumns, double[] b, int bRows, int bColumns, double beta, double[] c)
+ int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
{
if (a == null)
{
@@ -312,16 +312,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -477,13 +477,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
///
- public void CholeskySolve(double[] a, int aOrder, double[] b, int bRows, int bColumns)
+ public void CholeskySolve(double[] a, int orderA, double[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -492,12 +492,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(double[] a, int aOrder, double[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(double[] a, int orderA, double[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -507,12 +507,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(double[] r, int rRows, int rColumns, double[] q)
+ public void QRFactor(double[] r, int rowsR, int columnsR, double[] q)
{
throw new NotImplementedException();
}
@@ -522,15 +522,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(double[] r, int rRows, int rColumns, double[] q, double[] work)
+ public void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] work)
{
throw new NotImplementedException();
}
@@ -540,14 +540,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(double[] r, int rRows, int rColumns, double[] q, double[] b, int bColumns, double[] x)
+ public void QRSolve(double[] r, int rowsR, int columnsR, double[] q, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -557,17 +557,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(double[] r, int rRows, int rColumns, double[] q, double[] b, int bColumns, double[] x, double[] work)
+ public void QRSolve(double[] r, int rowsR, int columnsR, double[] q, double[] b, int columnsB, double[] x, double[] work)
{
throw new NotImplementedException();
}
@@ -577,12 +577,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(double[] q, double[] r, int rRows, int rColumns, double[] b, int bColumns, double[] x)
+ public void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -592,15 +592,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt)
+ public void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
throw new NotImplementedException();
}
@@ -610,8 +610,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -621,7 +621,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] work)
+ public void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
{
throw new NotImplementedException();
}
@@ -630,15 +630,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x)
+ public void SvdSolve(double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -647,18 +647,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x, double[] work)
+ public void SvdSolve(double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x, double[] work)
{
throw new NotImplementedException();
}
@@ -666,15 +666,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -904,17 +904,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(float[] x, int xRows, int xColumns, float[] y, int yRows, int yColumns, float[] result)
+ public void MatrixMultiply(float[] x, int rowsX, int columnsX, float[] y, int rowsY, int columnsY, float[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0f, x, xRows, xColumns, y, yRows, yColumns, 0.0f, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0f, x, rowsX, columnsX, y, rowsY, columnsY, 0.0f, result);
}
///
@@ -924,15 +924,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, float alpha, float[] a,
- int aRows, int aColumns, float[] b, int bRows, int bColumns, float beta, float[] c)
+ int rowsA, int columnsA, float[] b, int rowsB, int columnsB, float beta, float[] c)
{
if (a == null)
{
@@ -949,16 +949,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -1114,12 +1114,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(float[] a, int aOrder, float[] b, int bRows, int bColumns)
+ public void CholeskySolve(float[] a, int orderA, float[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1128,12 +1128,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(float[] a, int aOrder, float[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(float[] a, int orderA, float[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1143,12 +1143,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(float[] r, int rRows, int rColumns, float[] q)
+ public void QRFactor(float[] r, int rowsR, int columnsR, float[] q)
{
throw new NotImplementedException();
}
@@ -1158,15 +1158,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(float[] r, int rRows, int rColumns, float[] q, float[] work)
+ public void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] work)
{
throw new NotImplementedException();
}
@@ -1176,14 +1176,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(float[] r, int rRows, int rColumns, float[] q, float[] b, int bColumns, float[] x)
+ public void QRSolve(float[] r, int rowsR, int columnsR, float[] q, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1193,17 +1193,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(float[] r, int rRows, int rColumns, float[] q, float[] b, int bColumns, float[] x, float[] work)
+ public void QRSolve(float[] r, int rowsR, int columnsR, float[] q, float[] b, int columnsB, float[] x, float[] work)
{
throw new NotImplementedException();
}
@@ -1213,12 +1213,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(float[] q, float[] r, int rRows, int rColumns, float[] b, int bColumns, float[] x)
+ public void QRSolveFactored(float[] q, float[] r, int rowsR, int columnsR, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1228,15 +1228,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt)
+ public void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
throw new NotImplementedException();
}
@@ -1246,8 +1246,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -1257,7 +1257,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] work)
+ public void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
{
throw new NotImplementedException();
}
@@ -1266,15 +1266,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x)
+ public void SvdSolve(float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1283,18 +1283,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x, float[] work)
+ public void SvdSolve(float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x, float[] work)
{
throw new NotImplementedException();
}
@@ -1302,15 +1302,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1540,17 +1540,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(Complex[] x, int xRows, int xColumns, Complex[] y, int yRows, int yColumns, Complex[] result)
+ public void MatrixMultiply(Complex[] x, int rowsX, int columnsX, Complex[] y, int rowsY, int columnsY, Complex[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex.One, x, xRows, xColumns, y, yRows, yColumns, Complex.Zero, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex.One, x, rowsX, columnsX, y, rowsY, columnsY, Complex.Zero, result);
}
///
@@ -1560,15 +1560,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex alpha, Complex[] a,
- int aRows, int aColumns, Complex[] b, int bRows, int bColumns, Complex beta, Complex[] c)
+ int rowsA, int columnsA, Complex[] b, int rowsB, int columnsB, Complex beta, Complex[] c)
{
if (a == null)
{
@@ -1585,16 +1585,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -1750,12 +1750,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(Complex[] a, int aOrder, Complex[] b, int bRows, int bColumns)
+ public void CholeskySolve(Complex[] a, int orderA, Complex[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1764,12 +1764,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(Complex[] a, int aOrder, Complex[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(Complex[] a, int orderA, Complex[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1779,12 +1779,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex[] r, int rRows, int rColumns, Complex[] q)
+ public void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q)
{
throw new NotImplementedException();
}
@@ -1794,15 +1794,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] work)
+ public void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1812,14 +1812,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] b, int bColumns, Complex[] x)
+ public void QRSolve(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -1829,17 +1829,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] b, int bColumns, Complex[] x, Complex[] work)
+ public void QRSolve(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] b, int columnsB, Complex[] x, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1849,12 +1849,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(Complex[] q, Complex[] r, int rRows, int rColumns, Complex[] b, int bColumns, Complex[] x)
+ public void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -1864,15 +1864,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt)
+ public void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
throw new NotImplementedException();
}
@@ -1882,8 +1882,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -1893,7 +1893,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
+ public void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1902,15 +1902,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x)
+ public void SvdSolve(Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -1919,18 +1919,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x, Complex[] work)
+ public void SvdSolve(Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1938,15 +1938,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -2176,17 +2176,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(Complex32[] x, int xRows, int xColumns, Complex32[] y, int yRows, int yColumns, Complex32[] result)
+ public void MatrixMultiply(Complex32[] x, int rowsX, int columnsX, Complex32[] y, int rowsY, int columnsY, Complex32[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex32.One, x, xRows, xColumns, y, yRows, yColumns, Complex32.Zero, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex32.One, x, rowsX, columnsX, y, rowsY, columnsY, Complex32.Zero, result);
}
///
@@ -2196,15 +2196,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a,
- int aRows, int aColumns, Complex32[] b, int bRows, int bColumns, Complex32 beta, Complex32[] c)
+ int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c)
{
if (a == null)
{
@@ -2221,16 +2221,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -2386,12 +2386,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(Complex32[] a, int aOrder, Complex32[] b, int bRows, int bColumns)
+ public void CholeskySolve(Complex32[] a, int orderA, Complex32[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -2400,12 +2400,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(Complex32[] a, int aOrder, Complex32[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(Complex32[] a, int orderA, Complex32[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -2415,12 +2415,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex32[] r, int rRows, int rColumns, Complex32[] q)
+ public void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q)
{
throw new NotImplementedException();
}
@@ -2430,15 +2430,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] work)
+ public void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2448,14 +2448,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] b, int bColumns, Complex32[] x)
+ public void QRSolve(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -2465,17 +2465,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] b, int bColumns, Complex32[] x, Complex32[] work)
+ public void QRSolve(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2485,12 +2485,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(Complex32[] q, Complex32[] r, int rRows, int rColumns, Complex32[] b, int bColumns, Complex32[] x)
+ public void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -2500,15 +2500,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt)
+ public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
throw new NotImplementedException();
}
@@ -2518,8 +2518,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -2529,7 +2529,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
+ public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2538,15 +2538,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x)
+ public void SvdSolve(Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -2555,18 +2555,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x, Complex32[] work)
+ public void SvdSolve(Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2574,15 +2574,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
diff --git a/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProviderOfT.cs b/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProviderOfT.cs
index bf1a7532..e96d496e 100644
--- a/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProviderOfT.cs
+++ b/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProviderOfT.cs
@@ -185,15 +185,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- void MatrixMultiply(T[] x, int xRows, int xColumns, T[] y, int yRows, int yColumns, T[] result);
+ void MatrixMultiply(T[] x, int rowsX, int columnsX, T[] y, int rowsY, int columnsY, T[] result);
///
/// Multiplies two matrices and updates another with the result. c = alpha*op(a)*op(b) + beta*c
@@ -202,14 +202,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
- void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, T alpha, T[] a, int aRows, int aColumns, T[] b, int bRows, int bColumns, T beta, T[] c);
+ void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, T alpha, T[] a, int rowsA, int columnsA, T[] b, int rowsB, int columnsB, T beta, T[] c);
///
/// Computes the LUP factorization of A. P*A = L*U.
@@ -319,116 +319,116 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- void CholeskySolve(T[] a, int aOrder, T[] b, int bRows, int bColumns);
+ void CholeskySolve(T[] a, int orderA, T[] b, int rowsB, int columnsB);
///
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- void CholeskySolveFactored(T[] a, int aOrder, T[] b, int bRows, int bColumns);
+ void CholeskySolveFactored(T[] a, int orderA, T[] b, int rowsB, int columnsB);
///
/// Computes the QR factorization of A.
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- void QRFactor(T[] r, int rRows, int rColumns, T[] q);
+ void QRFactor(T[] r, int rowsR, int columnsR, T[] q);
///
/// Computes the QR factorization of A.
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- void QRFactor(T[] r, int rRows, int rColumns, T[] q, T[] work);
+ void QRFactor(T[] r, int rowsR, int columnsR, T[] q, T[] work);
///
/// Solves A*X=B for X using QR factorization of A.
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- void QRSolve(T[] r, int rRows, int rColumns, T[] q, T[] b, int bColumns, T[] x);
+ void QRSolve(T[] r, int rowsR, int columnsR, T[] q, T[] b, int columnsB, T[] x);
///
/// Solves A*X=B for X using QR factorization of A.
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- void QRSolve(T[] r, int rRows, int rColumns, T[] q, T[] b, int bColumns, T[] x, T[] work);
+ void QRSolve(T[] r, int rowsR, int columnsR, T[] q, T[] b, int columnsB, T[] x, T[] work);
///
/// Solves A*X=B for X using a previously QR factored matrix.
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- void QRSolveFactored(T[] q, T[] r, int rRows, int rColumns, T[] b, int bColumns, T[] x);
+ void QRSolveFactored(T[] q, T[] r, int rowsR, int columnsR, T[] b, int columnsB, T[] x);
///
/// Computes the singular value decomposition of A.
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- void SingularValueDecomposition(bool computeVectors, T[] a, int aRows, int aColumns, T[] s, T[] u, T[] vt);
+ void SingularValueDecomposition(bool computeVectors, T[] a, int rowsA, int columnsA, T[] s, T[] u, T[] vt);
///
/// Computes the singular value decomposition of A.
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -439,51 +439,51 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// On exit, work[0] contains the optimal work size value.
///
/// This is equivalent to the GESVD LAPACK routine.
- void SingularValueDecomposition(bool computeVectors, T[] a, int aRows, int aColumns, T[] s, T[] u, T[] vt, T[] work);
+ void SingularValueDecomposition(bool computeVectors, T[] a, int rowsA, int columnsA, T[] s, T[] u, T[] vt, T[] work);
///
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- void SvdSolve(T[] a, int aRows, int aColumns, T[] s, T[] u, T[] vt, T[] b, int bColumns, T[] x);
+ void SvdSolve(T[] a, int rowsA, int columnsA, T[] s, T[] u, T[] vt, T[] b, int columnsB, T[] x);
///
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
///
- void SvdSolve(T[] a, int aRows, int aColumns, T[] s, T[] u, T[] vt, T[] b, int bColumns, T[] x, T[] work);
+ void SvdSolve(T[] a, int rowsA, int columnsA, T[] s, T[] u, T[] vt, T[] b, int columnsB, T[] x, T[] work);
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- void SvdSolveFactored(int aRows, int aColumns, T[] s, T[] u, T[] vt, T[] b, int bColumns, T[] x);
+ void SvdSolveFactored(int rowsA, int columnsA, T[] s, T[] u, T[] vt, T[] b, int columnsB, T[] x);
}
}
diff --git a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs
index ac071b4d..43290034 100644
--- a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs
+++ b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs
@@ -26,7 +26,6 @@
namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
using System;
- using System.Linq;
using System.Numerics;
using Properties;
using Threading;
@@ -278,15 +277,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(double[] x, int xRows, int xColumns, double[] y, int yRows, int yColumns, double[] result)
+ public void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
{
// First check some basic requirement on the parameters of the matrix multiplication.
if (x == null)
@@ -304,22 +303,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("result");
}
- if (xRows * xColumns != x.Length)
+ if (rowsX * columnsX != x.Length)
{
throw new ArgumentException("x.Length != xRows * xColumns");
}
- if (yRows * yColumns != y.Length)
+ if (rowsY * columnsY != y.Length)
{
throw new ArgumentException("y.Length != yRows * yColumns");
}
- if (xColumns != yRows)
+ if (columnsX != rowsY)
{
throw new ArgumentException("xColumns != yRows");
}
- if (xRows * yColumns != result.Length)
+ if (rowsX * columnsY != result.Length)
{
throw new ArgumentException("xRows * yColumns != result.Length");
}
@@ -351,7 +350,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// TODO - For small matrices we should get rid of the parallelism because of startup costs.
// Perhaps the following implementations would be a good one
// http://blog.feradz.com/2009/01/cache-efficient-matrix-multiplication/
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, xdata, xRows, xColumns, ydata, yRows, yColumns, 0.0, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, xdata, rowsX, columnsX, ydata, rowsY, columnsY, 0.0, result);
}
///
@@ -361,18 +360,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
- public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int aRows, int aColumns, double[] b, int bRows, int bColumns, double beta, double[] c)
+ public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
{
// Choose nonsensical values for the number of rows in c; fill them in depending
// on the operations on a and b.
- int cRows;
+ int rowsC;
// First check some basic requirement on the parameters of the matrix multiplication.
if (a == null)
@@ -387,59 +386,59 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- if (aRows != bColumns)
+ if (rowsA != columnsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aColumns * bRows != c.Length)
+ if (columnsA * rowsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aColumns;
+ rowsC = columnsA;
}
else if ((int)transposeA > 111)
{
- if (aRows != bRows)
+ if (rowsA != rowsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aColumns * bColumns != c.Length)
+ if (columnsA * columnsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aColumns;
+ rowsC = columnsA;
}
else if ((int)transposeB > 111)
{
- if (aColumns != bColumns)
+ if (columnsA != columnsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aRows * bRows != c.Length)
+ if (rowsA * rowsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aRows;
+ rowsC = rowsA;
}
else
{
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aRows * bColumns != c.Length)
+ if (rowsA * columnsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aRows;
+ rowsC = rowsA;
}
if (alpha == 0.0 && beta == 0.0)
@@ -477,35 +476,39 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns,
- j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- double s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ double s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns,
+ CommonParallel.For(
+ 0,
+ columnsB,
j =>
{
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
{
- var iIndex = i * aRows;
+ var iIndex = i * rowsA;
double s = 0;
- for (var l = 0; l != aRows; l++)
+ for (var l = 0; l != rowsA; l++)
{
s += adata[iIndex + l] * bdata[jbIndex + l];
}
@@ -516,119 +519,131 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows,
- j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- double s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ double s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
- c[jIndex + i] = s;
- }
- });
+ c[jIndex + i] = s;
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns,
- j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- double s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ double s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = s;
- }
- });
+ c[jcIndex + i] = s;
+ }
+ });
}
}
else
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns,
- j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- double s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ double s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + s;
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns,
- j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- double s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ double s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows,
- j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- double s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ double s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
- c[jIndex + i] = s + c[jIndex + i] * beta;
- }
- });
+ c[jIndex + i] = s + (c[jIndex + i] * beta);
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns,
- j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- double s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ double s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
}
}
}
@@ -636,79 +651,87 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns,
- j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- double s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ double s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
- c[jIndex + i] = c[jIndex + i] * beta + alpha * s;
- }
- });
+ c[jIndex + i] = (c[jIndex + i] * beta) + (alpha * s);
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns,
- j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- double s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ double s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows,
- j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- double s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ double s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
- c[jIndex + i] = alpha * s + c[jIndex + i] * beta;
- }
- });
+ c[jIndex + i] = (alpha * s) + (c[jIndex + i] * beta);
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns,
- j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- double s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ double s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
}
}
}
@@ -750,7 +773,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
ipiv[i] = i;
}
- var vLUcolj = new double[order];
+ var vecLUcolj = new double[order];
// Outer loop.
for (var j = 0; j < order; j++)
@@ -761,7 +784,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Make a copy of the j-th column to localize references.
for (var i = 0; i < order; i++)
{
- vLUcolj[i] = data[indexj + i];
+ vecLUcolj[i] = data[indexj + i];
}
// Apply previous transformations.
@@ -772,17 +795,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var s = 0.0;
for (var k = 0; k < kmax; k++)
{
- s += data[k * order + i] * vLUcolj[k];
+ s += data[(k * order) + i] * vecLUcolj[k];
}
- data[indexj + i] = vLUcolj[i] -= s;
+ data[indexj + i] = vecLUcolj[i] -= s;
}
// Find pivot and exchange if necessary.
var p = j;
for (var i = j + 1; i < order; i++)
{
- if (Math.Abs(vLUcolj[i]) > Math.Abs(vLUcolj[p]))
+ if (Math.Abs(vecLUcolj[i]) > Math.Abs(vecLUcolj[p]))
{
p = i;
}
@@ -869,7 +892,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var inverse = new double[a.Length];
for (var i = 0; i < order; i++)
{
- inverse[i + order * i] = 1.0;
+ inverse[i + (order * i)] = 1.0;
}
LUSolveFactored(order, a, order, ipiv, inverse);
@@ -992,7 +1015,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var p = ipiv[i];
for (var j = 0; j < columnsOfB; j++)
{
- var indexk = j*order;
+ var indexk = j * order;
var indexkp = indexk + p;
var indexkj = indexk + i;
var temp = b[indexkp];
@@ -1018,10 +1041,10 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Solve U*X = Y;
for (var k = order - 1; k >= 0; k--)
{
- var korder = k + k * order;
+ var korder = k + (k * order);
for (var j = 0; j < columnsOfB; j++)
{
- b[k + j * order] /= a[korder];
+ b[k + (j * order)] /= a[korder];
}
korder = k * order;
@@ -1124,6 +1147,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
aT[(j * order) + i] = a[(i * order) + j];
}
}
+
LUSolveFactored(columnsOfB, aT, order, ipiv, b);
}
else
@@ -1156,7 +1180,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
int i;
for (i = 0; i < k; i++)
{
- s += a[i * order + k] * a[i * order + j];
+ s += a[(i * order) + k] * a[(i * order) + j];
}
var tmp = k * order;
@@ -1165,7 +1189,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
d += s * s;
}
- index = j * order + j;
+ index = (j * order) + j;
d = a[index] - d;
if (d <= 0.0)
{
@@ -1175,7 +1199,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
a[index] = Math.Sqrt(d);
for (var k = j + 1; k < order; k++)
{
- a[k * order + j] = 0.0;
+ a[(k * order) + j] = 0.0;
}
}
}
@@ -1184,12 +1208,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(double[] a, int aOrder, double[] b, int bRows, int bColumns)
+ public void CholeskySolve(double[] a, int orderA, double[] b, int rowsB, int columnsB)
{
if (a == null)
{
@@ -1201,7 +1225,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("b");
}
- if (aOrder != bRows)
+ if (orderA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -1211,20 +1235,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
- CholeskyFactor(a, aOrder);
- CholeskySolveFactored(a, aOrder, b, bRows, bColumns);
+ CholeskyFactor(a, orderA);
+ CholeskySolveFactored(a, orderA, b, rowsB, columnsB);
}
///
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A. Has to be different than .
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix. Has to be different than .
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(double[] a, int aOrder, double[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(double[] a, int orderA, double[] b, int rowsB, int columnsB)
{
if (a == null)
{
@@ -1236,7 +1260,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("b");
}
- if (aOrder != bRows)
+ if (orderA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -1246,36 +1270,39 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
- CommonParallel.For(0, bColumns, c =>
- {
- var cindex = c * aOrder;
+ CommonParallel.For(
+ 0,
+ columnsB,
+ c =>
+ {
+ var cindex = c * orderA;
- // Solve L*Y = B;
- double sum;
- for (var i = 0; i < aOrder; i++)
- {
- sum = b[cindex + i];
- for (var k = i - 1; k >= 0; k--)
- {
- sum -= a[k * aOrder + i] * b[cindex + k];
- }
+ // 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];
+ }
- b[cindex + i] = sum / a[i * aOrder + i];
- }
+ b[cindex + i] = sum / a[(i * orderA) + i];
+ }
- // Solve L'*X = Y;
- for (var i = aOrder - 1; i >= 0; i--)
- {
- sum = b[cindex + i];
- var iindex = i * aOrder;
- for (var k = i + 1; k < aOrder; k++)
- {
- sum -= a[iindex + k] * 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[iindex + i];
- }
- });
+ b[cindex + i] = sum / a[iindex + i];
+ }
+ });
}
///
@@ -1283,12 +1310,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(double[] r, int rRows, int rColumns, double[] q)
+ public void QRFactor(double[] r, int rowsR, int columnsR, double[] q)
{
if (r == null)
{
@@ -1300,18 +1327,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- var work = new double[rRows * rRows];
- QRFactor(r, rRows, rColumns, q, work);
+ var work = new double[rowsR * rowsR];
+ QRFactor(r, rowsR, columnsR, q, work);
}
///
@@ -1319,15 +1346,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(double[] r, int rRows, int rColumns, double[] q, double[] work)
+ public void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] work)
{
if (r == null)
{
@@ -1344,37 +1371,37 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (work.Length < rRows * rRows)
+ if (work.Length < rowsR * rowsR)
{
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
- CommonParallel.For(0, rRows, i => q[(i * rRows) + i] = 1.0);
+ CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = 1.0);
- var minmn = Math.Min(rRows, rColumns);
+ var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++)
{
- GenerateColumn(work, r, rRows, i, rRows - 1, i);
- ComputeQR(work, i, r, rRows, i, rRows - 1, i + 1, rColumns - 1);
+ GenerateColumn(work, r, rowsR, i, rowsR - 1, i);
+ ComputeQR(work, i, r, rowsR, i, rowsR - 1, i + 1, columnsR - 1);
}
for (var i = minmn - 1; i >= 0; i--)
{
- ComputeQR(work, i, q, rRows, i, rRows - 1, i, rRows - 1);
+ ComputeQR(work, i, q, rowsR, i, rowsR - 1, i, rowsR - 1);
}
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
}
#region QR Factor Helper functions
@@ -1442,8 +1469,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var norm = 0.0;
for (var i = 0; i < rowEnd - rowStart + 1; ++i)
{
- var iIndex = tmp + i;
- norm += work[iIndex] * work[iIndex];
+ var iindex = tmp + i;
+ norm += work[iindex] * work[iindex];
}
norm = Math.Sqrt(norm);
@@ -1475,14 +1502,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(double[] r, int rRows, int rColumns, double[] q, double[] b, int bColumns, double[] x)
+ public void QRSolve(double[] r, int rowsR, int columnsR, double[] q, double[] b, int columnsB, double[] x)
{
if (r == null)
{
@@ -1504,28 +1531,28 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (b.Length != rRows * bColumns)
+ if (b.Length != rowsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != rColumns * bColumns)
+ if (x.Length != columnsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
- var work = new double[rRows * rRows];
- QRSolve(r, rRows, rColumns, q, b, bColumns, x, work);
+ var work = new double[rowsR * rowsR];
+ QRSolve(r, rowsR, columnsR, q, b, columnsB, x, work);
}
///
@@ -1533,17 +1560,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(double[] r, int rRows, int rColumns, double[] q, double[] b, int bColumns, double[] x, double[] work)
+ public void QRSolve(double[] r, int rowsR, int columnsR, double[] q, double[] b, int columnsB, double[] x, double[] work)
{
if (r == null)
{
@@ -1565,36 +1592,36 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (b.Length != rRows * bColumns)
+ if (b.Length != rowsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != rColumns * bColumns)
+ if (x.Length != columnsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
- if (work.Length < rRows * rRows)
+ if (work.Length < rowsR * rowsR)
{
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
- QRFactor(r, rRows, rColumns, q, work);
- QRSolveFactored(q, r, rRows, rColumns, b, bColumns, x);
+ QRFactor(r, rowsR, columnsR, q, work);
+ QRSolveFactored(q, r, rowsR, columnsR, b, columnsB, x);
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
}
///
@@ -1602,12 +1629,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(double[] q, double[] r, int rRows, int rColumns, double[] b, int bColumns, double[] x)
+ public void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] b, int columnsB, double[] x)
{
if (r == null)
{
@@ -1629,22 +1656,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (b.Length != rRows * bColumns)
+ if (b.Length != rowsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != rColumns * bColumns)
+ if (x.Length != columnsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
@@ -1655,35 +1682,35 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
Buffer.BlockCopy(b, 0, sol, 0, b.Length * Constants.SizeOfDouble);
// Compute Y = transpose(Q)*B
- var column = new double[rRows];
- for (var j = 0; j < bColumns; j++)
+ var column = new double[rowsR];
+ for (var j = 0; j < columnsB; j++)
{
- var jm = j * rRows;
- CommonParallel.For(0, rRows, k => column[k] = sol[jm + k]);
+ var jm = j * rowsR;
+ CommonParallel.For(0, rowsR, k => column[k] = sol[jm + k]);
CommonParallel.For(
0,
- rRows,
+ rowsR,
i =>
{
- var im = i * rRows;
- sol[jm + i] = CommonParallel.Aggregate(0, rRows, k => q[im + k] * column[k]);
+ var im = i * rowsR;
+ sol[jm + i] = CommonParallel.Aggregate(0, rowsR, k => q[im + k] * column[k]);
});
}
// Solve R*X = Y;
- for (var k = rColumns - 1; k >= 0; k--)
+ for (var k = columnsR - 1; k >= 0; k--)
{
- var km = k * rRows;
- for (var j = 0; j < bColumns; j++)
+ var km = k * rowsR;
+ for (var j = 0; j < columnsB; j++)
{
- sol[(j * rRows) + k] /= r[km + k];
+ sol[(j * rowsR) + k] /= r[km + k];
}
for (var i = 0; i < k; i++)
{
- for (var j = 0; j < bColumns; j++)
+ for (var j = 0; j < columnsB; j++)
{
- var jm = j * rRows;
+ var jm = j * rowsR;
sol[jm + i] -= sol[jm + k] * r[km + i];
}
}
@@ -1692,12 +1719,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Fill result matrix
CommonParallel.For(
0,
- rColumns,
+ columnsR,
row =>
{
- for (var col = 0; col < bColumns; col++)
+ for (var col = 0; col < columnsB; col++)
{
- x[(col * rColumns) + row] = sol[row + (col * rRows)];
+ x[(col * columnsR) + row] = sol[row + (col * rowsR)];
}
});
}
@@ -1707,15 +1734,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt)
+ public void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
@@ -1737,24 +1764,24 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("vt");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
// TODO: Actually "work = new double[aRows]" is acceptable size of work array. I set size proposed in method description
- var work = new double[Math.Max((3 * Math.Min(aRows, aColumns)) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns))];
- SingularValueDecomposition(computeVectors, a, aRows, aColumns, s, u, vt, work);
+ var work = new double[Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA))];
+ SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
///
@@ -1762,8 +1789,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -1773,7 +1800,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] work)
+ public void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
{
if (a == null)
{
@@ -1800,17 +1827,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("work");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
@@ -1820,17 +1847,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
- if (work.Length < aRows)
+ if (work.Length < rowsA)
{
- work[0] = aRows;
+ work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
const int Maxiter = 1000;
- var e = new double[aColumns];
+ var e = new double[columnsA];
var v = new double[vt.Length];
- var stemp = new double[Math.Min(aRows + 1, aColumns)];
+ var stemp = new double[Math.Min(rowsA + 1, columnsA)];
int i, j, l, lp1;
@@ -1838,12 +1865,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var sn = 0.0;
double t;
- var ncu = aRows;
+ var ncu = rowsA;
// Reduce matrix to bidiagonal form, storing the diagonal elements
// in "s" and the super-diagonal elements in "e".
- var nct = Math.Min(aRows - 1, aColumns);
- var nrt = Math.Max(0, Math.Min(aColumns - 2, aRows));
+ var nct = Math.Min(rowsA - 1, columnsA);
+ var nrt = Math.Max(0, Math.Min(columnsA - 2, rowsA));
var lu = Math.Max(nct, nrt);
for (l = 0; l < lu; l++)
@@ -1854,28 +1881,28 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Compute the transformation for the l-th column and
// place the l-th diagonal in vector s[l].
var l1 = l;
- stemp[l] = Math.Sqrt(CommonParallel.Aggregate(l, aRows, i1 => (a[(l1 * aRows) + i1] * a[(l1 * aRows) + i1])));
+ stemp[l] = Math.Sqrt(CommonParallel.Aggregate(l, rowsA, i1 => (a[(l1 * rowsA) + i1] * a[(l1 * rowsA) + i1])));
if (stemp[l] != 0.0)
{
- if (a[(l * aRows) + l] != 0.0)
+ if (a[(l * rowsA) + l] != 0.0)
{
- stemp[l] = Math.Abs(stemp[l]) * (a[(l * aRows) + l] / Math.Abs(a[(l * aRows) + l]));
+ stemp[l] = Math.Abs(stemp[l]) * (a[(l * rowsA) + l] / Math.Abs(a[(l * rowsA) + l]));
}
// A part of column "l" of Matrix A from row "l" to end multiply by 1.0 / s[l]
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- a[(l * aRows) + i] = a[(l * aRows) + i] * (1.0 / stemp[l]);
+ a[(l * rowsA) + i] = a[(l * rowsA) + i] * (1.0 / stemp[l]);
}
- a[(l * aRows) + l] = 1.0 + a[(l * aRows) + l];
+ a[(l * rowsA) + l] = 1.0 + a[(l * rowsA) + l];
}
stemp[l] = -stemp[l];
}
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
if (l < nct)
{
@@ -1883,31 +1910,31 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
// Apply the transformation.
t = 0.0;
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- t += a[(j * aRows) + i] * a[(l * aRows) + i];
+ t += a[(j * rowsA) + i] * a[(l * rowsA) + i];
}
- t = -t / a[(l * aRows) + l];
+ t = -t / a[(l * rowsA) + l];
- for (var ii = l; ii < aRows; ii++)
+ for (var ii = l; ii < rowsA; ii++)
{
- a[(j * aRows) + ii] += t * a[(l * aRows) + ii];
+ a[(j * rowsA) + ii] += t * a[(l * rowsA) + ii];
}
}
}
// Place the l-th row of matrix into "e" for the
// subsequent calculation of the row transformation.
- e[j] = a[(j * aRows) + l];
+ e[j] = a[(j * rowsA) + l];
}
if (computeVectors && l < nct)
{
// Place the transformation in "u" for subsequent back multiplication.
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- u[(l * aRows) + i] = a[(l * aRows) + i];
+ u[(l * rowsA) + i] = a[(l * rowsA) + i];
}
}
@@ -1942,28 +1969,28 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
e[l] = -e[l];
- if (lp1 < aRows && e[l] != 0.0)
+ if (lp1 < rowsA && e[l] != 0.0)
{
// Apply the transformation.
- for (i = lp1; i < aRows; i++)
+ for (i = lp1; i < rowsA; i++)
{
work[i] = 0.0;
}
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
- for (var ii = lp1; ii < aRows; ii++)
+ for (var ii = lp1; ii < rowsA; ii++)
{
- work[ii] += e[j] * a[(j * aRows) + ii];
+ work[ii] += e[j] * a[(j * rowsA) + ii];
}
}
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
var ww = -e[j] / e[lp1];
- for (var ii = lp1; ii < aRows; ii++)
+ for (var ii = lp1; ii < rowsA; ii++)
{
- a[(j * aRows) + ii] += ww * work[ii];
+ a[(j * rowsA) + ii] += ww * work[ii];
}
}
}
@@ -1974,29 +2001,29 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
// Place the transformation in v for subsequent back multiplication.
- for (i = lp1; i < aColumns; i++)
+ for (i = lp1; i < columnsA; i++)
{
- v[(l * aColumns) + i] = e[i];
+ v[(l * columnsA) + i] = e[i];
}
}
// Set up the final bidiagonal matrix or order m.
- var m = Math.Min(aColumns, aRows + 1);
+ var m = Math.Min(columnsA, rowsA + 1);
var nctp1 = nct + 1;
var nrtp1 = nrt + 1;
- if (nct < aColumns)
+ if (nct < columnsA)
{
- stemp[nctp1 - 1] = a[((nctp1 - 1) * aRows) + (nctp1 - 1)];
+ stemp[nctp1 - 1] = a[((nctp1 - 1) * rowsA) + (nctp1 - 1)];
}
- if (aRows < m)
+ if (rowsA < m)
{
stemp[m - 1] = 0.0;
}
if (nrtp1 < m)
{
- e[nrtp1 - 1] = a[((m - 1) * aRows) + (nrtp1 - 1)];
+ e[nrtp1 - 1] = a[((m - 1) * rowsA) + (nrtp1 - 1)];
}
e[m - 1] = 0.0;
@@ -2006,12 +2033,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
for (j = nctp1 - 1; j < ncu; j++)
{
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- u[(j * aRows) + i] = 0.0;
+ u[(j * rowsA) + i] = 0.0;
}
- u[(j * aRows) + j] = 1.0;
+ u[(j * rowsA) + j] = 1.0;
}
for (l = nct - 1; l >= 0; l--)
@@ -2021,39 +2048,39 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
for (j = l + 1; j < ncu; j++)
{
t = 0.0;
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- t += u[(j * aRows) + i] * u[(l * aRows) + i];
+ t += u[(j * rowsA) + i] * u[(l * rowsA) + i];
}
- t = -t / u[(l * aRows) + l];
+ t = -t / u[(l * rowsA) + l];
- for (var ii = l; ii < aRows; ii++)
+ for (var ii = l; ii < rowsA; ii++)
{
- u[(j * aRows) + ii] += t * u[(l * aRows) + ii];
+ u[(j * rowsA) + ii] += t * u[(l * rowsA) + ii];
}
}
// A part of column "l" of matrix A from row "l" to end multiply by -1.0
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- u[(l * aRows) + i] = u[(l * aRows) + i] * -1.0;
+ u[(l * rowsA) + i] = u[(l * rowsA) + i] * -1.0;
}
- u[(l * aRows) + l] = 1.0 + u[(l * aRows) + l];
+ u[(l * rowsA) + l] = 1.0 + u[(l * rowsA) + l];
for (i = 0; i < l; i++)
{
- u[(l * aRows) + i] = 0.0;
+ u[(l * rowsA) + i] = 0.0;
}
}
else
{
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- u[(l * aRows) + i] = 0.0;
+ u[(l * rowsA) + i] = 0.0;
}
- u[(l * aRows) + l] = 1.0;
+ u[(l * rowsA) + l] = 1.0;
}
}
}
@@ -2061,36 +2088,36 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// If it is required, generate v.
if (computeVectors)
{
- for (l = aColumns - 1; l >= 0; l--)
+ for (l = columnsA - 1; l >= 0; l--)
{
lp1 = l + 1;
if (l < nrt)
{
if (e[l] != 0.0)
{
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
t = 0.0;
- for (i = lp1; i < aColumns; i++)
+ for (i = lp1; i < columnsA; i++)
{
- t += v[(j * aColumns) + i] * v[(l * aColumns) + i];
+ t += v[(j * columnsA) + i] * v[(l * columnsA) + i];
}
- t = -t / v[(l * aColumns) + lp1];
- for (var ii = l; ii < aColumns; ii++)
+ t = -t / v[(l * columnsA) + lp1];
+ for (var ii = l; ii < columnsA; ii++)
{
- v[(j * aColumns) + ii] += t * v[(l * aColumns) + ii];
+ v[(j * columnsA) + ii] += t * v[(l * columnsA) + ii];
}
}
}
}
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- v[(l * aColumns) + i] = 0.0;
+ v[(l * columnsA) + i] = 0.0;
}
- v[(l * aColumns) + l] = 1.0;
+ v[(l * columnsA) + l] = 1.0;
}
}
@@ -2111,9 +2138,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// A part of column "i" of matrix U from row 0 to end multiply by r
- for (j = 0; j < aRows; j++)
+ for (j = 0; j < rowsA; j++)
{
- u[(i * aRows) + j] = u[(i * aRows) + j] * r;
+ u[(i * rowsA) + j] = u[(i * rowsA) + j] * r;
}
}
}
@@ -2139,9 +2166,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
// A part of column "i+1" of matrix VT from row 0 to end multiply by r
- for (j = 0; j < aColumns; j++)
+ for (j = 0; j < columnsA; j++)
{
- v[((i + 1) * aColumns) + j] = v[((i + 1) * aColumns) + j] * r;
+ v[((i + 1) * columnsA) + j] = v[((i + 1) * columnsA) + j] * r;
}
}
@@ -2249,11 +2276,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// Rotate
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- var z = (cs * v[(k * aColumns) + i]) + (sn * v[((m - 1) * aColumns) + i]);
- v[((m - 1) * aColumns) + i] = (cs * v[((m - 1) * aColumns) + i]) - (sn * v[(k * aColumns) + i]);
- v[(k * aColumns) + i] = z;
+ var z = (cs * v[(k * columnsA) + i]) + (sn * v[((m - 1) * columnsA) + i]);
+ v[((m - 1) * columnsA) + i] = (cs * v[((m - 1) * columnsA) + i]) - (sn * v[(k * columnsA) + i]);
+ v[(k * columnsA) + i] = z;
}
}
}
@@ -2274,11 +2301,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// Rotate
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- var z = (cs * u[(k * aRows) + i]) + (sn * u[((l - 1) * aRows) + i]);
- u[((l - 1) * aRows) + i] = (cs * u[((l - 1) * aRows) + i]) - (sn * u[(k * aRows) + i]);
- u[(k * aRows) + i] = z;
+ var z = (cs * u[(k * rowsA) + i]) + (sn * u[((l - 1) * rowsA) + i]);
+ u[((l - 1) * rowsA) + i] = (cs * u[((l - 1) * rowsA) + i]) - (sn * u[(k * rowsA) + i]);
+ u[(k * rowsA) + i] = z;
}
}
}
@@ -2332,11 +2359,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
stemp[k + 1] = cs * stemp[k + 1];
if (computeVectors)
{
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- var z = (cs * v[(k * aColumns) + i]) + (sn * v[((k + 1) * aColumns) + i]);
- v[((k + 1) * aColumns) + i] = (cs * v[((k + 1) * aColumns) + i]) - (sn * v[(k * aColumns) + i]);
- v[(k * aColumns) + i] = z;
+ var z = (cs * v[(k * columnsA) + i]) + (sn * v[((k + 1) * columnsA) + i]);
+ v[((k + 1) * columnsA) + i] = (cs * v[((k + 1) * columnsA) + i]) - (sn * v[(k * columnsA) + i]);
+ v[(k * columnsA) + i] = z;
}
}
@@ -2346,13 +2373,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
stemp[k + 1] = -(sn * e[k]) + (cs * stemp[k + 1]);
g = sn * e[k + 1];
e[k + 1] = cs * e[k + 1];
- if (computeVectors && k < aRows)
+ if (computeVectors && k < rowsA)
{
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- var z = (cs * u[(k * aRows) + i]) + (sn * u[((k + 1) * aRows) + i]);
- u[((k + 1) * aRows) + i] = (cs * u[((k + 1) * aRows) + i]) - (sn * u[(k * aRows) + i]);
- u[(k * aRows) + i] = z;
+ var z = (cs * u[(k * rowsA) + i]) + (sn * u[((k + 1) * rowsA) + i]);
+ u[((k + 1) * rowsA) + i] = (cs * u[((k + 1) * rowsA) + i]) - (sn * u[(k * rowsA) + i]);
+ u[(k * rowsA) + i] = z;
}
}
}
@@ -2371,9 +2398,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// A part of column "l" of matrix VT from row 0 to end multiply by -1
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- v[(l * aColumns) + i] = v[(l * aColumns) + i] * -1.0;
+ v[(l * columnsA) + i] = v[(l * columnsA) + i] * -1.0;
}
}
}
@@ -2389,25 +2416,25 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
t = stemp[l];
stemp[l] = stemp[l + 1];
stemp[l + 1] = t;
- if (computeVectors && l < aColumns)
+ if (computeVectors && l < columnsA)
{
// Swap columns l, l + 1
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- var z = v[(l * aColumns) + i];
- v[(l * aColumns) + i] = v[((l + 1) * aColumns) + i];
- v[((l + 1) * aColumns) + i] = z;
+ var z = v[(l * columnsA) + i];
+ v[(l * columnsA) + i] = v[((l + 1) * columnsA) + i];
+ v[((l + 1) * columnsA) + i] = z;
}
}
- if (computeVectors && l < aRows)
+ if (computeVectors && l < rowsA)
{
// Swap columns l, l + 1
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- var z = u[(l * aRows) + i];
- u[(l * aRows) + i] = u[((l + 1) * aRows) + i];
- u[((l + 1) * aRows) + i] = z;
+ var z = u[(l * rowsA) + i];
+ u[(l * rowsA) + i] = u[((l + 1) * rowsA) + i];
+ u[((l + 1) * rowsA) + i] = z;
}
}
@@ -2423,11 +2450,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// Finally transpose "v" to get "vt" matrix
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- for (j = 0; j < aColumns; j++)
+ for (j = 0; j < columnsA; j++)
{
- vt[(j * aColumns) + i] = v[(i * aColumns) + j];
+ vt[(j * columnsA) + i] = v[(i * columnsA) + j];
}
}
}
@@ -2435,30 +2462,83 @@ 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
// 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.
- Buffer.BlockCopy(stemp, 0, s, 0, Math.Min(aRows, aColumns) * Constants.SizeOfDouble);
+ Buffer.BlockCopy(stemp, 0, s, 0, Math.Min(rowsA, columnsA) * Constants.SizeOfDouble);
// 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] = aRows;
+ work[0] = rowsA;
}
///
- /// Computes the singular value decomposition of A using CommonParallel where possible.
+ /// Given the Cartesian coordinates (da, db) of a point p, these fucntion return the parameters da, db, c, and s
+ /// associated with the Givens rotation that zeros the y-coordinate of the point.
+ ///
+ /// Provides the x-coordinate of the point p. On exit contains the parameter r associated with the Givens rotation
+ /// Provides the y-coordinate of the point p. On exit contains the parameter z associated with the Givens rotation
+ /// Contains the parameter c associated with the Givens rotation
+ /// Contains the parameter s associated with the Givens rotation
+ /// This is equivalent to the DROTG LAPACK routine.
+ private static void Drotg(ref double da, ref double db, ref double c, ref double s)
+ {
+ double r, z;
+
+ var roe = db;
+ var absda = Math.Abs(da);
+ var absdb = Math.Abs(db);
+ if (absda > absdb)
+ {
+ roe = da;
+ }
+
+ var scale = absda + absdb;
+ if (scale == 0.0)
+ {
+ c = 1.0;
+ s = 0.0;
+ r = 0.0;
+ z = 0.0;
+ }
+ else
+ {
+ var sda = da / scale;
+ var sdb = db / scale;
+ r = scale * Math.Sqrt((sda * sda) + (sdb * sdb));
+ if (roe < 0.0)
+ {
+ r = -r;
+ }
+
+ c = da / r;
+ s = db / r;
+ z = 1.0;
+ if (absda > absdb)
+ {
+ z = s;
+ }
+
+ if (absdb >= absda && c != 0.0)
+ {
+ z = 1.0 / c;
+ }
+ }
+
+ da = r;
+ db = z;
+ }
+
+ ///
+ /// Solves A*X=B for X using the singular value decomposition of A.
///
- /// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
- /// If is true, on exit U contains the left
- /// singular vectors.
- /// If is true, on exit VT contains the transposed
- /// right singular vectors.
- /// The work array. For real matrices, the work array should be at least
- /// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
- /// On exit, work[0] contains the optimal work size value.
- /// THIS METHOD IS NOT USED. ONLY FOR BENCHMARK PURPOSES.
- public void SingularValueDecompositionWithCommonParallel(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] work)
+ /// On exit U contains the left singular vectors.
+ /// On exit VT contains the transposed right singular vectors.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ public void SvdSolve(double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x)
{
if (a == null)
{
@@ -2480,687 +2560,1932 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("vt");
}
- if (u.Length != aRows * aRows)
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (work == null)
+ if (b.Length != rowsA * columnsB)
{
- throw new ArgumentNullException("work");
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (work.Length == 0)
+ if (x.Length != columnsA * columnsB)
{
- throw new ArgumentException(Resources.ArgumentSingleDimensionArray);
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (work.Length < aRows)
+ // TODO: Actually "work = new double[aRows]" is acceptable size of work array. I set size proposed in method description
+ var work = new double[Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA))];
+ SvdSolve(a, rowsA, columnsA, s, u, vt, b, columnsB, x, work);
+ }
+
+ ///
+ /// Solves A*X=B for X using the singular value decomposition of A.
+ ///
+ /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// The singular values of A in ascending value.
+ /// On exit U contains the left singular vectors.
+ /// On exit VT contains the transposed right singular vectors.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ /// The work array. For real matrices, the work array should be at least
+ /// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
+ /// On exit, work[0] contains the optimal work size value.
+ public void SvdSolve(double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x, double[] work)
+ {
+ if (a == null)
{
- work[0] = aRows;
- throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
+ throw new ArgumentNullException("a");
}
- const int Maxiter = 1000;
-
- var e = new double[aColumns];
- var v = new double[vt.Length];
- var stemp = new double[Math.Min(aRows + 1, aColumns)];
+ if (s == null)
+ {
+ throw new ArgumentNullException("s");
+ }
- int i, j, l, lp1;
+ if (u == null)
+ {
+ throw new ArgumentNullException("u");
+ }
- var cs = 0.0;
- var sn = 0.0;
- double t;
+ if (vt == null)
+ {
+ throw new ArgumentNullException("vt");
+ }
- var ncu = aRows;
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
- // Reduce matrix to bidiagonal form, storing the diagonal elements
- // in "s" and the super-diagonal elements in "e".
- var nct = Math.Min(aRows - 1, aColumns);
- var nrt = Math.Max(0, Math.Min(aColumns - 2, aRows));
- var lu = Math.Max(nct, nrt);
-
- for (l = 0; l < lu; l++)
+ if (x == null)
{
- lp1 = l + 1;
- var lCopy = l;
- if (l < nct)
- {
- // Compute the transformation for the l-th column and
- // place the l-th diagonal in vector s[l].
- stemp[l] = Math.Sqrt(CommonParallel.Aggregate(lCopy, aRows, row => (a[(lCopy * aRows) + row] * a[(lCopy * aRows) + row])));
-
- if (stemp[l] != 0.0)
- {
- if (a[(l * aRows) + l] != 0.0)
- {
- stemp[l] = Math.Abs(stemp[l]) * (a[(l * aRows) + l] / Math.Abs(a[(l * aRows) + l]));
- }
-
- // A part of column "l" of Matrix A from row "l" to end multiply by 1.0 / s[l]
- for (i = l; i < aRows; i++)
- {
- a[(l * aRows) + i] = a[(l * aRows) + i] * (1.0 / stemp[l]);
- }
+ throw new ArgumentNullException("x");
+ }
- a[(l * aRows) + l] = 1.0 + a[(l * aRows) + l];
- }
+ if (u.Length != rowsA * rowsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
+ }
- stemp[l] = -stemp[l];
- }
+ if (vt.Length != columnsA * columnsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
+ }
- for (j = lp1; j < aColumns; j++)
- {
- var jcopy = j;
+ if (s.Length != Math.Min(rowsA, columnsA))
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
+ }
- if (l < nct)
- {
- if (stemp[l] != 0.0)
- {
- // Apply the transformation.
- t = CommonParallel.Aggregate(lCopy, aRows, row => a[(jcopy * aRows) + row] * a[(lCopy * aRows) + row]);
- t = -t / a[(l * aRows) + l];
- for (var ii = l; ii < aRows; ii++)
- {
- a[(j * aRows) + ii] += t * a[(l * aRows) + ii];
- }
- }
- }
+ if (b.Length != rowsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
- // Place the l-th row of matrix into "e" for the
- // subsequent calculation of the row transformation.
- e[j] = a[(j * aRows) + l];
- }
+ if (x.Length != columnsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
- if (computeVectors && l < nct)
- {
- // Place the transformation in "u" for subsequent back multiplication.
- CommonParallel.For(lCopy, aRows, row => u[(lCopy * aRows) + row] = a[(lCopy * aRows) + row]);
- }
+ if (work.Length == 0)
+ {
+ throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
+ }
- if (l >= nrt)
- {
- continue;
- }
+ if (work.Length < rowsA)
+ {
+ work[0] = rowsA;
+ throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
+ }
- // Compute the l-th row transformation and place the l-th super-diagonal in e(l).
- e[l] = Math.Sqrt(CommonParallel.Aggregate(lp1, e.Length, index => e[index] * e[index]));
- if (e[l] != 0.0)
- {
- if (e[lp1] != 0.0)
- {
- e[l] = Math.Abs(e[l]) * (e[lp1] / Math.Abs(e[lp1]));
- }
+ SingularValueDecomposition(true, a, rowsA, columnsA, s, u, vt, work);
+ SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
+ }
- // Scale vector "e" from "lp1" by 1.0 / e[l]
- // lp1 > l, so we may use CommonParallel here
- CommonParallel.For(lp1, e.Length, index => e[index] = e[index] * (1.0 / e[lCopy]));
- e[lp1] = 1.0 + e[lp1];
- }
+ ///
+ /// Solves A*X=B for X using a previously SVD decomposed matrix.
+ ///
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// The s values returned by .
+ /// The left singular vectors returned by .
+ /// The right singular vectors returned by .
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ public void SvdSolveFactored(int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x)
+ {
+ if (s == null)
+ {
+ throw new ArgumentNullException("s");
+ }
- e[l] = -e[l];
+ if (u == null)
+ {
+ throw new ArgumentNullException("u");
+ }
- if (lp1 < aRows && e[l] != 0.0)
- {
- // Apply the transformation.
- for (i = lp1; i < aRows; i++)
- {
- work[i] = 0.0;
- }
+ if (vt == null)
+ {
+ throw new ArgumentNullException("vt");
+ }
- for (j = lp1; j < aColumns; j++)
- {
- for (var ii = lp1; ii < aRows; ii++)
- {
- work[ii] += e[j] * a[(j * aRows) + ii];
- }
- }
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
- for (j = lp1; j < aColumns; j++)
- {
- var ww = -e[j] / e[lp1];
- for (var ii = lp1; ii < aRows; ii++)
- {
- a[(j * aRows) + ii] += ww * work[ii];
- }
- }
- }
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
- if (!computeVectors)
- {
- continue;
- }
+ if (u.Length != rowsA * rowsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
+ }
- // Place the transformation in v for subsequent back multiplication.
- CommonParallel.For(lp1, aColumns, index => v[(lCopy * aColumns) + index] = e[index]);
+ if (vt.Length != columnsA * columnsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- // Set up the final bidiagonal matrix or order m.
- var m = Math.Min(aColumns, aRows + 1);
- var nctp1 = nct + 1;
- var nrtp1 = nrt + 1;
- if (nct < aColumns)
+ if (s.Length != Math.Min(rowsA, columnsA))
{
- stemp[nctp1 - 1] = a[(nctp1 - 1) * aRows + (nctp1 - 1)];
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (aRows < m)
+ if (b.Length != rowsA * columnsB)
{
- stemp[m - 1] = 0.0;
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (nrtp1 < m)
+ if (x.Length != columnsA * columnsB)
{
- e[nrtp1 - 1] = a[(m - 1) * aRows + (nrtp1 - 1)];
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- e[m - 1] = 0.0;
+ var mn = Math.Min(rowsA, columnsA);
+ var tmp = new double[columnsA];
- // If required, generate "u".
- if (computeVectors)
+ for (var k = 0; k < columnsB; k++)
{
- CommonParallel.For(nctp1 - 1, ncu, indexCol =>
- {
- CommonParallel.For(0, aRows, indexRow => u[(indexCol * aRows) + indexRow] = 0.0);
- u[(indexCol * aRows) + indexCol] = 1.0;
- });
-
- for (l = nct - 1; l >= 0; l--)
+ for (var j = 0; j < columnsA; j++)
{
- var lCopy = l;
-
- if (stemp[l] != 0.0)
+ double value = 0;
+ if (j < mn)
{
- for (j = l + 1; j < ncu; j++)
+ for (var i = 0; i < rowsA; i++)
{
- var jCopy = j;
- t = CommonParallel.Aggregate(lCopy, aRows, index => u[(jCopy * aRows) + index] * u[(lCopy * aRows) + index]);
- t = -t / u[(l * aRows) + l];
-
- for (var ii = l; ii < aRows; ii++)
- {
- u[(j * aRows) + ii] += t * u[(l * aRows) + ii];
- }
+ value += u[(j * rowsA) + i] * b[(k * rowsA) + i];
}
- // A part of column "l" of matrix A from row "l" to end multiply by -1.0
- CommonParallel.For(lCopy, aRows, index => u[(lCopy * aRows) + index] *= -1.0);
- u[(l * aRows) + l] = 1.0 + u[(l * aRows) + l];
- if (lCopy != 0)
- {
- CommonParallel.For(0, lCopy, index => u[(lCopy * aRows) + index] = 0.0);
- }
- }
- else
- {
- CommonParallel.For(0, aRows, index => u[(lCopy * aRows) + index] = 0.0);
- u[(l * aRows) + l] = 1.0;
+ value /= s[j];
}
+
+ tmp[j] = value;
}
- }
- // If it is required, generate v.
- if (computeVectors)
- {
- for (l = aColumns - 1; l >= 0; l--)
+ for (var j = 0; j < columnsA; j++)
{
- lp1 = l + 1;
- var lCopy = l;
-
- if (l < nrt)
+ double value = 0;
+ for (var i = 0; i < columnsA; i++)
{
- if (e[l] != 0.0)
- {
- for (j = lp1; j < aColumns; j++)
- {
- var jCopy = j;
- t = CommonParallel.Aggregate(lp1, aColumns, index => v[(jCopy * aColumns) + index] * v[(lCopy * aColumns) + index]);
- t = -t / v[(l * aColumns) + lp1];
- for (var ii = l; ii < aColumns; ii++)
- {
- v[(j * aColumns) + ii] += t * v[(l * aColumns) + ii];
- }
- }
- }
+ value += vt[(j * columnsA) + i] * tmp[i];
}
- CommonParallel.For(0, aColumns, index => v[(lCopy * aColumns) + index] = 0.0);
- v[(l * aColumns) + l] = 1.0;
+ x[(k * columnsA) + j] = value;
}
}
+ }
- // Transform "s" and "e" so that they are double
- for (i = 0; i < m; i++)
- {
- double r;
- if (stemp[i] != 0.0)
- {
- t = stemp[i];
- r = stemp[i] / t;
- stemp[i] = t;
- if (i < m - 1)
- {
- e[i] = e[i] / r;
- }
-
- if (computeVectors)
- {
- // A part of column "i" of matrix U from row 0 to end multiply by r
- for (j = 0; j < aRows; j++)
- {
- u[(i * aRows) + j] = u[(i * aRows) + j] * r;
- }
- }
- }
+ #endregion
- // Exit
- if (i == m - 1)
- {
- break;
- }
+ #region ILinearAlgebraProvider Members
- if (e[i] == 0.0)
- {
- continue;
- }
+ ///
+ /// Adds a scaled vector to another: y += alpha*x.
+ ///
+ /// The vector to update.
+ /// The value to scale by.
+ /// The vector to add to .
+ /// This equivalent to the AXPY BLAS routine.
+ public void AddVectorToScaledVector(float[] y, float alpha, float[] x)
+ {
+ if (y == null)
+ {
+ throw new ArgumentNullException("y");
+ }
- t = e[i];
- r = t / e[i];
- e[i] = t;
- stemp[i + 1] = stemp[i + 1] * r;
- if (!computeVectors)
- {
- continue;
- }
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
- // A part of column "i+1" of matrix VT from row 0 to end multiply by r
- for (j = 0; j < aColumns; j++)
- {
- v[((i + 1) * aColumns) + j] = v[((i + 1) * aColumns) + j] * r;
- }
+ if (y.Length != x.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
- // Main iteration loop for the singular values.
- var mn = m;
- var iter = 0;
+ if (alpha == 0.0)
+ {
+ return;
+ }
- while (m > 0)
+ if (alpha == 1.0)
{
- // Quit if all the singular values have been found.
- // If too many iterations have been performed throw exception.
- if (iter >= Maxiter)
- {
- throw new ArgumentException(Resources.ConvergenceFailed);
+ CommonParallel.For(0, y.Length, i => y[i] += x[i]);
+ }
+ else
+ {
+ CommonParallel.For(0, y.Length, i => y[i] += alpha * x[i]);
+ }
+ }
+
+ ///
+ /// Scales an array. Can be used to scale a vector and a matrix.
+ ///
+ /// The scalar.
+ /// The values to scale.
+ /// This is equivalent to the SCAL BLAS routine.
+ public void ScaleArray(float alpha, float[] x)
+ {
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (alpha == 1.0)
+ {
+ return;
+ }
+
+ CommonParallel.For(0, x.Length, i => x[i] = alpha * x[i]);
+ }
+
+ ///
+ /// Computes the dot product of x and y.
+ ///
+ /// The vector x.
+ /// The vector y.
+ /// The dot product of x and y.
+ /// This is equivalent to the DOT BLAS routine.
+ public float DotProduct(float[] x, float[] y)
+ {
+ if (y == null)
+ {
+ throw new ArgumentNullException("y");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (y.Length != x.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ float sum = 0;
+ CommonParallel.For(0, y.Length, index => sum += y[index] * x[index]);
+ return sum;
+ }
+
+ ///
+ /// Does a point wise add of two arrays z = x + y. This can be used
+ /// to add vectors or matrices.
+ ///
+ /// The array x.
+ /// The array y.
+ /// The result of the addition.
+ /// There is no equivalent BLAS routine, but many libraries
+ /// provide optimized (parallel and/or vectorized) versions of this
+ /// routine.
+ public void AddArrays(float[] x, float[] y, float[] result)
+ {
+ if (y == null)
+ {
+ throw new ArgumentNullException("y");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (y.Length != x.Length || y.Length != result.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ CommonParallel.For(0, y.Length, i => result[i] = x[i] + y[i]);
+ }
+
+ ///
+ /// Does a point wise subtraction of two arrays z = x - y. This can be used
+ /// to subtract vectors or matrices.
+ ///
+ /// The array x.
+ /// The array y.
+ /// The result of the subtraction.
+ /// There is no equivalent BLAS routine, but many libraries
+ /// provide optimized (parallel and/or vectorized) versions of this
+ /// routine.
+ public void SubtractArrays(float[] x, float[] y, float[] result)
+ {
+ if (y == null)
+ {
+ throw new ArgumentNullException("y");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (y.Length != x.Length || y.Length != result.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ CommonParallel.For(0, y.Length, i => result[i] = x[i] - y[i]);
+ }
+
+ ///
+ /// Does a point wise multiplication of two arrays z = x * y. This can be used
+ /// to multiple elements of vectors or matrices.
+ ///
+ /// The array x.
+ /// The array y.
+ /// The result of the point wise multiplication.
+ /// There is no equivalent BLAS routine, but many libraries
+ /// provide optimized (parallel and/or vectorized) versions of this
+ /// routine.
+ public void PointWiseMultiplyArrays(float[] x, float[] y, float[] result)
+ {
+ if (y == null)
+ {
+ throw new ArgumentNullException("y");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (y.Length != x.Length || y.Length != result.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ CommonParallel.For(0, y.Length, i => result[i] = x[i] * y[i]);
+ }
+
+ ///
+ /// Computes the requested of the matrix.
+ ///
+ /// The type of norm to compute.
+ /// The number of rows.
+ /// The number of columns.
+ /// The matrix to compute the norm from.
+ ///
+ /// The requested of the matrix.
+ ///
+ public float MatrixNorm(Norm norm, int rows, int columns, float[] matrix)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Computes the requested of the matrix.
+ ///
+ /// The type of norm to compute.
+ /// The number of rows.
+ /// The number of columns.
+ /// The matrix to compute the norm from.
+ /// The work array. Only used when
+ /// and needs to be have a length of at least M (number of rows of .
+ ///
+ /// The requested of the matrix.
+ ///
+ public float MatrixNorm(Norm norm, int rows, int columns, float[] matrix, float[] work)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Multiples two matrices. result = x * y
+ ///
+ /// The x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
+ /// The y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
+ /// Where to store the result of the multiplication.
+ /// This is a simplified version of the BLAS GEMM routine with alpha
+ /// set to 1.0 and beta set to 0.0, and x and y are not transposed.
+ public void MatrixMultiply(float[] x, int rowsX, int columnsX, float[] y, int rowsY, int columnsY, float[] result)
+ {
+ // First check some basic requirement on the parameters of the matrix multiplication.
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (y == null)
+ {
+ throw new ArgumentNullException("y");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (rowsX * columnsX != x.Length)
+ {
+ throw new ArgumentException("x.Length != xRows * xColumns");
+ }
+
+ if (rowsY * columnsY != y.Length)
+ {
+ throw new ArgumentException("y.Length != yRows * yColumns");
+ }
+
+ if (columnsX != rowsY)
+ {
+ throw new ArgumentException("xColumns != yRows");
+ }
+
+ if (rowsX * columnsY != result.Length)
+ {
+ throw new ArgumentException("xRows * yColumns != result.Length");
+ }
+
+ // Check whether we will be overwriting any of our inputs and make copies if necessary.
+ // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
+ // as result, we can do it on a row wise basis. We should investigate this.
+ float[] xdata;
+ if (ReferenceEquals(x, result))
+ {
+ xdata = (float[])x.Clone();
+ }
+ else
+ {
+ xdata = x;
+ }
+
+ float[] ydata;
+ if (ReferenceEquals(y, result))
+ {
+ ydata = (float[])y.Clone();
+ }
+ else
+ {
+ ydata = y;
+ }
+
+ // Start the actual matrix multiplication.
+ // TODO - For small matrices we should get rid of the parallelism because of startup costs.
+ // Perhaps the following implementations would be a good one
+ // http://blog.feradz.com/2009/01/cache-efficient-matrix-multiplication/
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0f, xdata, rowsX, columnsX, ydata, rowsY, columnsY, 0.0f, result);
+ }
+
+ ///
+ /// Multiplies two matrices and updates another with the result. c = alpha*op(a)*op(b) + beta*c
+ ///
+ /// How to transpose the matrix.
+ /// How to transpose the matrix.
+ /// The value to scale matrix.
+ /// The a matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
+ /// The b matrix
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
+ /// The value to scale the matrix.
+ /// The c matrix.
+ public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, float alpha, float[] a, int rowsA, int columnsA, float[] b, int rowsB, int columnsB, float beta, float[] c)
+ {
+ // Choose nonsensical values for the number of rows in c; fill them in depending
+ // on the operations on a and b.
+ int rowsC;
+
+ // First check some basic requirement on the parameters of the matrix multiplication.
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if ((int)transposeA > 111 && (int)transposeB > 111)
+ {
+ if (rowsA != columnsB)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ if (columnsA * rowsB != c.Length)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ rowsC = columnsA;
+ }
+ else if ((int)transposeA > 111)
+ {
+ if (rowsA != rowsB)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ if (columnsA * columnsB != c.Length)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ rowsC = columnsA;
+ }
+ else if ((int)transposeB > 111)
+ {
+ if (columnsA != columnsB)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ if (rowsA * rowsB != c.Length)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ rowsC = rowsA;
+ }
+ else
+ {
+ if (columnsA != rowsB)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ if (rowsA * columnsB != c.Length)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ rowsC = rowsA;
+ }
+
+ if (alpha == 0.0 && beta == 0.0)
+ {
+ Array.Clear(c, 0, c.Length);
+ return;
+ }
+
+ // Check whether we will be overwriting any of our inputs and make copies if necessary.
+ // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
+ // as result, we can do it on a row wise basis. We should investigate this.
+ float[] adata;
+ if (ReferenceEquals(a, c))
+ {
+ adata = (float[])a.Clone();
+ }
+ else
+ {
+ adata = a;
+ }
+
+ float[] bdata;
+ if (ReferenceEquals(b, c))
+ {
+ bdata = (float[])b.Clone();
+ }
+ else
+ {
+ bdata = b;
+ }
+
+ if (alpha == 1.0)
+ {
+ if (beta == 0.0)
+ {
+ if ((int)transposeA > 111 && (int)transposeB > 111)
+ {
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ float s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
+ }
+ else if ((int)transposeA > 111)
+ {
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ float s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s;
+ }
+ });
+ }
+ else if ((int)transposeB > 111)
+ {
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ float s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ float s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s;
+ }
+ });
+ }
+ }
+ else
+ {
+ if ((int)transposeA > 111 && (int)transposeB > 111)
+ {
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ float s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + s;
+ }
+ });
+ }
+ else if ((int)transposeA > 111)
+ {
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ float s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
+ }
+ else if ((int)transposeB > 111)
+ {
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ float s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s + (c[jIndex + i] * beta);
+ }
+ });
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ float s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
+ }
+ }
+ }
+ else
+ {
+ if ((int)transposeA > 111 && (int)transposeB > 111)
+ {
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ float s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + (alpha * s);
+ }
+ });
+ }
+ else if ((int)transposeA > 111)
+ {
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ float s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
+ }
+ else if ((int)transposeB > 111)
+ {
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ float s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (alpha * s) + (c[jIndex + i] * beta);
+ }
+ });
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ float s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
+ }
+ }
+ }
+
+ ///
+ /// Computes the LUP factorization of A. P*A = L*U.
+ ///
+ /// An by matrix. The matrix is overwritten with the
+ /// the LU factorization on exit. The lower triangular factor L is stored in under the diagonal of (the diagonal is always 1.0
+ /// for the L factor). The upper triangular factor U is stored on and above the diagonal of .
+ /// The order of the square matrix .
+ /// On exit, it contains the pivot indices. The size of the array must be .
+ /// This is equivalent to the GETRF LAPACK routine.
+ public void LUFactor(float[] data, int order, int[] ipiv)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ if (ipiv == null)
+ {
+ throw new ArgumentNullException("ipiv");
+ }
+
+ if (data.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
+ }
+
+ if (ipiv.Length != order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
+ }
+
+ // Initialize the pivot matrix to the identity permutation.
+ for (var i = 0; i < order; i++)
+ {
+ ipiv[i] = i;
+ }
+
+ var vecLUcolj = new float[order];
+
+ // Outer loop.
+ for (var j = 0; j < order; j++)
+ {
+ var indexj = j * order;
+ var indexjj = indexj + j;
+
+ // Make a copy of the j-th column to localize references.
+ for (var i = 0; i < order; i++)
+ {
+ vecLUcolj[i] = data[indexj + i];
+ }
+
+ // Apply previous transformations.
+ for (var i = 0; i < order; i++)
+ {
+ // Most of the time is spent in the following dot product.
+ var kmax = Math.Min(i, j);
+ var s = 0.0f;
+ for (var k = 0; k < kmax; k++)
+ {
+ s += data[(k * order) + i] * vecLUcolj[k];
+ }
+
+ data[indexj + i] = vecLUcolj[i] -= s;
+ }
+
+ // Find pivot and exchange if necessary.
+ var p = j;
+ for (var i = j + 1; i < order; i++)
+ {
+ if (Math.Abs(vecLUcolj[i]) > Math.Abs(vecLUcolj[p]))
+ {
+ p = i;
+ }
+ }
+
+ if (p != j)
+ {
+ for (var k = 0; k < order; k++)
+ {
+ var indexk = k * order;
+ var indexkp = indexk + p;
+ var indexkj = indexk + j;
+ var temp = data[indexkp];
+ data[indexkp] = data[indexkj];
+ data[indexkj] = temp;
+ }
+
+ ipiv[j] = p;
+ }
+
+ // Compute multipliers.
+ if (j < order & data[indexjj] != 0.0)
+ {
+ for (var i = j + 1; i < order; i++)
+ {
+ data[indexj + i] /= data[indexjj];
+ }
+ }
+ }
+ }
+
+ ///
+ /// Computes the inverse of matrix using LU factorization.
+ ///
+ /// The N by N matrix to invert. Contains the inverse On exit.
+ /// The order of the square matrix .
+ /// This is equivalent to the GETRF and GETRI LAPACK routines.
+ public void LUInverse(float[] a, int order)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (a.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
+ }
+
+ var ipiv = new int[order];
+ LUFactor(a, order, ipiv);
+ LUInverseFactored(a, order, ipiv);
+ }
+
+ ///
+ /// Computes the inverse of a previously factored matrix.
+ ///
+ /// The LU factored N by N matrix. Contains the inverse On exit.
+ /// The order of the square matrix .
+ /// The pivot indices of .
+ /// This is equivalent to the GETRI LAPACK routine.
+ public void LUInverseFactored(float[] a, int order, int[] ipiv)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (ipiv == null)
+ {
+ throw new ArgumentNullException("ipiv");
+ }
+
+ if (a.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
+ }
+
+ if (ipiv.Length != order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
+ }
+
+ var inverse = new float[a.Length];
+ for (var i = 0; i < order; i++)
+ {
+ inverse[i + (order * i)] = 1.0f;
+ }
+
+ LUSolveFactored(order, a, order, ipiv, inverse);
+ Buffer.BlockCopy(inverse, 0, a, 0, a.Length * Constants.SizeOfFloat);
+ }
+
+ ///
+ /// Computes the inverse of matrix using LU factorization.
+ ///
+ /// The N by N matrix to invert. Contains the inverse On exit.
+ /// The order of the square matrix .
+ /// The work array. The array must have a length of at least N,
+ /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
+ /// work size value.
+ /// This is equivalent to the GETRF and GETRI LAPACK routines.
+ public void LUInverse(float[] a, int order, float[] work)
+ {
+ LUInverse(a, order);
+ }
+
+ ///
+ /// Computes the inverse of a previously factored matrix.
+ ///
+ /// The LU factored N by N matrix. Contains the inverse On exit.
+ /// The order of the square matrix .
+ /// The pivot indices of .
+ /// The work array. The array must have a length of at least N,
+ /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
+ /// work size value.
+ /// This is equivalent to the GETRI LAPACK routine.
+ public void LUInverseFactored(float[] a, int order, int[] ipiv, float[] work)
+ {
+ LUInverseFactored(a, order, ipiv);
+ }
+
+ ///
+ /// Solves A*X=B for X using LU factorization.
+ ///
+ /// The number of columns of B.
+ /// The square matrix A.
+ /// The order of the square matrix .
+ /// The B matrix.
+ /// This is equivalent to the GETRF and GETRS LAPACK routines.
+ public void LUSolve(int columnsOfB, float[] a, int order, float[] b)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (a.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
+ }
+
+ if (b.Length != order * columnsOfB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ var ipiv = new int[order];
+ LUFactor(a, order, ipiv);
+ LUSolveFactored(columnsOfB, a, order, ipiv, b);
+ }
+
+ ///
+ /// Solves A*X=B for X using a previously factored A matrix.
+ ///
+ /// The number of columns of B.
+ /// The factored A matrix.
+ /// The order of the square matrix .
+ /// The pivot indices of .
+ /// The B matrix.
+ /// This is equivalent to the GETRS LAPACK routine.
+ public void LUSolveFactored(int columnsOfB, float[] a, int order, int[] ipiv, float[] b)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (ipiv == null)
+ {
+ throw new ArgumentNullException("ipiv");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (a.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
+ }
+
+ if (ipiv.Length != order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
+ }
+
+ if (b.Length != order * columnsOfB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ // Compute the column vector P*B
+ for (var i = 0; i < ipiv.Length; i++)
+ {
+ if (ipiv[i] == i)
+ {
+ continue;
+ }
+
+ var p = ipiv[i];
+ for (var j = 0; j < columnsOfB; j++)
+ {
+ var indexk = j * order;
+ var indexkp = indexk + p;
+ var indexkj = indexk + i;
+ var temp = b[indexkp];
+ b[indexkp] = b[indexkj];
+ b[indexkj] = temp;
+ }
+ }
+
+ // Solve L*Y = P*B
+ for (var k = 0; k < order; k++)
+ {
+ var korder = k * order;
+ for (var i = k + 1; i < order; i++)
+ {
+ for (var j = 0; j < columnsOfB; j++)
+ {
+ var index = j * order;
+ b[i + index] -= b[k + index] * a[i + korder];
+ }
+ }
+ }
+
+ // Solve U*X = Y;
+ for (var k = order - 1; k >= 0; k--)
+ {
+ var korder = k + (k * order);
+ for (var j = 0; j < columnsOfB; j++)
+ {
+ b[k + (j * order)] /= a[korder];
+ }
+
+ korder = k * order;
+ for (var i = 0; i < k; i++)
+ {
+ for (var j = 0; j < columnsOfB; j++)
+ {
+ var index = j * order;
+ b[i + index] -= b[k + index] * a[i + korder];
+ }
+ }
+ }
+ }
+
+ ///
+ /// Solves A*X=B for X using LU factorization.
+ ///
+ /// How to transpose the matrix.
+ /// The number of columns of B.
+ /// The square matrix A.
+ /// The order of the square matrix .
+ /// The B matrix.
+ /// This is equivalent to the GETRF and GETRS LAPACK routines.
+ public void LUSolve(Transpose transposeA, int columnsOfB, float[] a, int order, float[] b)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (a.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
+ }
+
+ if (b.Length != order * columnsOfB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ var ipiv = new int[order];
+ LUFactor(a, order, ipiv);
+ LUSolveFactored(transposeA, columnsOfB, a, order, ipiv, b);
+ }
+
+ ///
+ /// Solves A*X=B for X using a previously factored A matrix.
+ ///
+ /// How to transpose the matrix.
+ /// The number of columns of B.
+ /// The factored A matrix.
+ /// The order of the square matrix .
+ /// The pivot indices of .
+ /// The B matrix.
+ /// This is equivalent to the GETRS LAPACK routine.
+ public void LUSolveFactored(Transpose transposeA, int columnsOfB, float[] a, int order, int[] ipiv, float[] b)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (ipiv == null)
+ {
+ throw new ArgumentNullException("ipiv");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (a.Length != order * order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
+ }
+
+ if (ipiv.Length != order)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
+ }
+
+ if (b.Length != order * columnsOfB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ if ((transposeA == Transpose.Transpose) || (transposeA == Transpose.ConjugateTranspose))
+ {
+ var aT = new float[a.Length];
+ for (var i = 0; i < order; i++)
+ {
+ for (var j = 0; j < order; j++)
+ {
+ aT[(j * order) + i] = a[(i * order) + j];
+ }
+ }
+
+ LUSolveFactored(columnsOfB, aT, order, ipiv, b);
+ }
+ else
+ {
+ LUSolveFactored(columnsOfB, a, order, ipiv, b);
+ }
+ }
+
+ ///
+ /// Computes the Cholesky factorization of A.
+ ///
+ /// On entry, a square, positive definite matrix. On exit, the matrix is overwritten with the
+ /// the Cholesky factorization.
+ /// The number of rows or columns in the matrix.
+ /// This is equivalent to the POTRF LAPACK routine.
+ public void CholeskyFactor(float[] a, int order)
+ {
+ var factor = new float[a.Length];
+
+ for (var j = 0; j < order; j++)
+ {
+ float d = 0.0f;
+ int index;
+ for (var k = 0; k < j; k++)
+ {
+ float s = 0.0f;
+ int i;
+ for (i = 0; i < k; i++)
+ {
+ s += factor[(i * order) + k] * factor[(i * order) + j];
+ }
+
+ var tmp = k * order;
+ index = tmp + j;
+ s = (a[index] - s) / factor[tmp + k];
+ factor[index] = s;
+ d += s * s;
+ }
+
+ index = (j * order) + j;
+ d = a[index] - d;
+ if (d <= 0.0F)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
+ }
+
+ factor[index] = (float)Math.Sqrt(d);
+ for (var k = j + 1; k < order; k++)
+ {
+ factor[(k * order) + j] = 0.0F;
}
+ }
+
+ Buffer.BlockCopy(factor, 0, a, 0, factor.Length * Constants.SizeOfFloat);
+ }
+
+ ///
+ /// Solves A*X=B for X using Cholesky factorization.
+ ///
+ /// The square, positive definite matrix A.
+ /// The number of rows and columns in A.
+ /// The B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
+ /// This is equivalent to the POTRF add POTRS LAPACK routines.
+ public void CholeskySolve(float[] a, int orderA, float[] b, int rowsB, int columnsB)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (orderA != rowsB)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ if (ReferenceEquals(a, b))
+ {
+ throw new ArgumentException(Resources.ArgumentReferenceDifferent);
+ }
+
+ CholeskyFactor(a, orderA);
+ CholeskySolveFactored(a, orderA, b, rowsB, columnsB);
+ }
+
+ ///
+ /// Solves A*X=B for X using a previously factored A matrix.
+ ///
+ /// The square, positive definite matrix A.
+ /// The number of rows and columns in A.
+ /// The B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
+ /// This is equivalent to the POTRS LAPACK routine.
+ public void CholeskySolveFactored(float[] a, int orderA, float[] b, int rowsB, int columnsB)
+ {
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
- // This section of the program inspects for negligible elements in the s and e arrays.
- // On completion the variables kase and l are set as follows.
+ if (orderA != rowsB)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
- // kase = 1: if mS[m] and e[l-1] are negligible and l < m
- // kase = 2: if mS[l] is negligible and l < m
- // kase = 3: if e[l-1] is negligible, l < m, and mS[l, ..., mS[m] are not negligible (qr step).
- // kase = 4: if e[m-1] is negligible (convergence).
- double ztest;
- double test;
- for (l = m - 2; l >= 0; l--)
- {
- test = Math.Abs(stemp[l]) + Math.Abs(stemp[l + 1]);
- ztest = test + Math.Abs(e[l]);
- if (ztest.AlmostEqualInDecimalPlaces(test, 15))
- {
- e[l] = 0.0;
- break;
- }
- }
+ if (ReferenceEquals(a, b))
+ {
+ throw new ArgumentException(Resources.ArgumentReferenceDifferent);
+ }
- int kase;
- if (l == m - 2)
- {
- kase = 4;
- }
- else
+ CommonParallel.For(
+ 0,
+ columnsB,
+ c =>
{
- int ls;
- for (ls = m - 1; ls > l; ls--)
+ var cindex = c * orderA;
+
+ // Solve L*Y = B;
+ float sum;
+ for (var i = 0; i < orderA; i++)
{
- test = 0.0;
- if (ls != m - 1)
+ sum = b[cindex + i];
+ for (var k = i - 1; k >= 0; k--)
{
- test = test + Math.Abs(e[ls]);
+ sum -= a[(k * orderA) + i] * b[cindex + k];
}
- if (ls != l + 1)
- {
- test = test + Math.Abs(e[ls - 1]);
- }
+ b[cindex + i] = sum / a[(i * orderA) + i];
+ }
- ztest = test + Math.Abs(stemp[ls]);
- if (ztest.AlmostEqualInDecimalPlaces(test, 15))
+ // 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++)
{
- stemp[ls] = 0.0;
- break;
+ sum -= a[iindex + k] * b[cindex + k];
}
- }
- if (ls == l)
- {
- kase = 3;
- }
- else if (ls == m - 1)
- {
- kase = 1;
+ b[cindex + i] = sum / a[iindex + i];
}
- else
- {
- kase = 2;
- l = ls;
- }
- }
+ });
+ }
- l = l + 1;
+ ///
+ /// Computes the QR factorization of A.
+ ///
+ /// On entry, it is the M by N A matrix to factor. On exit,
+ /// it is overwritten with the R matrix of the QR factorization.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// On exit, A M by M matrix that holds the Q matrix of the
+ /// QR factorization.
+ /// This is similar to the GEQRF and ORGQR LAPACK routines.
+ public void QRFactor(float[] r, int rowsR, int columnsR, float[] q)
+ {
+ if (r == null)
+ {
+ throw new ArgumentNullException("r");
+ }
- // Perform the task indicated by kase.
- int k;
- double f;
- switch (kase)
+ if (q == null)
+ {
+ throw new ArgumentNullException("q");
+ }
+
+ if (r.Length != rowsR * columnsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
+ }
+
+ if (q.Length != rowsR * rowsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
+ }
+
+ var work = new float[rowsR * rowsR];
+ QRFactor(r, rowsR, columnsR, q, work);
+ }
+
+ ///
+ /// Computes the QR factorization of A.
+ ///
+ /// On entry, it is the M by N A matrix to factor. On exit,
+ /// it is overwritten with the R matrix of the QR factorization.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// On exit, A M by M matrix that holds the Q matrix of the
+ /// QR factorization.
+ /// The work array. The array must have a length of at least N,
+ /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
+ /// work size value.
+ /// This is similar to the GEQRF and ORGQR LAPACK routines.
+ public void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] work)
+ {
+ if (r == null)
+ {
+ throw new ArgumentNullException("r");
+ }
+
+ if (q == null)
+ {
+ throw new ArgumentNullException("q");
+ }
+
+ if (work == null)
+ {
+ throw new ArgumentNullException("q");
+ }
+
+ if (r.Length != rowsR * columnsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
+ }
+
+ if (q.Length != rowsR * rowsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
+ }
+
+ if (work.Length < rowsR * rowsR)
+ {
+ work[0] = rowsR * rowsR;
+ throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
+ }
+
+ CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = 1.0f);
+
+ var minmn = Math.Min(rowsR, columnsR);
+ for (var i = 0; i < minmn; i++)
+ {
+ GenerateColumn(work, r, rowsR, i, rowsR - 1, i);
+ ComputeQR(work, i, r, rowsR, i, rowsR - 1, i + 1, columnsR - 1);
+ }
+
+ for (var i = minmn - 1; i >= 0; i--)
+ {
+ ComputeQR(work, i, q, rowsR, i, rowsR - 1, i, rowsR - 1);
+ }
+
+ work[0] = rowsR * rowsR;
+ }
+
+ #region QR Factor Helper functions
+
+ ///
+ /// Perform calculation of Q or R
+ ///
+ /// Work array
+ /// Index of colunn in work array
+ /// Q or R matrices
+ /// The number of rows
+ /// The first row in
+ /// The last row
+ /// The first column
+ /// The last column
+ private static void ComputeQR(float[] work, int workIndex, float[] a, int rowCount, int rowStart, int rowEnd, int columnStart, int columnEnd)
+ {
+ if (rowStart > rowEnd || columnStart > columnEnd)
+ {
+ return;
+ }
+
+ var vector = new float[columnEnd - columnStart + 1];
+ for (var i = rowStart; i <= rowEnd; i++)
+ {
+ for (var j = columnStart; j <= columnEnd; j++)
{
- // Deflate negligible s[m].
- case 1:
- f = e[m - 2];
- e[m - 2] = 0.0;
- double t1;
- for (var kk = l; kk < m - 1; kk++)
- {
- k = m - 2 - kk + l;
- t1 = stemp[k];
+ vector[j - columnStart] += work[(workIndex * rowCount) + i - rowStart] * a[(j * rowCount) + i];
+ }
+ }
- Drotg(ref t1, ref f, ref cs, ref sn);
- stemp[k] = t1;
- if (k != l)
- {
- f = -sn * e[k - 1];
- e[k - 1] = cs * e[k - 1];
- }
+ for (var i = rowStart; i <= rowEnd; i++)
+ {
+ for (var j = columnStart; j <= columnEnd; j++)
+ {
+ a[(j * rowCount) + i] -= work[(workIndex * rowCount) + i - rowStart] * vector[j - columnStart];
+ }
+ }
+ }
- if (computeVectors)
- {
- // Rotate
- for (i = 0; i < aColumns; i++)
- {
- var z = cs * v[(k * aColumns) + i] + sn * v[((m - 1) * aColumns) + i];
- v[((m - 1) * aColumns) + i] = cs * v[((m - 1) * aColumns) + i] - sn * v[(k * aColumns) + i];
- v[(k * aColumns) + i] = z;
- }
- }
- }
+ ///
+ /// Generate column from initial matrix to work array
+ ///
+ /// Work array
+ /// Initial matrix
+ /// The number of rows in matrix
+ /// The firts row
+ /// The last row
+ /// Column index
+ private static void GenerateColumn(float[] work, float[] a, int rowCount, int rowStart, int rowEnd, int column)
+ {
+ var tmp = column * rowCount;
+ var index = tmp + rowStart;
- break;
+ CommonParallel.For(
+ rowStart,
+ rowEnd + 1,
+ i =>
+ {
+ var iIndex = tmp + i;
+ work[iIndex - rowStart] = a[iIndex];
+ a[iIndex] = 0.0f;
+ });
- // Split at negligible s[l].
- case 2:
- f = e[l - 1];
- e[l - 1] = 0.0;
- for (k = l; k < m; k++)
- {
- t1 = stemp[k];
- Drotg(ref t1, ref f, ref cs, ref sn);
- stemp[k] = t1;
- f = -sn * e[k];
- e[k] = cs * e[k];
- if (computeVectors)
- {
- // Rotate
- for (i = 0; i < aRows; i++)
- {
- var z = cs * u[(k * aRows) + i] + sn * u[((l - 1) * aRows) + i];
- u[((l - 1) * aRows) + i] = cs * u[((l - 1) * aRows) + i] - sn * u[(k * aRows) + i];
- u[(k * aRows) + i] = z;
- }
- }
- }
+ var norm = 0.0;
+ for (var i = 0; i < rowEnd - rowStart + 1; ++i)
+ {
+ var iindex = tmp + i;
+ norm += work[iindex] * work[iindex];
+ }
+
+ norm = Math.Sqrt(norm);
+ if (rowStart == rowEnd || norm == 0)
+ {
+ a[index] = -work[tmp];
+ work[tmp] = (float)Math.Sqrt(2.0);
+ return;
+ }
+
+ var scale = 1.0f / (float)norm;
+ if (work[tmp] < 0.0)
+ {
+ scale *= -1.0f;
+ }
- break;
+ a[index] = -1.0f / scale;
+ CommonParallel.For(0, rowEnd - rowStart + 1, i => work[tmp + i] *= scale);
+ work[tmp] += 1.0f;
- // Perform one qr step.
- case 3:
+ var s = (float)Math.Sqrt(1.0 / work[tmp]);
+ CommonParallel.For(0, rowEnd - rowStart + 1, i => work[tmp + i] *= s);
+ }
-// calculate the shift.
- var scale = 0.0;
- scale = Math.Max(scale, Math.Abs(stemp[m - 1]));
- scale = Math.Max(scale, Math.Abs(stemp[m - 2]));
- scale = Math.Max(scale, Math.Abs(e[m - 2]));
- scale = Math.Max(scale, Math.Abs(stemp[l]));
- scale = Math.Max(scale, Math.Abs(e[l]));
- var sm = stemp[m - 1] / scale;
- var smm1 = stemp[m - 2] / scale;
- var emm1 = e[m - 2] / scale;
- var sl = stemp[l] / scale;
- var el = e[l] / scale;
- var b = ((smm1 + sm) * (smm1 - sm) + (emm1 * emm1)) / 2.0;
- var c = (sm * emm1) * (sm * emm1);
- var shift = 0.0;
- if (b != 0.0 || c != 0.0)
- {
- shift = Math.Sqrt((b * b) + c);
- if (b < 0.0)
- {
- shift = -shift;
- }
+ #endregion
- shift = c / (b + shift);
- }
+ ///
+ /// Solves A*X=B for X using QR factorization of A.
+ ///
+ /// On entry, it is the M by N A matrix to factor. On exit,
+ /// it is overwritten with the R matrix of the QR factorization.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// On exit, A M by M matrix that holds the Q matrix of the
+ /// QR factorization.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ public void QRSolve(float[] r, int rowsR, int columnsR, float[] q, float[] b, int columnsB, float[] x)
+ {
+ if (r == null)
+ {
+ throw new ArgumentNullException("r");
+ }
- f = (sl + sm) * (sl - sm) + shift;
- var g = sl * el;
+ if (q == null)
+ {
+ throw new ArgumentNullException("q");
+ }
- // Chase zeros
- for (k = l; k < m - 1; k++)
- {
- Drotg(ref f, ref g, ref cs, ref sn);
- if (k != l)
- {
- e[k - 1] = f;
- }
+ if (b == null)
+ {
+ throw new ArgumentNullException("q");
+ }
- f = cs * stemp[k] + sn * e[k];
- e[k] = cs * e[k] - sn * stemp[k];
- g = sn * stemp[k + 1];
- stemp[k + 1] = cs * stemp[k + 1];
- if (computeVectors)
- {
- for (i = 0; i < aColumns; i++)
- {
- var z = cs * v[k * aColumns + i] + sn * v[(k + 1) * aColumns + i];
- v[(k + 1) * aColumns + i] = cs * v[(k + 1) * aColumns + i] - sn * v[k * aColumns + i];
- v[k * aColumns + i] = z;
- }
- }
+ if (x == null)
+ {
+ throw new ArgumentNullException("q");
+ }
- Drotg(ref f, ref g, ref cs, ref sn);
- stemp[k] = f;
- f = cs * e[k] + sn * stemp[k + 1];
- stemp[k + 1] = -sn * e[k] + cs * stemp[k + 1];
- g = sn * e[k + 1];
- e[k + 1] = cs * e[k + 1];
- if (computeVectors && k < aRows)
- {
- for (i = 0; i < aRows; i++)
- {
- var z = cs * u[k * aRows + i] + sn * u[(k + 1) * aRows + i];
- u[(k + 1) * aRows + i] = cs * u[(k + 1) * aRows + i] - sn * u[k * aRows + i];
- u[k * aRows + i] = z;
- }
- }
- }
+ if (r.Length != rowsR * columnsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
+ }
- e[m - 2] = f;
- iter = iter + 1;
- break;
+ if (q.Length != rowsR * rowsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
+ }
- // Convergence
- case 4:
+ if (b.Length != rowsR * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
-// Make the singular value positive
- if (stemp[l] < 0.0)
- {
- stemp[l] = -stemp[l];
- if (computeVectors)
- {
- // A part of column "l" of matrix VT from row 0 to end multiply by -1
- for (i = 0; i < aColumns; i++)
- {
- v[(l * aColumns) + i] = v[(l * aColumns) + i] * -1.0;
- }
- }
- }
+ if (x.Length != columnsR * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
+ }
- // Order the singular value.
- while (l != mn - 1)
- {
- if (stemp[l] >= stemp[l + 1])
- {
- break;
- }
+ var work = new float[rowsR * rowsR];
+ QRSolve(r, rowsR, columnsR, q, b, columnsB, x, work);
+ }
- t = stemp[l];
- stemp[l] = stemp[l + 1];
- stemp[l + 1] = t;
- if (computeVectors && l < aColumns)
- {
- // Swap columns l, l + 1
- for (i = 0; i < aColumns; i++)
- {
- var z = v[l * aColumns + i];
- v[l * aColumns + i] = v[(l + 1) * aColumns + i];
- v[(l + 1) * aColumns + i] = z;
- }
- }
+ ///
+ /// Solves A*X=B for X using QR factorization of A.
+ ///
+ /// On entry, it is the M by N A matrix to factor. On exit,
+ /// it is overwritten with the R matrix of the QR factorization.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// On exit, A M by M matrix that holds the Q matrix of the
+ /// QR factorization.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ /// The work array. The array must have a length of at least N,
+ /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
+ /// work size value.
+ public void QRSolve(float[] r, int rowsR, int columnsR, float[] q, float[] b, int columnsB, float[] x, float[] work)
+ {
+ if (r == null)
+ {
+ throw new ArgumentNullException("r");
+ }
- if (computeVectors && l < aRows)
- {
- // Swap columns l, l + 1
- for (i = 0; i < aRows; i++)
- {
- var z = u[l * aRows + i];
- u[l * aRows + i] = u[(l + 1) * aRows + i];
- u[(l + 1) * aRows + i] = z;
- }
- }
+ if (q == null)
+ {
+ throw new ArgumentNullException("q");
+ }
- l = l + 1;
- }
+ if (b == null)
+ {
+ throw new ArgumentNullException("q");
+ }
- iter = 0;
- m = m - 1;
- break;
- }
+ if (x == null)
+ {
+ throw new ArgumentNullException("q");
}
- if (computeVectors)
+ if (r.Length != rowsR * columnsR)
{
- // Finally transpose "v" to get "vt" matrix
- for (i = 0; i < aColumns; i++)
- {
- for (j = 0; j < aColumns; j++)
- {
- vt[j * aColumns + i] = v[i * aColumns + j];
- }
- }
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- // 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.
- // We should port lapack's svd routine to remove this problem.
- Buffer.BlockCopy(stemp, 0, s, 0, Math.Min(aRows, aColumns) * Constants.SizeOfDouble);
+ if (q.Length != rowsR * rowsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
+ }
- // 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] = aRows;
- }
+ if (b.Length != rowsR * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ if (x.Length != columnsR * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
+ }
+
+ if (work.Length < rowsR * rowsR)
+ {
+ work[0] = rowsR * rowsR;
+ throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
+ }
+
+ QRFactor(r, rowsR, columnsR, q, work);
+ QRSolveFactored(q, r, rowsR, columnsR, b, columnsB, x);
+ work[0] = rowsR * rowsR;
+ }
+
///
- /// Given the Cartesian coordinates (da, db) of a point p, these fucntion return the parameters da, db, c, and s
- /// associated with the Givens rotation that zeros the y-coordinate of the point.
+ /// Solves A*X=B for X using a previously QR factored matrix.
///
- /// Provides the x-coordinate of the point p. On exit contains the parameter r associated with the Givens rotation
- /// Provides the y-coordinate of the point p. On exit contains the parameter z associated with the Givens rotation
- /// Contains the parameter c associated with the Givens rotation
- /// Contains the parameter s associated with the Givens rotation
- /// This is equivalent to the DROTG LAPACK routine.
- private static void Drotg(ref double da, ref double db, ref double c, ref double s)
+ /// The Q matrix obtained by calling .
+ /// The R matrix obtained by calling .
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ public void QRSolveFactored(float[] q, float[] r, int rowsR, int columnsR, float[] b, int columnsB, float[] x)
{
- double r, z;
+ if (r == null)
+ {
+ throw new ArgumentNullException("r");
+ }
- var roe = db;
- var absda = Math.Abs(da);
- var absdb = Math.Abs(db);
- if (absda > absdb)
+ if (q == null)
{
- roe = da;
+ throw new ArgumentNullException("q");
}
- var scale = absda + absdb;
- if (scale == 0.0)
+ if (b == null)
{
- c = 1.0;
- s = 0.0;
- r = 0.0;
- z = 0.0;
+ throw new ArgumentNullException("q");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("q");
+ }
+
+ if (r.Length != rowsR * columnsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
+ }
+
+ if (q.Length != rowsR * rowsR)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
+ }
+
+ if (b.Length != rowsR * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ if (x.Length != columnsR * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
+ }
+
+ var sol = new float[b.Length];
+
+ // Copy B matrix to "sol", so B data will not be changed
+ Buffer.BlockCopy(b, 0, sol, 0, b.Length * Constants.SizeOfFloat);
+
+ // Compute Y = transpose(Q)*B
+ var column = new float[rowsR];
+ for (var j = 0; j < columnsB; j++)
+ {
+ var jm = j * rowsR;
+ CommonParallel.For(0, rowsR, k => column[k] = sol[jm + k]);
+ CommonParallel.For(
+ 0,
+ rowsR,
+ i =>
+ {
+ var im = i * rowsR;
+ sol[jm + i] = CommonParallel.Aggregate(0, rowsR, k => q[im + k] * column[k]);
+ });
}
- else
- {
- var sda = da / scale;
- var sdb = db / scale;
- r = scale * Math.Sqrt((sda * sda) + (sdb * sdb));
- if (roe < 0.0)
- {
- r = -r;
- }
- c = da / r;
- s = db / r;
- z = 1.0;
- if (absda > absdb)
+ // Solve R*X = Y;
+ for (var k = columnsR - 1; k >= 0; k--)
+ {
+ var km = k * rowsR;
+ for (var j = 0; j < columnsB; j++)
{
- z = s;
+ sol[(j * rowsR) + k] /= r[km + k];
}
- if (absdb >= absda && c != 0.0)
+ for (var i = 0; i < k; i++)
{
- z = 1.0 / c;
+ for (var j = 0; j < columnsB; j++)
+ {
+ var jm = j * rowsR;
+ sol[jm + i] -= sol[jm + k] * r[km + i];
+ }
}
}
- da = r;
- db = z;
+ // Fill result matrix
+ CommonParallel.For(
+ 0,
+ columnsR,
+ row =>
+ {
+ for (var col = 0; col < columnsB; col++)
+ {
+ x[(col * columnsR) + row] = sol[row + (col * rowsR)];
+ }
+ });
}
///
- /// Solves A*X=B for X using the singular value decomposition of A.
+ /// Computes the singular value decomposition of A.
///
+ /// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
- /// On exit U contains the left singular vectors.
- /// On exit VT contains the transposed right singular vectors.
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- public void SvdSolve(double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x)
+ /// If is true, on exit U contains the left
+ /// singular vectors.
+ /// If is true, on exit VT contains the transposed
+ /// right singular vectors.
+ /// This is equivalent to the GESVD LAPACK routine.
+ public void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
- if (a == null)
+ if (a == null)
{
throw new ArgumentNullException("a");
}
@@ -3180,62 +4505,43 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("vt");
}
- if (b == null)
- {
- throw new ArgumentNullException("b");
- }
-
- if (x == null)
- {
- throw new ArgumentNullException("x");
- }
-
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (b.Length != aRows * bColumns)
- {
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
- }
-
- if (x.Length != aColumns * bColumns)
- {
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
- }
-
// TODO: Actually "work = new double[aRows]" is acceptable size of work array. I set size proposed in method description
- var work = new double[Math.Max((3 * Math.Min(aRows, aColumns)) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns))];
- SvdSolve(a, aRows, aColumns, s, u, vt, b, bColumns, x, work);
+ var work = new float[Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA))];
+ SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
///
- /// Solves A*X=B for X using the singular value decomposition of A.
+ /// Computes the singular value decomposition of A.
///
+ /// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
- /// On exit U contains the left singular vectors.
- /// On exit VT contains the transposed right singular vectors.
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
+ /// If is true, on exit U contains the left
+ /// singular vectors.
+ /// If is true, on exit VT contains the transposed
+ /// right singular vectors.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x, double[] work)
+ /// This is equivalent to the GESVD LAPACK routine.
+ public void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
{
if (a == null)
{
@@ -3257,1129 +4563,966 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("vt");
}
- if (b == null)
- {
- throw new ArgumentNullException("b");
- }
-
- if (x == null)
+ if (work == null)
{
- throw new ArgumentNullException("x");
+ throw new ArgumentNullException("work");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (b.Length != aRows * bColumns)
- {
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
- }
-
- if (x.Length != aColumns * bColumns)
- {
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
- }
-
if (work.Length == 0)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
- if (work.Length < aRows)
+ if (work.Length < rowsA)
{
- work[0] = aRows;
+ work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
- SingularValueDecomposition(true, a, aRows, aColumns, s, u, vt, work);
- SvdSolveFactored(aRows, aColumns, s, u, vt, b, bColumns, x);
- }
+ const int Maxiter = 1000;
- ///
- /// Solves A*X=B for X using a previously SVD decomposed matrix.
- ///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// The s values returned by .
- /// The left singular vectors returned by .
- /// The right singular vectors returned by .
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x)
- {
- if (s == null)
- {
- throw new ArgumentNullException("s");
- }
+ var e = new float[columnsA];
+ var v = new float[vt.Length];
+ var stemp = new float[Math.Min(rowsA + 1, columnsA)];
- if (u == null)
- {
- throw new ArgumentNullException("u");
- }
+ int i, j, l, lp1;
- if (vt == null)
- {
- throw new ArgumentNullException("vt");
- }
+ var cs = 0.0f;
+ var sn = 0.0f;
+ float t;
- if (b == null)
- {
- throw new ArgumentNullException("b");
- }
+ var ncu = rowsA;
- if (x == null)
+ // Reduce matrix to bidiagonal form, storing the diagonal elements
+ // in "s" and the super-diagonal elements in "e".
+ var nct = Math.Min(rowsA - 1, columnsA);
+ var nrt = Math.Max(0, Math.Min(columnsA - 2, rowsA));
+ var lu = Math.Max(nct, nrt);
+
+ for (l = 0; l < lu; l++)
{
- throw new ArgumentNullException("x");
+ lp1 = l + 1;
+ if (l < nct)
+ {
+ // Compute the transformation for the l-th column and
+ // place the l-th diagonal in vector s[l].
+ var l1 = l;
+ stemp[l] = (float)Math.Sqrt(CommonParallel.Aggregate(l, rowsA, i1 => (a[(l1 * rowsA) + i1] * a[(l1 * rowsA) + i1])));
+
+ if (stemp[l] != 0.0)
+ {
+ if (a[(l * rowsA) + l] != 0.0)
+ {
+ stemp[l] = Math.Abs(stemp[l]) * (a[(l * rowsA) + l] / Math.Abs(a[(l * rowsA) + l]));
+ }
+
+ // A part of column "l" of Matrix A from row "l" to end multiply by 1.0 / s[l]
+ for (i = l; i < rowsA; i++)
+ {
+ a[(l * rowsA) + i] = a[(l * rowsA) + i] * (1.0f / stemp[l]);
+ }
+
+ a[(l * rowsA) + l] = 1.0f + a[(l * rowsA) + l];
+ }
+
+ stemp[l] = -stemp[l];
+ }
+
+ for (j = lp1; j < columnsA; j++)
+ {
+ if (l < nct)
+ {
+ if (stemp[l] != 0.0)
+ {
+ // Apply the transformation.
+ t = 0.0f;
+ for (i = l; i < rowsA; i++)
+ {
+ t += a[(j * rowsA) + i] * a[(l * rowsA) + i];
+ }
+
+ t = -t / a[(l * rowsA) + l];
+
+ for (var ii = l; ii < rowsA; ii++)
+ {
+ a[(j * rowsA) + ii] += t * a[(l * rowsA) + ii];
+ }
+ }
+ }
+
+ // Place the l-th row of matrix into "e" for the
+ // subsequent calculation of the row transformation.
+ e[j] = a[(j * rowsA) + l];
+ }
+
+ if (computeVectors && l < nct)
+ {
+ // Place the transformation in "u" for subsequent back multiplication.
+ for (i = l; i < rowsA; i++)
+ {
+ u[(l * rowsA) + i] = a[(l * rowsA) + i];
+ }
+ }
+
+ if (l >= nrt)
+ {
+ continue;
+ }
+
+ // Compute the l-th row transformation and place the l-th super-diagonal in e(l).
+ var enorm = 0.0;
+ for (i = lp1; i < e.Length; i++)
+ {
+ enorm += e[i] * e[i];
+ }
+
+ e[l] = (float)Math.Sqrt(enorm);
+ if (e[l] != 0.0)
+ {
+ if (e[lp1] != 0.0)
+ {
+ e[l] = Math.Abs(e[l]) * (e[lp1] / Math.Abs(e[lp1]));
+ }
+
+ // Scale vector "e" from "lp1" by 1.0 / e[l]
+ for (i = lp1; i < e.Length; i++)
+ {
+ e[i] = e[i] * (1.0f / e[l]);
+ }
+
+ e[lp1] = 1.0f + e[lp1];
+ }
+
+ e[l] = -e[l];
+
+ if (lp1 < rowsA && e[l] != 0.0)
+ {
+ // Apply the transformation.
+ for (i = lp1; i < rowsA; i++)
+ {
+ work[i] = 0.0f;
+ }
+
+ for (j = lp1; j < columnsA; j++)
+ {
+ for (var ii = lp1; ii < rowsA; ii++)
+ {
+ work[ii] += e[j] * a[(j * rowsA) + ii];
+ }
+ }
+
+ for (j = lp1; j < columnsA; j++)
+ {
+ var ww = -e[j] / e[lp1];
+ for (var ii = lp1; ii < rowsA; ii++)
+ {
+ a[(j * rowsA) + ii] += ww * work[ii];
+ }
+ }
+ }
+
+ if (!computeVectors)
+ {
+ continue;
+ }
+
+ // Place the transformation in v for subsequent back multiplication.
+ for (i = lp1; i < columnsA; i++)
+ {
+ v[(l * columnsA) + i] = e[i];
+ }
}
- if (u.Length != aRows * aRows)
+ // Set up the final bidiagonal matrix or order m.
+ var m = Math.Min(columnsA, rowsA + 1);
+ var nctp1 = nct + 1;
+ var nrtp1 = nrt + 1;
+ if (nct < columnsA)
{
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
+ stemp[nctp1 - 1] = a[((nctp1 - 1) * rowsA) + (nctp1 - 1)];
}
- if (vt.Length != aColumns * aColumns)
+ if (rowsA < m)
{
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
+ stemp[m - 1] = 0.0f;
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (nrtp1 < m)
{
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
+ e[nrtp1 - 1] = a[((m - 1) * rowsA) + (nrtp1 - 1)];
}
- if (b.Length != aRows * bColumns)
+ e[m - 1] = 0.0f;
+
+ // If required, generate "u".
+ if (computeVectors)
{
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
- }
+ for (j = nctp1 - 1; j < ncu; j++)
+ {
+ for (i = 0; i < rowsA; i++)
+ {
+ u[(j * rowsA) + i] = 0.0f;
+ }
+
+ u[(j * rowsA) + j] = 1.0f;
+ }
+
+ for (l = nct - 1; l >= 0; l--)
+ {
+ if (stemp[l] != 0.0)
+ {
+ for (j = l + 1; j < ncu; j++)
+ {
+ t = 0.0f;
+ for (i = l; i < rowsA; i++)
+ {
+ t += u[(j * rowsA) + i] * u[(l * rowsA) + i];
+ }
+
+ t = -t / u[(l * rowsA) + l];
- if (x.Length != aColumns * bColumns)
- {
- throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
- }
+ for (var ii = l; ii < rowsA; ii++)
+ {
+ u[(j * rowsA) + ii] += t * u[(l * rowsA) + ii];
+ }
+ }
- var mn = Math.Min(aRows, aColumns);
- var tmp = new double[aColumns];
+ // A part of column "l" of matrix A from row "l" to end multiply by -1.0
+ for (i = l; i < rowsA; i++)
+ {
+ u[(l * rowsA) + i] = u[(l * rowsA) + i] * -1.0f;
+ }
- for (var k = 0; k < bColumns; k++)
- {
- for (var j = 0; j < aColumns; j++)
- {
- double value = 0;
- if (j < mn)
+ u[(l * rowsA) + l] = 1.0f + u[(l * rowsA) + l];
+ for (i = 0; i < l; i++)
+ {
+ u[(l * rowsA) + i] = 0.0f;
+ }
+ }
+ else
{
- for (var i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- value += u[(j * aRows) + i] * b[(k * aRows) + i];
+ u[(l * rowsA) + i] = 0.0f;
}
- value /= s[j];
+ u[(l * rowsA) + l] = 1.0f;
}
-
- tmp[j] = value;
}
+ }
- for (var j = 0; j < aColumns; j++)
+ // If it is required, generate v.
+ if (computeVectors)
+ {
+ for (l = columnsA - 1; l >= 0; l--)
{
- double value = 0;
- for (var i = 0; i < aColumns; i++)
+ lp1 = l + 1;
+ if (l < nrt)
{
- value += vt[(j * aColumns) + i] * tmp[i];
- }
-
- x[(k * aColumns) + j] = value;
- }
- }
- }
+ if (e[l] != 0.0)
+ {
+ for (j = lp1; j < columnsA; j++)
+ {
+ t = 0.0f;
+ for (i = lp1; i < columnsA; i++)
+ {
+ t += v[(j * columnsA) + i] * v[(l * columnsA) + i];
+ }
- #endregion
+ t = -t / v[(l * columnsA) + lp1];
+ for (var ii = l; ii < columnsA; ii++)
+ {
+ v[(j * columnsA) + ii] += t * v[(l * columnsA) + ii];
+ }
+ }
+ }
+ }
- #region ILinearAlgebraProvider Members
+ for (i = 0; i < columnsA; i++)
+ {
+ v[(l * columnsA) + i] = 0.0f;
+ }
- ///
- /// Adds a scaled vector to another: y += alpha*x.
- ///
- /// The vector to update.
- /// The value to scale by.
- /// The vector to add to .
- /// This equivalent to the AXPY BLAS routine.
- public void AddVectorToScaledVector(float[] y, float alpha, float[] x)
- {
- if (y == null)
- {
- throw new ArgumentNullException("y");
+ v[(l * columnsA) + l] = 1.0f;
+ }
}
- if (x == null)
+ // Transform "s" and "e" so that they are double
+ for (i = 0; i < m; i++)
{
- throw new ArgumentNullException("x");
- }
+ float r;
+ if (stemp[i] != 0.0)
+ {
+ t = stemp[i];
+ r = stemp[i] / t;
+ stemp[i] = t;
+ if (i < m - 1)
+ {
+ e[i] = e[i] / r;
+ }
- if (y.Length != x.Length)
- {
- throw new ArgumentException(Resources.ArgumentVectorsSameLength);
- }
+ if (computeVectors)
+ {
+ // A part of column "i" of matrix U from row 0 to end multiply by r
+ for (j = 0; j < rowsA; j++)
+ {
+ u[(i * rowsA) + j] = u[(i * rowsA) + j] * r;
+ }
+ }
+ }
- if (alpha == 0.0)
- {
- return;
- }
+ // Exit
+ if (i == m - 1)
+ {
+ break;
+ }
- if (alpha == 1.0)
- {
- CommonParallel.For(0, y.Length, i => y[i] += x[i]);
- }
- else
- {
- CommonParallel.For(0, y.Length, i => y[i] += alpha * x[i]);
- }
- }
+ if (e[i] == 0.0)
+ {
+ continue;
+ }
- ///
- /// Scales an array. Can be used to scale a vector and a matrix.
- ///
- /// The scalar.
- /// The values to scale.
- /// This is equivalent to the SCAL BLAS routine.
- public void ScaleArray(float alpha, float[] x)
- {
- if (x == null)
- {
- throw new ArgumentNullException("x");
- }
+ t = e[i];
+ r = t / e[i];
+ e[i] = t;
+ stemp[i + 1] = stemp[i + 1] * r;
+ if (!computeVectors)
+ {
+ continue;
+ }
- if (alpha == 1.0)
- {
- return;
+ // A part of column "i+1" of matrix VT from row 0 to end multiply by r
+ for (j = 0; j < columnsA; j++)
+ {
+ v[((i + 1) * columnsA) + j] = v[((i + 1) * columnsA) + j] * r;
+ }
}
- CommonParallel.For(0, x.Length, i => x[i] = alpha * x[i]);
- }
-
- ///
- /// Computes the dot product of x and y.
- ///
- /// The vector x.
- /// The vector y.
- /// The dot product of x and y.
- /// This is equivalent to the DOT BLAS routine.
- public float DotProduct(float[] x, float[] y)
- {
- if (y == null)
- {
- throw new ArgumentNullException("y");
- }
+ // Main iteration loop for the singular values.
+ var mn = m;
+ var iter = 0;
- if (x == null)
+ while (m > 0)
{
- throw new ArgumentNullException("x");
- }
+ // Quit if all the singular values have been found.
+ // If too many iterations have been performed throw exception.
+ if (iter >= Maxiter)
+ {
+ throw new ArgumentException(Resources.ConvergenceFailed);
+ }
- if (y.Length != x.Length)
- {
- throw new ArgumentException(Resources.ArgumentVectorsSameLength);
- }
+ // This section of the program inspects for negligible elements in the s and e arrays,
+ // on completion the variables kase and l are set as follows:
+ // kase = 1: if mS[m] and e[l-1] are negligible and l < m
+ // kase = 2: if mS[l] is negligible and l < m
+ // kase = 3: if e[l-1] is negligible, l < m, and mS[l, ..., mS[m] are not negligible (qr step).
+ // kase = 4: if e[m-1] is negligible (convergence).
+ double ztest;
+ double test;
+ for (l = m - 2; l >= 0; l--)
+ {
+ test = Math.Abs(stemp[l]) + Math.Abs(stemp[l + 1]);
+ ztest = test + Math.Abs(e[l]);
+ if (ztest.AlmostEqualInDecimalPlaces(test, 7))
+ {
+ e[l] = 0.0f;
+ break;
+ }
+ }
- return y.Select((t, i) => t * x[i]).Sum();
- }
+ int kase;
+ if (l == m - 2)
+ {
+ kase = 4;
+ }
+ else
+ {
+ int ls;
+ for (ls = m - 1; ls > l; ls--)
+ {
+ test = 0.0;
+ if (ls != m - 1)
+ {
+ test = test + Math.Abs(e[ls]);
+ }
- ///
- /// Does a point wise add of two arrays z = x + y. This can be used
- /// to add vectors or matrices.
- ///
- /// The array x.
- /// The array y.
- /// The result of the addition.
- /// There is no equivalent BLAS routine, but many libraries
- /// provide optimized (parallel and/or vectorized) versions of this
- /// routine.
- public void AddArrays(float[] x, float[] y, float[] result)
- {
- if (y == null)
- {
- throw new ArgumentNullException("y");
- }
+ if (ls != l + 1)
+ {
+ test = test + Math.Abs(e[ls - 1]);
+ }
- if (x == null)
- {
- throw new ArgumentNullException("x");
- }
+ ztest = test + Math.Abs(stemp[ls]);
+ if (ztest.AlmostEqualInDecimalPlaces(test, 7))
+ {
+ stemp[ls] = 0.0f;
+ break;
+ }
+ }
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
+ if (ls == l)
+ {
+ kase = 3;
+ }
+ else if (ls == m - 1)
+ {
+ kase = 1;
+ }
+ else
+ {
+ kase = 2;
+ l = ls;
+ }
+ }
- if (y.Length != x.Length || y.Length != result.Length)
- {
- throw new ArgumentException(Resources.ArgumentVectorsSameLength);
- }
+ l = l + 1;
- CommonParallel.For(0, y.Length, i => result[i] = x[i] + y[i]);
- }
+ // Perform the task indicated by kase.
+ int k;
+ float f;
+ switch (kase)
+ {
+ // Deflate negligible s[m].
+ case 1:
+ f = e[m - 2];
+ e[m - 2] = 0.0f;
+ float t1;
+ for (var kk = l; kk < m - 1; kk++)
+ {
+ k = m - 2 - kk + l;
+ t1 = stemp[k];
- ///
- /// Does a point wise subtraction of two arrays z = x - y. This can be used
- /// to subtract vectors or matrices.
- ///
- /// The array x.
- /// The array y.
- /// The result of the subtraction.
- /// There is no equivalent BLAS routine, but many libraries
- /// provide optimized (parallel and/or vectorized) versions of this
- /// routine.
- public void SubtractArrays(float[] x, float[] y, float[] result)
- {
- if (y == null)
- {
- throw new ArgumentNullException("y");
- }
+ Drotg(ref t1, ref f, ref cs, ref sn);
+ stemp[k] = t1;
+ if (k != l)
+ {
+ f = -sn * e[k - 1];
+ e[k - 1] = cs * e[k - 1];
+ }
- if (x == null)
- {
- throw new ArgumentNullException("x");
- }
+ if (computeVectors)
+ {
+ // Rotate
+ for (i = 0; i < columnsA; i++)
+ {
+ var z = (cs * v[(k * columnsA) + i]) + (sn * v[((m - 1) * columnsA) + i]);
+ v[((m - 1) * columnsA) + i] = (cs * v[((m - 1) * columnsA) + i]) - (sn * v[(k * columnsA) + i]);
+ v[(k * columnsA) + i] = z;
+ }
+ }
+ }
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
+ break;
- if (y.Length != x.Length || y.Length != result.Length)
- {
- throw new ArgumentException(Resources.ArgumentVectorsSameLength);
- }
+ // Split at negligible s[l].
+ case 2:
+ f = e[l - 1];
+ e[l - 1] = 0.0f;
+ for (k = l; k < m; k++)
+ {
+ t1 = stemp[k];
+ Drotg(ref t1, ref f, ref cs, ref sn);
+ stemp[k] = t1;
+ f = -sn * e[k];
+ e[k] = cs * e[k];
+ if (computeVectors)
+ {
+ // Rotate
+ for (i = 0; i < rowsA; i++)
+ {
+ var z = (cs * u[(k * rowsA) + i]) + (sn * u[((l - 1) * rowsA) + i]);
+ u[((l - 1) * rowsA) + i] = (cs * u[((l - 1) * rowsA) + i]) - (sn * u[(k * rowsA) + i]);
+ u[(k * rowsA) + i] = z;
+ }
+ }
+ }
- CommonParallel.For(0, y.Length, i => result[i] = x[i] - y[i]);
- }
+ break;
- ///
- /// Does a point wise multiplication of two arrays z = x * y. This can be used
- /// to multiple elements of vectors or matrices.
- ///
- /// The array x.
- /// The array y.
- /// The result of the point wise multiplication.
- /// There is no equivalent BLAS routine, but many libraries
- /// provide optimized (parallel and/or vectorized) versions of this
- /// routine.
- public void PointWiseMultiplyArrays(float[] x, float[] y, float[] result)
- {
- if (y == null)
- {
- throw new ArgumentNullException("y");
- }
+ // Perform one qr step.
+ case 3:
- if (x == null)
- {
- throw new ArgumentNullException("x");
- }
+ // calculate the shift.
+ var scale = 0.0f;
+ scale = Math.Max(scale, Math.Abs(stemp[m - 1]));
+ scale = Math.Max(scale, Math.Abs(stemp[m - 2]));
+ scale = Math.Max(scale, Math.Abs(e[m - 2]));
+ scale = Math.Max(scale, Math.Abs(stemp[l]));
+ scale = Math.Max(scale, Math.Abs(e[l]));
+ var sm = stemp[m - 1] / scale;
+ var smm1 = stemp[m - 2] / scale;
+ var emm1 = e[m - 2] / scale;
+ var sl = stemp[l] / scale;
+ var el = e[l] / scale;
+ var b = (((smm1 + sm) * (smm1 - sm)) + (emm1 * emm1)) / 2.0f;
+ var c = (sm * emm1) * (sm * emm1);
+ var shift = 0.0f;
+ if (b != 0.0 || c != 0.0)
+ {
+ shift = (float)Math.Sqrt((b * b) + c);
+ if (b < 0.0)
+ {
+ shift = -shift;
+ }
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
+ shift = c / (b + shift);
+ }
- if (y.Length != x.Length || y.Length != result.Length)
- {
- throw new ArgumentException(Resources.ArgumentVectorsSameLength);
- }
+ f = ((sl + sm) * (sl - sm)) + shift;
+ var g = sl * el;
- CommonParallel.For(0, y.Length, i => result[i] = x[i] * y[i]);
- }
+ // Chase zeros
+ for (k = l; k < m - 1; k++)
+ {
+ Drotg(ref f, ref g, ref cs, ref sn);
+ if (k != l)
+ {
+ e[k - 1] = f;
+ }
- public float MatrixNorm(Norm norm, int rows, int columns, float[] matrix)
- {
- throw new NotImplementedException();
- }
+ f = (cs * stemp[k]) + (sn * e[k]);
+ e[k] = (cs * e[k]) - (sn * stemp[k]);
+ g = sn * stemp[k + 1];
+ stemp[k + 1] = cs * stemp[k + 1];
+ if (computeVectors)
+ {
+ for (i = 0; i < columnsA; i++)
+ {
+ var z = (cs * v[(k * columnsA) + i]) + (sn * v[((k + 1) * columnsA) + i]);
+ v[((k + 1) * columnsA) + i] = (cs * v[((k + 1) * columnsA) + i]) - (sn * v[(k * columnsA) + i]);
+ v[(k * columnsA) + i] = z;
+ }
+ }
- public float MatrixNorm(Norm norm, int rows, int columns, float[] matrix, float[] work)
- {
- throw new NotImplementedException();
- }
+ Drotg(ref f, ref g, ref cs, ref sn);
+ stemp[k] = f;
+ f = (cs * e[k]) + (sn * stemp[k + 1]);
+ stemp[k + 1] = -(sn * e[k]) + (cs * stemp[k + 1]);
+ g = sn * e[k + 1];
+ e[k + 1] = cs * e[k + 1];
+ if (computeVectors && k < rowsA)
+ {
+ for (i = 0; i < rowsA; i++)
+ {
+ var z = (cs * u[(k * rowsA) + i]) + (sn * u[((k + 1) * rowsA) + i]);
+ u[((k + 1) * rowsA) + i] = (cs * u[((k + 1) * rowsA) + i]) - (sn * u[(k * rowsA) + i]);
+ u[(k * rowsA) + i] = z;
+ }
+ }
+ }
- ///
- /// Multiples two matrices. result = x * y
- ///
- /// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
- /// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
- /// Where to store the result of the multiplication.
- /// This is a simplified version of the BLAS GEMM routine with alpha
- /// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(float[] x, int xRows, int xColumns, float[] y, int yRows, int yColumns, float[] result)
- {
- // First check some basic requirement on the parameters of the matrix multiplication.
- if (x == null)
- {
- throw new ArgumentNullException("x");
- }
+ e[m - 2] = f;
+ iter = iter + 1;
+ break;
- if (y == null)
- {
- throw new ArgumentNullException("y");
- }
+ // Convergence
+ case 4:
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
+ // Make the singular value positive
+ if (stemp[l] < 0.0)
+ {
+ stemp[l] = -stemp[l];
+ if (computeVectors)
+ {
+ // A part of column "l" of matrix VT from row 0 to end multiply by -1
+ for (i = 0; i < columnsA; i++)
+ {
+ v[(l * columnsA) + i] = v[(l * columnsA) + i] * -1.0f;
+ }
+ }
+ }
- if (xRows * xColumns != x.Length)
- {
- throw new ArgumentException("x.Length != xRows * xColumns");
- }
+ // Order the singular value.
+ while (l != mn - 1)
+ {
+ if (stemp[l] >= stemp[l + 1])
+ {
+ break;
+ }
- if (yRows * yColumns != y.Length)
- {
- throw new ArgumentException("y.Length != yRows * yColumns");
- }
+ t = stemp[l];
+ stemp[l] = stemp[l + 1];
+ stemp[l + 1] = t;
+ if (computeVectors && l < columnsA)
+ {
+ // Swap columns l, l + 1
+ for (i = 0; i < columnsA; i++)
+ {
+ var z = v[(l * columnsA) + i];
+ v[(l * columnsA) + i] = v[((l + 1) * columnsA) + i];
+ v[((l + 1) * columnsA) + i] = z;
+ }
+ }
- if (xColumns != yRows)
- {
- throw new ArgumentException("xColumns != yRows");
- }
+ if (computeVectors && l < rowsA)
+ {
+ // Swap columns l, l + 1
+ for (i = 0; i < rowsA; i++)
+ {
+ var z = u[(l * rowsA) + i];
+ u[(l * rowsA) + i] = u[((l + 1) * rowsA) + i];
+ u[((l + 1) * rowsA) + i] = z;
+ }
+ }
- if (xRows * yColumns != result.Length)
- {
- throw new ArgumentException("xRows * yColumns != result.Length");
- }
+ l = l + 1;
+ }
- // Check whether we will be overwriting any of our inputs and make copies if necessary.
- // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
- // as result, we can do it on a row wise basis. We should investigate this.
- float[] xdata;
- if (ReferenceEquals(x, result))
- {
- xdata = (float[])x.Clone();
- }
- else
- {
- xdata = x;
+ iter = 0;
+ m = m - 1;
+ break;
+ }
}
- float[] ydata;
- if (ReferenceEquals(y, result))
- {
- ydata = (float[])y.Clone();
- }
- else
+ if (computeVectors)
{
- ydata = y;
+ // Finally transpose "v" to get "vt" matrix
+ for (i = 0; i < columnsA; i++)
+ {
+ for (j = 0; j < columnsA; j++)
+ {
+ vt[(j * columnsA) + i] = v[(i * columnsA) + j];
+ }
+ }
}
- // Start the actual matrix multiplication.
- // TODO - For small matrices we should get rid of the parallelism because of startup costs.
- // Perhaps the following implementations would be a good one
- // http://blog.feradz.com/2009/01/cache-efficient-matrix-multiplication/
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0f, xdata, xRows, xColumns, ydata, yRows, yColumns, 0.0f, result);
+ // 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.
+ // We should port lapack's svd routine to remove this problem.
+ Buffer.BlockCopy(stemp, 0, s, 0, Math.Min(rowsA, columnsA) * Constants.SizeOfFloat);
+
+ // 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] = rowsA;
}
///
- /// Multiplies two matrices and updates another with the result. c = alpha*op(a)*op(b) + beta*c
+ /// Given the Cartesian coordinates (da, db) of a point p, these fucntion return the parameters da, db, c, and s
+ /// associated with the Givens rotation that zeros the y-coordinate of the point.
///
- /// How to transpose the matrix.
- /// How to transpose the matrix.
- /// The value to scale matrix.
- /// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
- /// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
- /// The value to scale the matrix.
- /// The c matrix.
- public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, float alpha, float[] a,
- int aRows, int aColumns, float[] b, int bRows, int bColumns, float beta, float[] c)
+ /// Provides the x-coordinate of the point p. On exit contains the parameter r associated with the Givens rotation
+ /// Provides the y-coordinate of the point p. On exit contains the parameter z associated with the Givens rotation
+ /// Contains the parameter c associated with the Givens rotation
+ /// Contains the parameter s associated with the Givens rotation
+ /// This is equivalent to the DROTG LAPACK routine.
+ private static void Drotg(ref float da, ref float db, ref float c, ref float s)
{
- // Choose nonsensical values for the number of rows and columns in c; fill them in depending
- // on the operations on a and b.
- var cRows = -1;
- var cColumns = -1;
+ float r, z;
- // First check some basic requirement on the parameters of the matrix multiplication.
- if (a == null)
+ var roe = db;
+ var absda = Math.Abs(da);
+ var absdb = Math.Abs(db);
+ if (absda > absdb)
{
- throw new ArgumentNullException("a");
+ roe = da;
}
- if (b == null)
+ var scale = absda + absdb;
+ if (scale == 0.0)
{
- throw new ArgumentNullException("b");
+ c = 1.0f;
+ s = 0.0f;
+ r = 0.0f;
+ z = 0.0f;
}
-
- if ((int)transposeA > 111 && (int)transposeB > 111)
+ else
{
- if (aRows != bColumns)
- {
- throw new ArgumentOutOfRangeException();
- }
-
- if (aColumns * bRows != c.Length)
+ var sda = da / scale;
+ var sdb = db / scale;
+ r = scale * (float)Math.Sqrt((sda * sda) + (sdb * sdb));
+ if (roe < 0.0)
{
- throw new ArgumentOutOfRangeException();
+ r = -r;
}
- cRows = aColumns;
- cColumns = bRows;
- }
- else if ((int)transposeA > 111)
- {
- if (aRows != bRows)
+ c = da / r;
+ s = db / r;
+ z = 1.0f;
+ if (absda > absdb)
{
- throw new ArgumentOutOfRangeException();
+ z = s;
}
- if (aColumns * bColumns != c.Length)
+ if (absdb >= absda && c != 0.0)
{
- throw new ArgumentOutOfRangeException();
+ z = 1.0f / c;
}
-
- cRows = aColumns;
- cColumns = bColumns;
}
- else if ((int)transposeB > 111)
- {
- if (aColumns != bColumns)
- {
- throw new ArgumentOutOfRangeException();
- }
- if (aRows * bRows != c.Length)
- {
- throw new ArgumentOutOfRangeException();
- }
+ da = r;
+ db = z;
+ }
- cRows = aRows;
- cColumns = bRows;
- }
- else
+ ///
+ /// Solves A*X=B for X using the singular value decomposition of A.
+ ///
+ /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// The singular values of A in ascending value.
+ /// On exit U contains the left singular vectors.
+ /// On exit VT contains the transposed right singular vectors.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ public void SvdSolve(float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x)
+ {
+ if (a == null)
{
- if (aColumns != bRows)
- {
- throw new ArgumentOutOfRangeException();
- }
-
- if (aRows * bColumns != c.Length)
- {
- throw new ArgumentOutOfRangeException();
- }
-
- cRows = aRows;
- cColumns = bColumns;
+ throw new ArgumentNullException("a");
}
- if (alpha == 0.0 && beta == 0.0)
+ if (s == null)
{
- Array.Clear(c, 0, c.Length);
- return;
+ throw new ArgumentNullException("s");
}
-
- // Check whether we will be overwriting any of our inputs and make copies if necessary.
- // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
- // as result, we can do it on a row wise basis. We should investigate this.
- float[] adata;
- if (ReferenceEquals(a, c))
+ if (u == null)
{
- adata = (float[])a.Clone();
+ throw new ArgumentNullException("u");
}
- else
+
+ if (vt == null)
{
- adata = a;
+ throw new ArgumentNullException("vt");
}
- float[] bdata;
- if (ReferenceEquals(b, c))
+ if (b == null)
{
- bdata = (float[])b.Clone();
+ throw new ArgumentNullException("b");
}
- else
+
+ if (x == null)
{
- bdata = b;
+ throw new ArgumentNullException("x");
}
- if (alpha == 1.0)
+ if (u.Length != rowsA * rowsA)
{
- if (beta == 0.0)
- {
- if ((int)transposeA > 111 && (int)transposeB > 111)
- {
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- float s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
- }
- else if ((int)transposeA > 111)
- {
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- float s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s;
- }
- });
- }
- else if ((int)transposeB > 111)
- {
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- float s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
- }
- else
- {
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- float s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s;
- }
- });
- }
- }
- else
- {
- if ((int)transposeA > 111 && (int)transposeB > 111)
- {
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- float s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + s;
- }
- });
- }
- else if ((int)transposeA > 111)
- {
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- float s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
- }
- else if ((int)transposeB > 111)
- {
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- float s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s + c[jIndex + i] * beta;
- }
- });
- }
- else
- {
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- float s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
- }
- }
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- else
- {
- if ((int)transposeA > 111 && (int)transposeB > 111)
- {
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- float s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + alpha * s;
- }
- });
- }
- else if ((int)transposeA > 111)
- {
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- float s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
- }
- else if ((int)transposeB > 111)
- {
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- float s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = alpha * s + c[jIndex + i] * beta;
- }
- });
- }
- else
- {
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- float s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
- }
+ if (vt.Length != columnsA * columnsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- }
-
- ///
- /// Computes the LUP factorization of A. P*A = L*U.
- ///
- /// An by matrix. The matrix is overwritten with the
- /// the LU factorization on exit. The lower triangular factor L is stored in under the diagonal of (the diagonal is always 1.0
- /// for the L factor). The upper triangular factor U is stored on and above the diagonal of .
- /// The order of the square matrix .
- /// On exit, it contains the pivot indices. The size of the array must be .
- /// This is equivalent to the GETRF LAPACK routine.
- public void LUFactor(float[] data, int order, int[] ipiv)
- {
- throw new NotImplementedException();
- }
- ///
- /// Computes the inverse of matrix using LU factorization.
- ///
- /// The N by N matrix to invert. Contains the inverse On exit.
- /// The order of the square matrix .
- /// This is equivalent to the GETRF and GETRI LAPACK routines.
- public void LUInverse(float[] a, int order)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Computes the inverse of a previously factored matrix.
- ///
- /// The LU factored N by N matrix. Contains the inverse On exit.
- /// The order of the square matrix .
- /// The pivot indices of .
- /// This is equivalent to the GETRI LAPACK routine.
- public void LUInverseFactored(float[] a, int order, int[] ipiv)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Computes the inverse of matrix using LU factorization.
- ///
- /// The N by N matrix to invert. Contains the inverse On exit.
- /// The order of the square matrix .
- /// The work array. The array must have a length of at least N,
- /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
- /// work size value.
- /// This is equivalent to the GETRF and GETRI LAPACK routines.
- public void LUInverse(float[] a, int order, float[] work)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Computes the inverse of a previously factored matrix.
- ///
- /// The LU factored N by N matrix. Contains the inverse On exit.
- /// The order of the square matrix .
- /// The pivot indices of .
- /// The work array. The array must have a length of at least N,
- /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
- /// work size value.
- /// This is equivalent to the GETRI LAPACK routine.
- public void LUInverseFactored(float[] a, int order, int[] ipiv, float[] work)
- {
- throw new NotImplementedException();
- }
-
- public void LUSolve(int columnsOfB, float[] a, int order, float[] b)
- {
- throw new NotImplementedException();
- }
-
- public void LUSolveFactored(int columnsOfB, float[] a, int order, int[] ipiv, float[] b)
- {
- throw new NotImplementedException();
- }
+ if (s.Length != Math.Min(rowsA, columnsA))
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
+ }
- public void LUSolve(Transpose transposeA, int columnsOfB, float[] a, int order, float[] b)
- {
- throw new NotImplementedException();
- }
+ if (b.Length != rowsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
- public void LUSolveFactored(Transpose transposeA, int columnsOfB, float[] a, int order, int[] ipiv, float[] b)
- {
- throw new NotImplementedException();
+ if (x.Length != columnsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ // TODO: Actually "work = new double[aRows]" is acceptable size of work array. I set size proposed in method description
+ var work = new float[Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA))];
+ SvdSolve(a, rowsA, columnsA, s, u, vt, b, columnsB, x, work);
}
///
- /// Computes the Cholesky factorization of A.
+ /// Solves A*X=B for X using the singular value decomposition of A.
///
- /// On entry, a square, positive definite matrix. On exit, the matrix is overwritten with the
- /// the Cholesky factorization.
- /// The number of rows or columns in the matrix.
- /// This is equivalent to the POTRF LAPACK routine.
- public void CholeskyFactor(float[] a, int order)
+ /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// The singular values of A in ascending value.
+ /// On exit U contains the left singular vectors.
+ /// On exit VT contains the transposed right singular vectors.
+ /// The B matrix.
+ /// The number of columns of B.
+ /// On exit, the solution matrix.
+ /// The work array. For real matrices, the work array should be at least
+ /// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
+ /// On exit, work[0] contains the optimal work size value.
+ public void SvdSolve(float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x, float[] work)
{
- var factor = new float[a.Length];
+ if (a == null)
+ {
+ throw new ArgumentNullException("a");
+ }
- for (var j = 0; j < order; j++)
+ if (s == null)
{
- var d = 0.0F;
- int index;
- for (var k = 0; k < j; k++)
- {
- var s = 0.0F;
- int i;
- for (i = 0; i < k; i++)
- {
- s += factor[i * order + k] * factor[i * order + j];
- }
+ throw new ArgumentNullException("s");
+ }
- var tmp = k * order;
- index = tmp + j;
- factor[index] = s = (a[index] - s) / factor[tmp + k];
- d += s * s;
- }
+ if (u == null)
+ {
+ throw new ArgumentNullException("u");
+ }
- index = j * order + j;
- d = a[index] - d;
- if (d <= 0.0F)
- {
- throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
- }
+ if (vt == null)
+ {
+ throw new ArgumentNullException("vt");
+ }
- factor[index] = (float)Math.Sqrt(d);
- for (var k = j + 1; k < order; k++)
- {
- factor[k * order + j] = 0.0F;
- }
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
}
- Buffer.BlockCopy(factor, 0, a, 0, factor.Length * Constants.SizeOfFloat);
- }
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
- ///
- /// Solves A*X=B for X using Cholesky factorization.
- ///
- /// The square, positive definite matrix A.
- /// The number of rows and columns in A.
- /// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
- /// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(float[] a, int aOrder, float[] b, int bRows, int bColumns)
- {
- throw new NotImplementedException();
- }
+ if (u.Length != rowsA * rowsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
+ }
- ///
- /// Solves A*X=B for X using a previously factored A matrix.
- ///
- /// The square, positive definite matrix A.
- /// The number of rows and columns in A.
- /// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
- /// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(float[] a, int aOrder, float[] b, int bRows, int bColumns)
- {
- throw new NotImplementedException();
- }
+ if (vt.Length != columnsA * columnsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
+ }
- ///
- /// Computes the QR factorization of A.
- ///
- /// On entry, it is the M by N A matrix to factor. On exit,
- /// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// On exit, A M by M matrix that holds the Q matrix of the
- /// QR factorization.
- /// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(float[] r, int rRows, int rColumns, float[] q)
- {
- throw new NotImplementedException();
- }
+ if (s.Length != Math.Min(rowsA, columnsA))
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
+ }
- ///
- /// Computes the QR factorization of A.
- ///
- /// On entry, it is the M by N A matrix to factor. On exit,
- /// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// On exit, A M by M matrix that holds the Q matrix of the
- /// QR factorization.
- /// The work array. The array must have a length of at least N,
- /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
- /// work size value.
- /// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(float[] r, int rRows, int rColumns, float[] q, float[] work)
- {
- throw new NotImplementedException();
- }
+ if (b.Length != rowsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
- ///
- /// Solves A*X=B for X using QR factorization of A.
- ///
- /// On entry, it is the M by N A matrix to factor. On exit,
- /// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// On exit, A M by M matrix that holds the Q matrix of the
- /// QR factorization.
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- public void QRSolve(float[] r, int rRows, int rColumns, float[] q, float[] b, int bColumns, float[] x)
- {
- throw new NotImplementedException();
- }
+ if (x.Length != columnsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
- ///
- /// Solves A*X=B for X using QR factorization of A.
- ///
- /// On entry, it is the M by N A matrix to factor. On exit,
- /// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// On exit, A M by M matrix that holds the Q matrix of the
- /// QR factorization.
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- /// The work array. The array must have a length of at least N,
- /// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
- /// work size value.
- public void QRSolve(float[] r, int rRows, int rColumns, float[] q, float[] b, int bColumns, float[] x, float[] work)
- {
- throw new NotImplementedException();
+ if (work.Length == 0)
+ {
+ throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
+ }
+
+ if (work.Length < rowsA)
+ {
+ work[0] = rowsA;
+ throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
+ }
+
+ SingularValueDecomposition(true, a, rowsA, columnsA, s, u, vt, work);
+ SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
///
- /// Solves A*X=B for X using a previously QR factored matrix.
+ /// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The Q matrix obtained by calling .
- /// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
+ /// The s values returned by .
+ /// The left singular vectors returned by .
+ /// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(float[] q, float[] r, int rRows, int rColumns, float[] b, int bColumns, float[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x)
{
- throw new NotImplementedException();
- }
+ if (s == null)
+ {
+ throw new ArgumentNullException("s");
+ }
- ///
- /// Computes the singular value decomposition of A.
- ///
- /// Compute the singular U and VT vectors or not.
- /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// The singular values of A in ascending value.
- /// If is true, on exit U contains the left
- /// singular vectors.
- /// If is true, on exit VT contains the transposed
- /// right singular vectors.
- /// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt)
- {
- throw new NotImplementedException();
- }
+ if (u == null)
+ {
+ throw new ArgumentNullException("u");
+ }
- ///
- /// Computes the singular value decomposition of A.
- ///
- /// Compute the singular U and VT vectors or not.
- /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// The singular values of A in ascending value.
- /// If is true, on exit U contains the left
- /// singular vectors.
- /// If is true, on exit VT contains the transposed
- /// right singular vectors.
- /// The work array. For real matrices, the work array should be at least
- /// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
- /// On exit, work[0] contains the optimal work size value.
- /// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] work)
- {
- throw new NotImplementedException();
- }
+ if (vt == null)
+ {
+ throw new ArgumentNullException("vt");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("b");
+ }
+
+ if (x == null)
+ {
+ throw new ArgumentNullException("x");
+ }
+
+ if (u.Length != rowsA * rowsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
+ }
+
+ if (vt.Length != columnsA * columnsA)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
+ }
+
+ if (s.Length != Math.Min(rowsA, columnsA))
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
+ }
+
+ if (b.Length != rowsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ if (x.Length != columnsA * columnsB)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
+ }
+
+ var mn = Math.Min(rowsA, columnsA);
+ var tmp = new float[columnsA];
+
+ for (var k = 0; k < columnsB; k++)
+ {
+ for (var j = 0; j < columnsA; j++)
+ {
+ float value = 0;
+ if (j < mn)
+ {
+ for (var i = 0; i < rowsA; i++)
+ {
+ value += u[(j * rowsA) + i] * b[(k * rowsA) + i];
+ }
- ///
- /// Solves A*X=B for X using the singular value decomposition of A.
- ///
- /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// The singular values of A in ascending value.
- /// On exit U contains the left singular vectors.
- /// On exit VT contains the transposed right singular vectors.
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- public void SvdSolve(float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x)
- {
- throw new NotImplementedException();
- }
+ value /= s[j];
+ }
- ///
- /// Solves A*X=B for X using the singular value decomposition of A.
- ///
- /// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// The singular values of A in ascending value.
- /// On exit U contains the left singular vectors.
- /// On exit VT contains the transposed right singular vectors.
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- /// The work array. For real matrices, the work array should be at least
- /// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
- /// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x, float[] work)
- {
- throw new NotImplementedException();
- }
+ tmp[j] = value;
+ }
- ///
- /// Solves A*X=B for X using a previously SVD decomposed matrix.
- ///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
- /// The s values returned by .
- /// The left singular vectors returned by .
- /// The right singular vectors returned by .
- /// The B matrix.
- /// The number of columns of B.
- /// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x)
- {
- throw new NotImplementedException();
+ for (var j = 0; j < columnsA; j++)
+ {
+ float value = 0;
+ for (var i = 0; i < columnsA; i++)
+ {
+ value += vt[(j * columnsA) + i] * tmp[i];
+ }
+
+ x[(k * columnsA) + j] = value;
+ }
+ }
}
#endregion
@@ -4470,14 +5613,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
- var d = new Complex(0.0, 0.0);
-
- for (var i = 0; i < y.Length; i++)
- {
- d += y[i] * x[i];
- }
-
- return d;
+ return CommonParallel.Aggregate(0, y.Length, index => y[index] * x[index]);
}
///
@@ -4585,11 +5721,33 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
CommonParallel.For(0, y.Length, i => result[i] = x[i] * y[i]);
}
+ ///
+ /// Computes the requested of the matrix.
+ ///
+ /// The type of norm to compute.
+ /// The number of rows.
+ /// The number of columns.
+ /// The matrix to compute the norm from.
+ ///
+ /// The requested of the matrix.
+ ///
public Complex MatrixNorm(Norm norm, int rows, int columns, Complex[] matrix)
{
throw new NotImplementedException();
}
+ ///
+ /// Computes the requested of the matrix.
+ ///
+ /// The type of norm to compute.
+ /// The number of rows.
+ /// The number of columns.
+ /// The matrix to compute the norm from.
+ /// The work array. Only used when
+ /// and needs to be have a length of at least M (number of rows of .
+ ///
+ /// The requested of the matrix.
+ ///
public Complex MatrixNorm(Norm norm, int rows, int columns, Complex[] matrix, Complex[] work)
{
throw new NotImplementedException();
@@ -4599,15 +5757,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(Complex[] x, int xRows, int xColumns, Complex[] y, int yRows, int yColumns, Complex[] result)
+ public void MatrixMultiply(Complex[] x, int rowsX, int columnsX, Complex[] y, int rowsY, int columnsY, Complex[] result)
{
// First check some basic requirement on the parameters of the matrix multiplication.
if (x == null)
@@ -4625,22 +5783,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("result");
}
- if (xRows * xColumns != x.Length)
+ if (rowsX * columnsX != x.Length)
{
throw new ArgumentException("x.Length != xRows * xColumns");
}
- if (yRows * yColumns != y.Length)
+ if (rowsY * columnsY != y.Length)
{
throw new ArgumentException("y.Length != yRows * yColumns");
}
- if (xColumns != yRows)
+ if (columnsX != rowsY)
{
throw new ArgumentException("xColumns != yRows");
}
- if (xRows * yColumns != result.Length)
+ if (rowsX * columnsY != result.Length)
{
throw new ArgumentException("xRows * yColumns != result.Length");
}
@@ -4672,7 +5830,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// TODO - For small matrices we should get rid of the parallelism because of startup costs.
// Perhaps the following implementations would be a good one
// http://blog.feradz.com/2009/01/cache-efficient-matrix-multiplication/
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex.One, xdata, xRows, xColumns, ydata, yRows, yColumns, Complex.Zero, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex.One, xdata, rowsX, columnsX, ydata, rowsY, columnsY, Complex.Zero, result);
}
///
@@ -4682,20 +5840,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
- public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex alpha, Complex[] a,
- int aRows, int aColumns, Complex[] b, int bRows, int bColumns, Complex beta, Complex[] c)
+ public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex alpha, Complex[] a, int rowsA, int columnsA, Complex[] b, int rowsB, int columnsB, Complex beta, Complex[] c)
{
- // Choose nonsensical values for the number of rows and columns in c; fill them in depending
+ // Choose nonsensical values for the number of rows in c; fill them in depending
// on the operations on a and b.
- var cRows = -1;
- var cColumns = -1;
+ int rowsC;
// First check some basic requirement on the parameters of the matrix multiplication.
if (a == null)
@@ -4710,63 +5866,59 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- if (aRows != bColumns)
+ if (rowsA != columnsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aColumns * bRows != c.Length)
+ if (columnsA * rowsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aColumns;
- cColumns = bRows;
+ rowsC = columnsA;
}
else if ((int)transposeA > 111)
{
- if (aRows != bRows)
+ if (rowsA != rowsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aColumns * bColumns != c.Length)
+ if (columnsA * columnsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aColumns;
- cColumns = bColumns;
+ rowsC = columnsA;
}
else if ((int)transposeB > 111)
{
- if (aColumns != bColumns)
+ if (columnsA != columnsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aRows * bRows != c.Length)
+ if (rowsA * rowsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aRows;
- cColumns = bRows;
+ rowsC = rowsA;
}
else
{
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aRows * bColumns != c.Length)
+ if (rowsA * columnsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aRows;
- cColumns = bColumns;
+ rowsC = rowsA;
}
if (alpha == 0.0 && beta == 0.0)
@@ -4775,7 +5927,6 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
return;
}
-
// Check whether we will be overwriting any of our inputs and make copies if necessary.
// TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
// as result, we can do it on a row wise basis. We should investigate this.
@@ -4805,150 +5956,174 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- Complex s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- Complex s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s;
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = s;
- }
- });
+ c[jcIndex + i] = s;
+ }
+ });
}
}
else
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- Complex s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + s;
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- Complex s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s + c[jIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s + (c[jIndex + i] * beta);
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
}
}
}
@@ -4956,75 +6131,87 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- Complex s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + alpha * s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + (alpha * s);
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- Complex s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = alpha * s + c[jIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (alpha * s) + (c[jIndex + i] * beta);
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
}
}
}
@@ -5066,7 +6253,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
ipiv[i] = i;
}
- var vLUcolj = new Complex[order];
+ var vecLUcolj = new Complex[order];
// Outer loop.
for (var j = 0; j < order; j++)
@@ -5077,7 +6264,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Make a copy of the j-th column to localize references.
for (var i = 0; i < order; i++)
{
- vLUcolj[i] = data[indexj + i];
+ vecLUcolj[i] = data[indexj + i];
}
// Apply previous transformations.
@@ -5088,17 +6275,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var s = Complex.Zero;
for (var k = 0; k < kmax; k++)
{
- s += data[k * order + i] * vLUcolj[k];
+ s += data[(k * order) + i] * vecLUcolj[k];
}
- data[indexj + i] = vLUcolj[i] -= s;
+ data[indexj + i] = vecLUcolj[i] -= s;
}
// Find pivot and exchange if necessary.
var p = j;
for (var i = j + 1; i < order; i++)
{
- if (vLUcolj[i].Magnitude > vLUcolj[p].Magnitude)
+ if (vecLUcolj[i].Magnitude > vecLUcolj[p].Magnitude)
{
p = i;
}
@@ -5185,7 +6372,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var inverse = new Complex[a.Length];
for (var i = 0; i < order; i++)
{
- inverse[i + order * i] = Complex.One;
+ inverse[i + (order * i)] = Complex.One;
}
LUSolveFactored(order, a, order, ipiv, inverse);
@@ -5334,10 +6521,10 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Solve U*X = Y;
for (var k = order - 1; k >= 0; k--)
{
- var korder = k + k * order;
+ var korder = k + (k * order);
for (var j = 0; j < columnsOfB; j++)
{
- b[k + j * order] /= a[korder];
+ b[k + (j * order)] /= a[korder];
}
korder = k * order;
@@ -5350,7 +6537,6 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
}
}
-
}
///
@@ -5486,7 +6672,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var s = Complex.Zero;
for (var k = 0; k < j; k++)
{
- s += a[k * order + i] * a[k * order + j].Conjugate();
+ s += a[(k * order) + i] * a[(k * order) + j].Conjugate();
}
var tmp = j * order;
@@ -5495,7 +6681,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
d += s * s.Conjugate();
}
- index = i * order + i;
+ index = (i * order) + i;
d = a[index] - d;
if (d.Real <= 0.0)
{
@@ -5505,7 +6691,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
a[index] = d.SquareRoot();
for (var k = i + 1; k < order; k++)
{
- a[k * order + i] = 0.0;
+ a[(k * order) + i] = 0.0;
}
}
}
@@ -5514,12 +6700,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(Complex[] a, int aOrder, Complex[] b, int bRows, int bColumns)
+ public void CholeskySolve(Complex[] a, int orderA, Complex[] b, int rowsB, int columnsB)
{
if (a == null)
{
@@ -5531,7 +6717,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("b");
}
- if (aOrder != bRows)
+ if (orderA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -5541,20 +6727,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
- CholeskyFactor(a, aOrder);
- CholeskySolveFactored(a, aOrder, b, bRows, bColumns);
+ CholeskyFactor(a, orderA);
+ CholeskySolveFactored(a, orderA, b, rowsB, columnsB);
}
///
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(Complex[] a, int aOrder, Complex[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(Complex[] a, int orderA, Complex[] b, int rowsB, int columnsB)
{
if (a == null)
{
@@ -5566,7 +6752,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("b");
}
- if (aOrder != bRows)
+ if (orderA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -5576,36 +6762,39 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
- CommonParallel.For(0, bColumns, c =>
- {
- var cindex = c * aOrder;
-
- // Solve L*Y = B;
- Complex sum;
- for (var i = 0; i < aOrder; i++)
+ CommonParallel.For(
+ 0,
+ columnsB,
+ c =>
{
- sum = b[cindex + i];
- for (var k = i - 1; k >= 0; k--)
+ var cindex = c * orderA;
+
+ // Solve L*Y = B;
+ Complex sum;
+ for (var i = 0; i < orderA; i++)
{
- sum -= a[k * aOrder + i] * b[cindex + k];
- }
+ sum = b[cindex + i];
+ for (var k = i - 1; k >= 0; k--)
+ {
+ sum -= a[(k * orderA) + i] * b[cindex + k];
+ }
- b[cindex + i] = sum / a[i * aOrder + i];
- }
+ b[cindex + i] = sum / a[(i * orderA) + i];
+ }
- // Solve L'*X = Y;
- for (var i = aOrder - 1; i >= 0; i--)
- {
- sum = b[cindex + i];
- var iindex = i * aOrder;
- for (var k = i + 1; k < aOrder; k++)
+ // Solve L'*X = Y;
+ for (var i = orderA - 1; i >= 0; i--)
{
- sum -= a[iindex + k].Conjugate() * b[cindex + k];
- }
+ 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];
- }
- });
+ b[cindex + i] = sum / a[iindex + i];
+ }
+ });
}
///
@@ -5613,12 +6802,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex[] r, int rRows, int rColumns, Complex[] q)
+ public void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q)
{
if (r == null)
{
@@ -5630,18 +6819,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- var work = new Complex[rRows * rRows];
- QRFactor(r, rRows, rColumns, q, work);
+ var work = new Complex[rowsR * rowsR];
+ QRFactor(r, rowsR, columnsR, q, work);
}
///
@@ -5649,15 +6838,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] work)
+ public void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] work)
{
if (r == null)
{
@@ -5674,37 +6863,37 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (work.Length < rRows * rRows)
+ if (work.Length < rowsR * rowsR)
{
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
- CommonParallel.For(0, rRows, i => q[(i * rRows) + i] = Complex.One);
+ CommonParallel.For(0, rowsR, i => q[(i * rowsR) + i] = Complex.One);
- var minmn = Math.Min(rRows, rColumns);
+ var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++)
{
- GenerateColumn(work, r, rRows, i, rRows - 1, i);
- ComputeQR(work, i, r, rRows, i, rRows - 1, i + 1, rColumns - 1);
+ GenerateColumn(work, r, rowsR, i, rowsR - 1, i);
+ ComputeQR(work, i, r, rowsR, i, rowsR - 1, i + 1, columnsR - 1);
}
for (var i = minmn - 1; i >= 0; i--)
{
- ComputeQR(work, i, q, rRows, i, rRows - 1, i, rRows - 1);
+ ComputeQR(work, i, q, rowsR, i, rowsR - 1, i, rowsR - 1);
}
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
}
#region QR Factor Helper functions
@@ -5772,8 +6961,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var norm = Complex.Zero;
for (var i = 0; i < rowEnd - rowStart + 1; ++i)
{
- var iIndex = tmp + i;
- norm += work[iIndex].Magnitude * work[iIndex].Magnitude;
+ var index1 = tmp + i;
+ norm += work[index1].Magnitude * work[index1].Magnitude;
}
norm = norm.SquareRoot();
@@ -5804,14 +6993,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] b, int bColumns, Complex[] x)
+ public void QRSolve(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] b, int columnsB, Complex[] x)
{
if (r == null)
{
@@ -5833,28 +7022,28 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (b.Length != rRows * bColumns)
+ if (b.Length != rowsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != rColumns * bColumns)
+ if (x.Length != columnsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
- var work = new Complex[rRows * rRows];
- QRSolve(r, rRows, rColumns, q, b, bColumns, x, work);
+ var work = new Complex[rowsR * rowsR];
+ QRSolve(r, rowsR, columnsR, q, b, columnsB, x, work);
}
///
@@ -5862,17 +7051,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] b, int bColumns, Complex[] x, Complex[] work)
+ public void QRSolve(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] b, int columnsB, Complex[] x, Complex[] work)
{
if (r == null)
{
@@ -5894,36 +7083,36 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (b.Length != rRows * bColumns)
+ if (b.Length != rowsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != rColumns * bColumns)
+ if (x.Length != columnsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
- if (work.Length < rRows * rRows)
+ if (work.Length < rowsR * rowsR)
{
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
- QRFactor(r, rRows, rColumns, q, work);
- QRSolveFactored(q, r, rRows, rColumns, b, bColumns, x);
+ QRFactor(r, rowsR, columnsR, q, work);
+ QRSolveFactored(q, r, rowsR, columnsR, b, columnsB, x);
- work[0] = rRows * rRows;
+ work[0] = rowsR * rowsR;
}
///
@@ -5931,12 +7120,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(Complex[] q, Complex[] r, int rRows, int rColumns, Complex[] b, int bColumns, Complex[] x)
+ public void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] b, int columnsB, Complex[] x)
{
if (r == null)
{
@@ -5958,22 +7147,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("q");
}
- if (r.Length != rRows * rColumns)
+ if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "r");
}
- if (q.Length != rRows * rRows)
+ if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "q");
}
- if (b.Length != rRows * bColumns)
+ if (b.Length != rowsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != rColumns * bColumns)
+ if (x.Length != columnsR * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
@@ -5984,35 +7173,35 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
CommonParallel.For(0, b.Length, index => sol[index] = b[index]);
// Compute Y = transpose(Q)*B
- var column = new Complex[rRows];
- for (var j = 0; j < bColumns; j++)
+ var column = new Complex[rowsR];
+ for (var j = 0; j < columnsB; j++)
{
- var jm = j * rRows;
- CommonParallel.For(0, rRows, k => column[k] = sol[jm + k]);
+ var jm = j * rowsR;
+ CommonParallel.For(0, rowsR, k => column[k] = sol[jm + k]);
CommonParallel.For(
0,
- rRows,
+ rowsR,
i =>
{
- var im = i * rRows;
- sol[jm + i] = CommonParallel.Aggregate(0, rRows, k => q[im + k].Conjugate() * column[k]);
+ var im = i * rowsR;
+ sol[jm + i] = CommonParallel.Aggregate(0, rowsR, k => q[im + k].Conjugate() * column[k]);
});
}
// Solve R*X = Y;
- for (var k = rColumns - 1; k >= 0; k--)
+ for (var k = columnsR - 1; k >= 0; k--)
{
- var km = k * rRows;
- for (var j = 0; j < bColumns; j++)
+ var km = k * rowsR;
+ for (var j = 0; j < columnsB; j++)
{
- sol[(j * rRows) + k] /= r[km + k];
+ sol[(j * rowsR) + k] /= r[km + k];
}
for (var i = 0; i < k; i++)
{
- for (var j = 0; j < bColumns; j++)
+ for (var j = 0; j < columnsB; j++)
{
- var jm = j * rRows;
+ var jm = j * rowsR;
sol[jm + i] -= sol[jm + k] * r[km + i];
}
}
@@ -6021,12 +7210,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Fill result matrix
CommonParallel.For(
0,
- rColumns,
+ columnsR,
row =>
{
- for (var col = 0; col < bColumns; col++)
+ for (var col = 0; col < columnsB; col++)
{
- x[(col * rColumns) + row] = sol[row + (col * rRows)];
+ x[(col * columnsR) + row] = sol[row + (col * rowsR)];
}
});
}
@@ -6036,15 +7225,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt)
+ public void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
@@ -6066,25 +7255,24 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("vt");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
// TODO: Actually "work = new double[aRows]" is acceptable size of work array. I set size proposed in method description
- var work = new Complex[Math.Max((3 * Math.Min(aRows, aColumns)) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns))];
- SingularValueDecomposition(computeVectors, a, aRows, aColumns, s, u, vt, work);
-
+ var work = new Complex[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
+ SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
///
@@ -6092,8 +7280,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -6103,7 +7291,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
+ public void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
{
if (a == null)
{
@@ -6130,17 +7318,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("work");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
@@ -6150,17 +7338,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
- if (work.Length < aRows)
+ if (work.Length < rowsA)
{
- work[0] = aRows;
+ work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
const int Maxiter = 1000;
- var e = new Complex[aColumns];
+ var e = new Complex[columnsA];
var v = new Complex[vt.Length];
- var stemp = new Complex[Math.Min(aRows + 1, aColumns)];
+ var stemp = new Complex[Math.Min(rowsA + 1, columnsA)];
int i, j, l, lp1;
@@ -6168,12 +7356,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
var sn = 0.0;
Complex t;
- var ncu = aRows;
+ var ncu = rowsA;
// Reduce matrix to bidiagonal form, storing the diagonal elements
// in "s" and the super-diagonal elements in "e".
- var nct = Math.Min(aRows - 1, aColumns);
- var nrt = Math.Max(0, Math.Min(aColumns - 2, aRows));
+ var nct = Math.Min(rowsA - 1, columnsA);
+ var nrt = Math.Max(0, Math.Min(columnsA - 2, rowsA));
var lu = Math.Max(nct, nrt);
for (l = 0; l < lu; l++)
@@ -6184,32 +7372,32 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// Compute the transformation for the l-th column and
// place the l-th diagonal in vector s[l].
var sum = 0.0;
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- sum += a[(l * aRows) + i].Magnitude * a[(l * aRows) + i].Magnitude;
+ sum += a[(l * rowsA) + i].Magnitude * a[(l * rowsA) + i].Magnitude;
}
stemp[l] = Math.Sqrt(sum);
if (stemp[l] != 0.0)
{
- if (a[(l * aRows) + l] != 0.0)
+ if (a[(l * rowsA) + l] != 0.0)
{
- stemp[l] = stemp[l].Magnitude * (a[(l * aRows) + l] / a[(l * aRows) + l].Magnitude);
+ stemp[l] = stemp[l].Magnitude * (a[(l * rowsA) + l] / a[(l * rowsA) + l].Magnitude);
}
// A part of column "l" of Matrix A from row "l" to end multiply by 1.0 / s[l]
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- a[(l * aRows) + i] = a[(l * aRows) + i] * (1.0 / stemp[l]);
+ a[(l * rowsA) + i] = a[(l * rowsA) + i] * (1.0 / stemp[l]);
}
- a[(l * aRows) + l] = 1.0 + a[(l * aRows) + l];
+ a[(l * rowsA) + l] = 1.0 + a[(l * rowsA) + l];
}
stemp[l] = -stemp[l];
}
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
if (l < nct)
{
@@ -6217,31 +7405,31 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
// Apply the transformation.
t = 0.0;
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- t += a[(l * aRows) + i].Conjugate() * a[(j * aRows) + i];
+ t += a[(l * rowsA) + i].Conjugate() * a[(j * rowsA) + i];
}
- t = -t / a[(l * aRows) + l];
+ t = -t / a[(l * rowsA) + l];
- for (var ii = l; ii < aRows; ii++)
+ for (var ii = l; ii < rowsA; ii++)
{
- a[(j * aRows) + ii] += t * a[(l * aRows) + ii];
+ a[(j * rowsA) + ii] += t * a[(l * rowsA) + ii];
}
}
}
// Place the l-th row of matrix into "e" for the
// subsequent calculation of the row transformation.
- e[j] = a[(j * aRows) + l].Conjugate();
+ e[j] = a[(j * rowsA) + l].Conjugate();
}
if (computeVectors && l < nct)
{
// Place the transformation in "u" for subsequent back multiplication.
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- u[(l * aRows) + i] = a[(l * aRows) + i];
+ u[(l * rowsA) + i] = a[(l * rowsA) + i];
}
}
@@ -6276,28 +7464,28 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
e[l] = -e[l].Conjugate();
- if (lp1 < aRows && e[l] != 0.0)
+ if (lp1 < rowsA && e[l] != 0.0)
{
// Apply the transformation.
- for (i = lp1; i < aRows; i++)
+ for (i = lp1; i < rowsA; i++)
{
work[i] = 0.0;
}
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
- for (var ii = lp1; ii < aRows; ii++)
+ for (var ii = lp1; ii < rowsA; ii++)
{
- work[ii] += e[j] * a[(j * aRows) + ii];
+ work[ii] += e[j] * a[(j * rowsA) + ii];
}
}
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
var ww = (-e[j] / e[lp1]).Conjugate();
- for (var ii = lp1; ii < aRows; ii++)
+ for (var ii = lp1; ii < rowsA; ii++)
{
- a[(j * aRows) + ii] += ww * work[ii];
+ a[(j * rowsA) + ii] += ww * work[ii];
}
}
}
@@ -6308,29 +7496,29 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
// Place the transformation in v for subsequent back multiplication.
- for (i = lp1; i < aColumns; i++)
+ for (i = lp1; i < columnsA; i++)
{
- v[(l * aColumns) + i] = e[i];
+ v[(l * columnsA) + i] = e[i];
}
}
// Set up the final bidiagonal matrix or order m.
- var m = Math.Min(aColumns, aRows + 1);
+ var m = Math.Min(columnsA, rowsA + 1);
var nctp1 = nct + 1;
var nrtp1 = nrt + 1;
- if (nct < aColumns)
+ if (nct < columnsA)
{
- stemp[nctp1 - 1] = a[((nctp1 - 1) * aRows) + (nctp1 - 1)];
+ stemp[nctp1 - 1] = a[((nctp1 - 1) * rowsA) + (nctp1 - 1)];
}
- if (aRows < m)
+ if (rowsA < m)
{
stemp[m - 1] = 0.0;
}
if (nrtp1 < m)
{
- e[nrtp1 - 1] = a[((m - 1) * aRows) + (nrtp1 - 1)];
+ e[nrtp1 - 1] = a[((m - 1) * rowsA) + (nrtp1 - 1)];
}
e[m - 1] = 0.0;
@@ -6340,12 +7528,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
for (j = nctp1 - 1; j < ncu; j++)
{
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- u[(j * aRows) + i] = 0.0;
+ u[(j * rowsA) + i] = 0.0;
}
- u[(j * aRows) + j] = 1.0;
+ u[(j * rowsA) + j] = 1.0;
}
for (l = nct - 1; l >= 0; l--)
@@ -6355,38 +7543,38 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
for (j = l + 1; j < ncu; j++)
{
t = 0.0;
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- t += u[(l * aRows) + i].Conjugate() * u[(j * aRows) + i];
+ t += u[(l * rowsA) + i].Conjugate() * u[(j * rowsA) + i];
}
- t = -t / u[(l * aRows) + l];
- for (var ii = l; ii < aRows; ii++)
+ t = -t / u[(l * rowsA) + l];
+ for (var ii = l; ii < rowsA; ii++)
{
- u[(j * aRows) + ii] += t * u[(l * aRows) + ii];
+ u[(j * rowsA) + ii] += t * u[(l * rowsA) + ii];
}
}
// A part of column "l" of matrix A from row "l" to end multiply by -1.0
- for (i = l; i < aRows; i++)
+ for (i = l; i < rowsA; i++)
{
- u[(l * aRows) + i] = u[(l * aRows) + i] * -1.0;
+ u[(l * rowsA) + i] = u[(l * rowsA) + i] * -1.0;
}
- u[(l * aRows) + l] = 1.0 + u[(l * aRows) + l];
+ u[(l * rowsA) + l] = 1.0 + u[(l * rowsA) + l];
for (i = 0; i < l; i++)
{
- u[(l * aRows) + i] = 0.0;
+ u[(l * rowsA) + i] = 0.0;
}
}
else
{
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- u[(l * aRows) + i] = 0.0;
+ u[(l * rowsA) + i] = 0.0;
}
- u[(l * aRows) + l] = 1.0;
+ u[(l * rowsA) + l] = 1.0;
}
}
}
@@ -6394,36 +7582,36 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// If it is required, generate v.
if (computeVectors)
{
- for (l = aColumns - 1; l >= 0; l--)
+ for (l = columnsA - 1; l >= 0; l--)
{
lp1 = l + 1;
if (l < nrt)
{
if (e[l] != 0.0)
{
- for (j = lp1; j < aColumns; j++)
+ for (j = lp1; j < columnsA; j++)
{
t = 0.0;
- for (i = lp1; i < aColumns; i++)
+ for (i = lp1; i < columnsA; i++)
{
- t += v[(l * aColumns) + i].Conjugate() * v[(j * aColumns) + i];
+ t += v[(l * columnsA) + i].Conjugate() * v[(j * columnsA) + i];
}
- t = -t / v[(l * aColumns) + lp1];
- for (var ii = l; ii < aColumns; ii++)
+ t = -t / v[(l * columnsA) + lp1];
+ for (var ii = l; ii < columnsA; ii++)
{
- v[(j * aColumns) + ii] += t * v[(l * aColumns) + ii];
+ v[(j * columnsA) + ii] += t * v[(l * columnsA) + ii];
}
}
}
}
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- v[(l * aColumns) + i] = 0.0;
+ v[(l * columnsA) + i] = 0.0;
}
- v[(l * aColumns) + l] = 1.0;
+ v[(l * columnsA) + l] = 1.0;
}
}
@@ -6444,9 +7632,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// A part of column "i" of matrix U from row 0 to end multiply by r
- for (j = 0; j < aRows; j++)
+ for (j = 0; j < rowsA; j++)
{
- u[(i * aRows) + j] = u[(i * aRows) + j] * r;
+ u[(i * rowsA) + j] = u[(i * rowsA) + j] * r;
}
}
}
@@ -6472,9 +7660,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
// A part of column "i+1" of matrix VT from row 0 to end multiply by r
- for (j = 0; j < aColumns; j++)
+ for (j = 0; j < columnsA; j++)
{
- v[((i + 1) * aColumns) + j] = v[((i + 1) * aColumns) + j] * r;
+ v[((i + 1) * columnsA) + j] = v[((i + 1) * columnsA) + j] * r;
}
}
@@ -6581,11 +7769,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// Rotate
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- var z = (cs * v[(k * aColumns) + i]) + (sn * v[((m - 1) * aColumns) + i]);
- v[((m - 1) * aColumns) + i] = (cs * v[((m - 1) * aColumns) + i]) - (sn * v[(k * aColumns) + i]);
- v[(k * aColumns) + i] = z;
+ var z = (cs * v[(k * columnsA) + i]) + (sn * v[((m - 1) * columnsA) + i]);
+ v[((m - 1) * columnsA) + i] = (cs * v[((m - 1) * columnsA) + i]) - (sn * v[(k * columnsA) + i]);
+ v[(k * columnsA) + i] = z;
}
}
}
@@ -6606,11 +7794,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// Rotate
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- var z = (cs * u[(k * aRows) + i]) + (sn * u[((l - 1) * aRows) + i]);
- u[((l - 1) * aRows) + i] = (cs * u[((l - 1) * aRows) + i]) - (sn * u[(k * aRows) + i]);
- u[(k * aRows) + i] = z;
+ var z = (cs * u[(k * rowsA) + i]) + (sn * u[((l - 1) * rowsA) + i]);
+ u[((l - 1) * rowsA) + i] = (cs * u[((l - 1) * rowsA) + i]) - (sn * u[(k * rowsA) + i]);
+ u[(k * rowsA) + i] = z;
}
}
}
@@ -6663,11 +7851,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
stemp[k + 1] = cs * stemp[k + 1];
if (computeVectors)
{
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- var z = (cs * v[(k * aColumns) + i]) + (sn * v[((k + 1) * aColumns) + i]);
- v[((k + 1) * aColumns) + i] = (cs * v[((k + 1) * aColumns) + i]) - (sn * v[(k * aColumns) + i]);
- v[(k * aColumns) + i] = z;
+ var z = (cs * v[(k * columnsA) + i]) + (sn * v[((k + 1) * columnsA) + i]);
+ v[((k + 1) * columnsA) + i] = (cs * v[((k + 1) * columnsA) + i]) - (sn * v[(k * columnsA) + i]);
+ v[(k * columnsA) + i] = z;
}
}
@@ -6677,13 +7865,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
stemp[k + 1] = -(sn * e[k]) + (cs * stemp[k + 1]);
g = sn * e[k + 1].Real;
e[k + 1] = cs * e[k + 1];
- if (computeVectors && k < aRows)
+ if (computeVectors && k < rowsA)
{
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- var z = (cs * u[(k * aRows) + i]) + (sn * u[((k + 1) * aRows) + i]);
- u[((k + 1) * aRows) + i] = (cs * u[((k + 1) * aRows) + i]) - (sn * u[(k * aRows) + i]);
- u[(k * aRows) + i] = z;
+ var z = (cs * u[(k * rowsA) + i]) + (sn * u[((k + 1) * rowsA) + i]);
+ u[((k + 1) * rowsA) + i] = (cs * u[((k + 1) * rowsA) + i]) - (sn * u[(k * rowsA) + i]);
+ u[(k * rowsA) + i] = z;
}
}
}
@@ -6702,9 +7890,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// A part of column "l" of matrix VT from row 0 to end multiply by -1
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- v[(l * aColumns) + i] = v[(l * aColumns) + i] * -1.0;
+ v[(l * columnsA) + i] = v[(l * columnsA) + i] * -1.0;
}
}
}
@@ -6720,25 +7908,25 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
t = stemp[l];
stemp[l] = stemp[l + 1];
stemp[l + 1] = t;
- if (computeVectors && l < aColumns)
+ if (computeVectors && l < columnsA)
{
// Swap columns l, l + 1
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- var z = v[(l * aColumns) + i];
- v[(l * aColumns) + i] = v[((l + 1) * aColumns) + i];
- v[((l + 1) * aColumns) + i] = z;
+ var z = v[(l * columnsA) + i];
+ v[(l * columnsA) + i] = v[((l + 1) * columnsA) + i];
+ v[((l + 1) * columnsA) + i] = z;
}
}
- if (computeVectors && l < aRows)
+ if (computeVectors && l < rowsA)
{
// Swap columns l, l + 1
- for (i = 0; i < aRows; i++)
+ for (i = 0; i < rowsA; i++)
{
- var z = u[(l * aRows) + i];
- u[(l * aRows) + i] = u[((l + 1) * aRows) + i];
- u[((l + 1) * aRows) + i] = z;
+ var z = u[(l * rowsA) + i];
+ u[(l * rowsA) + i] = u[((l + 1) * rowsA) + i];
+ u[((l + 1) * rowsA) + i] = z;
}
}
@@ -6754,11 +7942,11 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if (computeVectors)
{
// Finally transpose "v" to get "vt" matrix
- for (i = 0; i < aColumns; i++)
+ for (i = 0; i < columnsA; i++)
{
- for (j = 0; j < aColumns; j++)
+ for (j = 0; j < columnsA; j++)
{
- vt[(j * aColumns) + i] = v[(i * aColumns) + j].Conjugate();
+ vt[(j * columnsA) + i] = v[(i * columnsA) + j].Conjugate();
}
}
}
@@ -6766,26 +7954,26 @@ 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
// 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.
- CommonParallel.For(0, Math.Min(aRows, aColumns), index => s[index] = stemp[index]);
+ CommonParallel.For(0, Math.Min(rowsA, columnsA), index => s[index] = stemp[index]);
// 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] = aRows;
+ work[0] = rowsA;
}
///
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x)
+ public void SvdSolve(Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x)
{
if (a == null)
{
@@ -6817,52 +8005,52 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("x");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (b.Length != aRows * bColumns)
+ if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != aColumns * bColumns)
+ if (x.Length != columnsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
// TODO: Actually "work = new double[aRows]" is acceptable size of work array. I set size proposed in method description
- var work = new Complex[Math.Max((3 * Math.Min(aRows, aColumns)) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns))];
- SvdSolve(a, aRows, aColumns, s, u, vt, b, bColumns, x, work);
+ var work = new Complex[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
+ SvdSolve(a, rowsA, columnsA, s, u, vt, b, columnsB, x, work);
}
///
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x, Complex[] work)
+ public void SvdSolve(Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x, Complex[] work)
{
if (a == null)
{
@@ -6894,27 +8082,27 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("x");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (b.Length != aRows * bColumns)
+ if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != aColumns * bColumns)
+ if (x.Length != columnsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@@ -6924,28 +8112,28 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
- if (work.Length < aRows)
+ if (work.Length < rowsA)
{
- work[0] = aRows;
+ work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
- SingularValueDecomposition(true, a, aRows, aColumns, s, u, vt, work);
- SvdSolveFactored(aRows, aColumns, s, u, vt, b, bColumns, x);
+ SingularValueDecomposition(true, a, rowsA, columnsA, s, u, vt, work);
+ SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x)
{
if (s == null)
{
@@ -6972,44 +8160,44 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("x");
}
- if (u.Length != aRows * aRows)
+ if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
- if (vt.Length != aColumns * aColumns)
+ if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
- if (s.Length != Math.Min(aRows, aColumns))
+ if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
- if (b.Length != aRows * bColumns)
+ if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- if (x.Length != aColumns * bColumns)
+ if (x.Length != columnsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
- var mn = Math.Min(aRows, aColumns);
- var tmp = new Complex[aColumns];
+ var mn = Math.Min(rowsA, columnsA);
+ var tmp = new Complex[columnsA];
- for (var k = 0; k < bColumns; k++)
+ for (var k = 0; k < columnsB; k++)
{
- for (var j = 0; j < aColumns; j++)
+ for (var j = 0; j < columnsA; j++)
{
var value = Complex.Zero;
if (j < mn)
{
- for (var i = 0; i < aRows; i++)
+ for (var i = 0; i < rowsA; i++)
{
- value += u[(j * aRows) + i].Conjugate() * b[(k * aRows) + i];
+ value += u[(j * rowsA) + i].Conjugate() * b[(k * rowsA) + i];
}
value /= s[j];
@@ -7018,15 +8206,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
tmp[j] = value;
}
- for (var j = 0; j < aColumns; j++)
+ for (var j = 0; j < columnsA; j++)
{
var value = Complex.Zero;
- for (var i = 0; i < aColumns; i++)
+ for (var i = 0; i < columnsA; i++)
{
- value += vt[(j * aColumns) + i].Conjugate() * tmp[i];
+ value += vt[(j * columnsA) + i].Conjugate() * tmp[i];
}
- x[(k * aColumns) + j] = value;
+ x[(k * columnsA) + j] = value;
}
}
}
@@ -7234,11 +8422,33 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
CommonParallel.For(0, y.Length, i => result[i] = x[i] * y[i]);
}
+ ///
+ /// Computes the requested of the matrix.
+ ///
+ /// The type of norm to compute.
+ /// The number of rows.
+ /// The number of columns.
+ /// The matrix to compute the norm from.
+ ///
+ /// The requested of the matrix.
+ ///
public Complex32 MatrixNorm(Norm norm, int rows, int columns, Complex32[] matrix)
{
throw new NotImplementedException();
}
+ ///
+ /// Computes the requested of the matrix.
+ ///
+ /// The type of norm to compute.
+ /// The number of rows.
+ /// The number of columns.
+ /// The matrix to compute the norm from.
+ /// The work array. Only used when
+ /// and needs to be have a length of at least M (number of rows of .
+ ///
+ /// The requested of the matrix.
+ ///
public Complex32 MatrixNorm(Norm norm, int rows, int columns, Complex32[] matrix, Complex32[] work)
{
throw new NotImplementedException();
@@ -7248,15 +8458,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(Complex32[] x, int xRows, int xColumns, Complex32[] y, int yRows, int yColumns, Complex32[] result)
+ public void MatrixMultiply(Complex32[] x, int rowsX, int columnsX, Complex32[] y, int rowsY, int columnsY, Complex32[] result)
{
// First check some basic requirement on the parameters of the matrix multiplication.
if (x == null)
@@ -7274,22 +8484,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new ArgumentNullException("result");
}
- if (xRows * xColumns != x.Length)
+ if (rowsX * columnsX != x.Length)
{
throw new ArgumentException("x.Length != xRows * xColumns");
}
- if (yRows * yColumns != y.Length)
+ if (rowsY * columnsY != y.Length)
{
throw new ArgumentException("y.Length != yRows * yColumns");
}
- if (xColumns != yRows)
+ if (columnsX != rowsY)
{
throw new ArgumentException("xColumns != yRows");
}
- if (xRows * yColumns != result.Length)
+ if (rowsX * columnsY != result.Length)
{
throw new ArgumentException("xRows * yColumns != result.Length");
}
@@ -7321,7 +8531,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
// TODO - For small matrices we should get rid of the parallelism because of startup costs.
// Perhaps the following implementations would be a good one
// http://blog.feradz.com/2009/01/cache-efficient-matrix-multiplication/
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex32.One, xdata, xRows, xColumns, ydata, yRows, yColumns, Complex32.Zero, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex32.One, xdata, rowsX, columnsX, ydata, rowsY, columnsY, Complex32.Zero, result);
}
///
@@ -7331,20 +8541,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
- public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a,
- int aRows, int aColumns, Complex32[] b, int bRows, int bColumns, Complex32 beta, Complex32[] c)
+ public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a, int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c)
{
- // Choose nonsensical values for the number of rows and columns in c; fill them in depending
+ // Choose nonsensical values for the number of rows in c; fill them in depending
// on the operations on a and b.
- var cRows = -1;
- var cColumns = -1;
+ int rowsC;
// First check some basic requirement on the parameters of the matrix multiplication.
if (a == null)
@@ -7359,63 +8567,59 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- if (aRows != bColumns)
+ if (rowsA != columnsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aColumns * bRows != c.Length)
+ if (columnsA * rowsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aColumns;
- cColumns = bRows;
+ rowsC = columnsA;
}
else if ((int)transposeA > 111)
{
- if (aRows != bRows)
+ if (rowsA != rowsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aColumns * bColumns != c.Length)
+ if (columnsA * columnsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aColumns;
- cColumns = bColumns;
+ rowsC = columnsA;
}
else if ((int)transposeB > 111)
{
- if (aColumns != bColumns)
+ if (columnsA != columnsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aRows * bRows != c.Length)
+ if (rowsA * rowsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aRows;
- cColumns = bRows;
+ rowsC = rowsA;
}
else
{
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentOutOfRangeException();
}
- if (aRows * bColumns != c.Length)
+ if (rowsA * columnsB != c.Length)
{
throw new ArgumentOutOfRangeException();
}
- cRows = aRows;
- cColumns = bColumns;
+ rowsC = rowsA;
}
if (alpha.IsZero() && beta.IsZero())
@@ -7424,7 +8628,6 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
return;
}
-
// Check whether we will be overwriting any of our inputs and make copies if necessary.
// TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
// as result, we can do it on a row wise basis. We should investigate this.
@@ -7454,150 +8657,174 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- Complex32 s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex32 s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- Complex32 s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex32 s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s;
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex32 s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s;
- }
- });
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex32 s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s;
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex32 s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex32 s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = s;
- }
- });
+ c[jcIndex + i] = s;
+ }
+ });
}
}
else
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- Complex32 s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex32 s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + s;
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- Complex32 s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex32 s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex32 s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = s + c[jIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex32 s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = s + (c[jIndex + i] * beta);
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex32 s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex32 s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = s + (c[jcIndex + i] * beta);
+ }
+ });
}
}
}
@@ -7605,75 +8832,87 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
if ((int)transposeA > 111 && (int)transposeB > 111)
{
- CommonParallel.For(0, aColumns, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != bRows; i++)
- {
- var iIndex = i * aRows;
- Complex32 s = 0;
- for (var l = 0; l != bColumns; l++)
- {
- s += adata[iIndex + l] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = c[jIndex + i] * beta + alpha * s;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsA,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsB; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex32 s = 0;
+ for (var l = 0; l != columnsB; l++)
+ {
+ s += adata[iIndex + l] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (c[jIndex + i] * beta) + (alpha * s);
+ }
+ });
}
else if ((int)transposeA > 111)
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aColumns; i++)
- {
- var iIndex = i * aRows;
- Complex32 s = 0;
- for (var l = 0; l != aRows; l++)
- {
- s += adata[iIndex + l] * bdata[jbIndex + l];
- }
-
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != columnsA; i++)
+ {
+ var iIndex = i * rowsA;
+ Complex32 s = 0;
+ for (var l = 0; l != rowsA; l++)
+ {
+ s += adata[iIndex + l] * bdata[jbIndex + l];
+ }
+
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
}
else if ((int)transposeB > 111)
{
- CommonParallel.For(0, bRows, j =>
- {
- var jIndex = j * cRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex32 s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[l * bRows + j];
- }
-
- c[jIndex + i] = alpha * s + c[jIndex + i] * beta;
- }
- });
+ CommonParallel.For(
+ 0,
+ rowsB,
+ j =>
+ {
+ var jIndex = j * rowsC;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex32 s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
+ }
+
+ c[jIndex + i] = (alpha * s) + (c[jIndex + i] * beta);
+ }
+ });
}
else
{
- CommonParallel.For(0, bColumns, j =>
- {
- var jcIndex = j * cRows;
- var jbIndex = j * bRows;
- for (var i = 0; i != aRows; i++)
- {
- Complex32 s = 0;
- for (var l = 0; l != aColumns; l++)
- {
- s += adata[l * aRows + i] * bdata[jbIndex + l];
- }
+ CommonParallel.For(
+ 0,
+ columnsB,
+ j =>
+ {
+ var jcIndex = j * rowsC;
+ var jbIndex = j * rowsB;
+ for (var i = 0; i != rowsA; i++)
+ {
+ Complex32 s = 0;
+ for (var l = 0; l != columnsA; l++)
+ {
+ s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
+ }
- c[jcIndex + i] = alpha * s + c[jcIndex + i] * beta;
- }
- });
+ c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
+ }
+ });
}
}
}
@@ -7744,21 +8983,57 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
throw new NotImplementedException();
}
+ ///
+ /// Solves A*X=B for X using LU factorization.
+ ///
+ /// The number of columns of B.
+ /// The square matrix A.
+ /// The order of the square matrix .
+ /// The B matrix.
+ /// This is equivalent to the GETRF and GETRS LAPACK routines.
public void LUSolve(int columnsOfB, Complex32[] a, int order, Complex32[] b)
{
throw new NotImplementedException();
}
+ ///
+ /// Solves A*X=B for X using a previously factored A matrix.
+ ///
+ /// The number of columns of B.
+ /// The factored A matrix.
+ /// The order of the square matrix .
+ /// The pivot indices of .
+ /// The B matrix.
+ /// This is equivalent to the GETRS LAPACK routine.
public void LUSolveFactored(int columnsOfB, Complex32[] a, int order, int[] ipiv, Complex32[] b)
{
throw new NotImplementedException();
}
+ ///
+ /// Solves A*X=B for X using LU factorization.
+ ///
+ /// How to transpose the matrix.
+ /// The number of columns of B.
+ /// The square matrix A.
+ /// The order of the square matrix .
+ /// The B matrix.
+ /// This is equivalent to the GETRF and GETRS LAPACK routines.
public void LUSolve(Transpose transposeA, int columnsOfB, Complex32[] a, int order, Complex32[] b)
{
throw new NotImplementedException();
}
+ ///
+ /// Solves A*X=B for X using a previously factored A matrix.
+ ///
+ /// How to transpose the matrix.
+ /// The number of columns of B.
+ /// The factored A matrix.
+ /// The order of the square matrix .
+ /// The pivot indices of .
+ /// The B matrix.
+ /// This is equivalent to the GETRS LAPACK routine.
public void LUSolveFactored(Transpose transposeA, int columnsOfB, Complex32[] a, int order, int[] ipiv, Complex32[] b)
{
throw new NotImplementedException();
@@ -7780,12 +9055,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(Complex32[] a, int aOrder, Complex32[] b, int bRows, int bColumns)
+ public void CholeskySolve(Complex32[] a, int orderA, Complex32[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -7794,12 +9069,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(Complex32[] a, int aOrder, Complex32[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(Complex32[] a, int orderA, Complex32[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -7809,12 +9084,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex32[] r, int rRows, int rColumns, Complex32[] q)
+ public void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q)
{
throw new NotImplementedException();
}
@@ -7824,15 +9099,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] work)
+ public void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -7842,14 +9117,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] b, int bColumns, Complex32[] x)
+ public void QRSolve(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -7859,17 +9134,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] b, int bColumns, Complex32[] x, Complex32[] work)
+ public void QRSolve(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -7879,12 +9154,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(Complex32[] q, Complex32[] r, int rRows, int rColumns, Complex32[] b, int bColumns, Complex32[] x)
+ public void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -7894,15 +9169,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt)
+ public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
throw new NotImplementedException();
}
@@ -7912,8 +9187,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -7923,7 +9198,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
+ public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -7932,15 +9207,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x)
+ public void SvdSolve(Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -7949,18 +9224,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x, Complex32[] work)
+ public void SvdSolve(Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -7968,15 +9243,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
diff --git a/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs
index 5094a665..fdca19cc 100644
--- a/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs
+++ b/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs
@@ -266,17 +266,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(double[] x, int xRows, int xColumns, double[] y, int yRows, int yColumns, double[] result)
+ public void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, xRows, xColumns, y, yRows, yColumns, 0.0, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, rowsX, columnsX, y, rowsY, columnsY, 0.0, result);
}
///
@@ -286,15 +286,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a,
- int aRows, int aColumns, double[] b, int bRows, int bColumns, double beta, double[] c)
+ int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
{
if (a == null)
{
@@ -311,16 +311,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -476,13 +476,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
///
- public void CholeskySolve(double[] a, int aOrder, double[] b, int bRows, int bColumns)
+ public void CholeskySolve(double[] a, int orderA, double[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -491,12 +491,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(double[] a, int aOrder, double[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(double[] a, int orderA, double[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -506,12 +506,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(double[] r, int rRows, int rColumns, double[] q)
+ public void QRFactor(double[] r, int rowsR, int columnsR, double[] q)
{
throw new NotImplementedException();
}
@@ -521,15 +521,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(double[] r, int rRows, int rColumns, double[] q, double[] work)
+ public void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] work)
{
throw new NotImplementedException();
}
@@ -539,14 +539,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(double[] r, int rRows, int rColumns, double[] q, double[] b, int bColumns, double[] x)
+ public void QRSolve(double[] r, int rowsR, int columnsR, double[] q, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -556,17 +556,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(double[] r, int rRows, int rColumns, double[] q, double[] b, int bColumns, double[] x, double[] work)
+ public void QRSolve(double[] r, int rowsR, int columnsR, double[] q, double[] b, int columnsB, double[] x, double[] work)
{
throw new NotImplementedException();
}
@@ -576,12 +576,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(double[] q, double[] r, int rRows, int rColumns, double[] b, int bColumns, double[] x)
+ public void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -591,15 +591,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt)
+ public void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
throw new NotImplementedException();
}
@@ -609,8 +609,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -620,7 +620,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] work)
+ public void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
{
throw new NotImplementedException();
}
@@ -629,15 +629,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x)
+ public void SvdSolve(double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -646,18 +646,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(double[] a, int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x, double[] work)
+ public void SvdSolve(double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x, double[] work)
{
throw new NotImplementedException();
}
@@ -665,15 +665,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, double[] s, double[] u, double[] vt, double[] b, int bColumns, double[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] b, int columnsB, double[] x)
{
throw new NotImplementedException();
}
@@ -903,17 +903,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(float[] x, int xRows, int xColumns, float[] y, int yRows, int yColumns, float[] result)
+ public void MatrixMultiply(float[] x, int rowsX, int columnsX, float[] y, int rowsY, int columnsY, float[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0f, x, xRows, xColumns, y, yRows, yColumns, 0.0f, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0f, x, rowsX, columnsX, y, rowsY, columnsY, 0.0f, result);
}
///
@@ -923,15 +923,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, float alpha, float[] a,
- int aRows, int aColumns, float[] b, int bRows, int bColumns, float beta, float[] c)
+ int rowsA, int columnsA, float[] b, int rowsB, int columnsB, float beta, float[] c)
{
if (a == null)
{
@@ -948,16 +948,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -1113,12 +1113,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(float[] a, int aOrder, float[] b, int bRows, int bColumns)
+ public void CholeskySolve(float[] a, int orderA, float[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1127,12 +1127,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(float[] a, int aOrder, float[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(float[] a, int orderA, float[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1142,12 +1142,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(float[] r, int rRows, int rColumns, float[] q)
+ public void QRFactor(float[] r, int rowsR, int columnsR, float[] q)
{
throw new NotImplementedException();
}
@@ -1157,15 +1157,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(float[] r, int rRows, int rColumns, float[] q, float[] work)
+ public void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] work)
{
throw new NotImplementedException();
}
@@ -1175,14 +1175,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(float[] r, int rRows, int rColumns, float[] q, float[] b, int bColumns, float[] x)
+ public void QRSolve(float[] r, int rowsR, int columnsR, float[] q, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1192,17 +1192,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(float[] r, int rRows, int rColumns, float[] q, float[] b, int bColumns, float[] x, float[] work)
+ public void QRSolve(float[] r, int rowsR, int columnsR, float[] q, float[] b, int columnsB, float[] x, float[] work)
{
throw new NotImplementedException();
}
@@ -1212,12 +1212,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(float[] q, float[] r, int rRows, int rColumns, float[] b, int bColumns, float[] x)
+ public void QRSolveFactored(float[] q, float[] r, int rowsR, int columnsR, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1227,15 +1227,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt)
+ public void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
throw new NotImplementedException();
}
@@ -1245,8 +1245,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -1256,7 +1256,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] work)
+ public void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
{
throw new NotImplementedException();
}
@@ -1265,15 +1265,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x)
+ public void SvdSolve(float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1282,18 +1282,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(float[] a, int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x, float[] work)
+ public void SvdSolve(float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x, float[] work)
{
throw new NotImplementedException();
}
@@ -1301,15 +1301,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, float[] s, float[] u, float[] vt, float[] b, int bColumns, float[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] b, int columnsB, float[] x)
{
throw new NotImplementedException();
}
@@ -1539,17 +1539,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(Complex[] x, int xRows, int xColumns, Complex[] y, int yRows, int yColumns, Complex[] result)
+ public void MatrixMultiply(Complex[] x, int rowsX, int columnsX, Complex[] y, int rowsY, int columnsY, Complex[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex.One, x, xRows, xColumns, y, yRows, yColumns, Complex.Zero, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex.One, x, rowsX, columnsX, y, rowsY, columnsY, Complex.Zero, result);
}
///
@@ -1559,15 +1559,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex alpha, Complex[] a,
- int aRows, int aColumns, Complex[] b, int bRows, int bColumns, Complex beta, Complex[] c)
+ int rowsA, int columnsA, Complex[] b, int rowsB, int columnsB, Complex beta, Complex[] c)
{
if (a == null)
{
@@ -1584,16 +1584,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -1749,12 +1749,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(Complex[] a, int aOrder, Complex[] b, int bRows, int bColumns)
+ public void CholeskySolve(Complex[] a, int orderA, Complex[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1763,12 +1763,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(Complex[] a, int aOrder, Complex[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(Complex[] a, int orderA, Complex[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -1778,12 +1778,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex[] r, int rRows, int rColumns, Complex[] q)
+ public void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q)
{
throw new NotImplementedException();
}
@@ -1793,15 +1793,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] work)
+ public void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1811,14 +1811,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] b, int bColumns, Complex[] x)
+ public void QRSolve(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -1828,17 +1828,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(Complex[] r, int rRows, int rColumns, Complex[] q, Complex[] b, int bColumns, Complex[] x, Complex[] work)
+ public void QRSolve(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] b, int columnsB, Complex[] x, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1848,12 +1848,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(Complex[] q, Complex[] r, int rRows, int rColumns, Complex[] b, int bColumns, Complex[] x)
+ public void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -1863,15 +1863,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt)
+ public void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
throw new NotImplementedException();
}
@@ -1881,8 +1881,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -1892,7 +1892,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
+ public void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1901,15 +1901,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x)
+ public void SvdSolve(Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -1918,18 +1918,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(Complex[] a, int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x, Complex[] work)
+ public void SvdSolve(Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x, Complex[] work)
{
throw new NotImplementedException();
}
@@ -1937,15 +1937,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int bColumns, Complex[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] b, int columnsB, Complex[] x)
{
throw new NotImplementedException();
}
@@ -2175,17 +2175,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Multiples two matrices. result = x * y
///
/// The x matrix.
- /// The number of rows in the x matrix.
- /// The number of columns in the x matrix.
+ /// The number of rows in the x matrix.
+ /// The number of columns in the x matrix.
/// The y matrix.
- /// The number of rows in the y matrix.
- /// The number of columns in the y matrix.
+ /// The number of rows in the y matrix.
+ /// The number of columns in the y matrix.
/// Where to store the result of the multiplication.
/// This is a simplified version of the BLAS GEMM routine with alpha
/// set to 1.0 and beta set to 0.0, and x and y are not transposed.
- public void MatrixMultiply(Complex32[] x, int xRows, int xColumns, Complex32[] y, int yRows, int yColumns, Complex32[] result)
+ public void MatrixMultiply(Complex32[] x, int rowsX, int columnsX, Complex32[] y, int rowsY, int columnsY, Complex32[] result)
{
- MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex32.One, x, xRows, xColumns, y, yRows, yColumns, Complex32.Zero, result);
+ MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, Complex32.One, x, rowsX, columnsX, y, rowsY, columnsY, Complex32.Zero, result);
}
///
@@ -2195,15 +2195,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// How to transpose the matrix.
/// The value to scale matrix.
/// The a matrix.
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The b matrix
- /// The number of rows in the matrix.
- /// The number of columns in the matrix.
+ /// The number of rows in the matrix.
+ /// The number of columns in the matrix.
/// The value to scale the matrix.
/// The c matrix.
public void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex32 alpha, Complex32[] a,
- int aRows, int aColumns, Complex32[] b, int bRows, int bColumns, Complex32 beta, Complex32[] c)
+ int rowsA, int columnsA, Complex32[] b, int rowsB, int columnsB, Complex32 beta, Complex32[] c)
{
if (a == null)
{
@@ -2220,16 +2220,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("c");
}
- var m = transposeA == Transpose.DontTranspose ? aRows : aColumns;
- var n = transposeB == Transpose.DontTranspose ? bColumns : bRows;
- var k = transposeA == Transpose.DontTranspose ? aColumns : aRows;
+ var m = transposeA == Transpose.DontTranspose ? rowsA : columnsA;
+ var n = transposeB == Transpose.DontTranspose ? columnsB : rowsB;
+ var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
- if( c.Length != aRows * bColumns)
+ if( c.Length != rowsA * columnsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
- if (aColumns != bRows)
+ if (columnsA != rowsB)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@@ -2385,12 +2385,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using Cholesky factorization.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRF add POTRS LAPACK routines.
- public void CholeskySolve(Complex32[] a, int aOrder, Complex32[] b, int bRows, int bColumns)
+ public void CholeskySolve(Complex32[] a, int orderA, Complex32[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -2399,12 +2399,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using a previously factored A matrix.
///
/// The square, positive definite matrix A.
- /// The number of rows and columns in A.
+ /// The number of rows and columns in A.
/// The B matrix.
- /// The number of rows in the B matrix.
- /// The number of columns in the B matrix.
+ /// The number of rows in the B matrix.
+ /// The number of columns in the B matrix.
/// This is equivalent to the POTRS LAPACK routine.
- public void CholeskySolveFactored(Complex32[] a, int aOrder, Complex32[] b, int bRows, int bColumns)
+ public void CholeskySolveFactored(Complex32[] a, int orderA, Complex32[] b, int rowsB, int columnsB)
{
throw new NotImplementedException();
}
@@ -2414,12 +2414,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex32[] r, int rRows, int rColumns, Complex32[] q)
+ public void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q)
{
throw new NotImplementedException();
}
@@ -2429,15 +2429,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
/// This is similar to the GEQRF and ORGQR LAPACK routines.
- public void QRFactor(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] work)
+ public void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2447,14 +2447,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolve(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] b, int bColumns, Complex32[] x)
+ public void QRSolve(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -2464,17 +2464,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.
- public void QRSolve(Complex32[] r, int rRows, int rColumns, Complex32[] q, Complex32[] b, int bColumns, Complex32[] x, Complex32[] work)
+ public void QRSolve(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2484,12 +2484,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// The Q matrix obtained by calling .
/// The R matrix obtained by calling .
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void QRSolveFactored(Complex32[] q, Complex32[] r, int rRows, int rColumns, Complex32[] b, int bColumns, Complex32[] x)
+ public void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -2499,15 +2499,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
/// If is true, on exit VT contains the transposed
/// right singular vectors.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt)
+ public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
throw new NotImplementedException();
}
@@ -2517,8 +2517,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Compute the singular U and VT vectors or not.
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// If is true, on exit U contains the left
/// singular vectors.
@@ -2528,7 +2528,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
/// This is equivalent to the GESVD LAPACK routine.
- public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
+ public void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2537,15 +2537,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolve(Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x)
+ public void SvdSolve(Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
@@ -2554,18 +2554,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
/// Solves A*X=B for X using the singular value decomposition of A.
///
/// On entry, the M by N matrix to decompose. On exit, A may be overwritten.
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The singular values of A in ascending value.
/// On exit U contains the left singular vectors.
/// On exit VT contains the transposed right singular vectors.
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
/// The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.
- public void SvdSolve(Complex32[] a, int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x, Complex32[] work)
+ public void SvdSolve(Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work)
{
throw new NotImplementedException();
}
@@ -2573,15 +2573,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
///
/// Solves A*X=B for X using a previously SVD decomposed matrix.
///
- /// The number of rows in the A matrix.
- /// The number of columns in the A matrix.
+ /// The number of rows in the A matrix.
+ /// The number of columns in the A matrix.
/// The s values returned by .
/// The left singular vectors returned by .
/// The right singular vectors returned by .
/// The B matrix.
- /// The number of columns of B.
+ /// The number of columns of B.
/// On exit, the solution matrix.
- public void SvdSolveFactored(int aRows, int aColumns, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int bColumns, Complex32[] x)
+ public void SvdSolveFactored(int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] b, int columnsB, Complex32[] x)
{
throw new NotImplementedException();
}
diff --git a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
index 5367bf76..c970b583 100644
--- a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
@@ -718,16 +718,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(Complex val1)
- {
- return val1.AlmostEqual(Complex.One);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs
index 52f9c5ba..335686da 100644
--- a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs
+++ b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs
@@ -1438,10 +1438,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
tmp.CopyTo(target);
}
- CommonParallel.For(
- 0,
- Count,
- index => target[index] = this[index].Conjugate());
+ var otherVector = target as DenseVector;
+ if (otherVector == null)
+ {
+ base.Conjugate(target);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Count,
+ index => otherVector.Data[index] = Data[index].Conjugate());
+ }
}
#region Simple arithmetic of type T
@@ -1489,16 +1497,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(Complex val1)
- {
- return Complex.One.AlmostEqual(val1);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
index 0bf51c79..ca00ec8a 100644
--- a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
@@ -1597,16 +1597,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
var matrix = CreateMatrix(numberOfRows, numberOfColumns);
- CommonParallel.For(
- 0,
- ColumnCount,
- j =>
- {
- for (var i = 0; i < matrix.RowCount; i++)
- {
- matrix[i, j] = new Complex(distribution.Sample(), distribution.Sample());
- }
- });
+ var mn = Math.Min(numberOfRows, numberOfColumns);
+ CommonParallel.For(0, mn, i => matrix[i, i] = new Complex(distribution.Sample(), distribution.Sample()));
return matrix;
}
@@ -1635,16 +1627,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
var matrix = CreateMatrix(numberOfRows, numberOfColumns);
- CommonParallel.For(
- 0,
- ColumnCount,
- j =>
- {
- for (var i = 0; i < matrix.RowCount; i++)
- {
- matrix[i, j] = new Complex(distribution.Sample(), distribution.Sample());
- }
- });
+ var mn = Math.Min(numberOfRows, numberOfColumns);
+ CommonParallel.For(0, mn, i => matrix[i, i] = new Complex(distribution.Sample(), distribution.Sample()));
return matrix;
}
@@ -1694,16 +1678,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(Complex val1)
- {
- return Complex.One.AlmostEqual(val1);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs
index 374a8a64..69ccf087 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs
@@ -209,15 +209,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
return val1.NaturalLogarithm();
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs
index baf323fb..058e4742 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs
@@ -201,24 +201,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
return val1 * val2;
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
-
- ///
- /// Get value of type T equal to minus one
- ///
- /// One value
- protected sealed override Complex MinusOneValueT
- {
- get { return -Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs
index dec02790..1fa36654 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs
@@ -190,14 +190,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
return val1.Magnitude;
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseSvd.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseSvd.cs
index 88fa07c6..aa98288e 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseSvd.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseSvd.cs
@@ -202,16 +202,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
return val1.Magnitude;
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs
index 5e0c85ad..58ded73f 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs
@@ -312,14 +312,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
return val1.Magnitude;
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/UserCholesky.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/UserCholesky.cs
index 1417c631..1b40a88a 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/UserCholesky.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/UserCholesky.cs
@@ -254,15 +254,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
return val1.NaturalLogarithm();
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/UserLU.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/UserLU.cs
index a0768b70..03e17611 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/UserLU.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/UserLU.cs
@@ -312,24 +312,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
return val1 * val2;
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
-
- ///
- /// Get value of type T equal to minus one
- ///
- /// One value
- protected sealed override Complex MinusOneValueT
- {
- get { return -Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/UserQR.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/UserQR.cs
index 293fb4f5..dd64b30f 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/UserQR.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/UserQR.cs
@@ -352,15 +352,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
return val1.Magnitude;
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/UserSvd.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/UserSvd.cs
index 0b2ab5fa..172de227 100644
--- a/src/Numerics/LinearAlgebra/Complex/Factorization/UserSvd.cs
+++ b/src/Numerics/LinearAlgebra/Complex/Factorization/UserSvd.cs
@@ -960,15 +960,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
return val1.Magnitude;
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override Complex OneValueT
- {
- get { return Complex.One; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
index 1d556ad3..9adc572d 100644
--- a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
@@ -1686,16 +1686,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(Complex val1)
- {
- return Complex.One.AlmostEqual(val1);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs
index ad0e11cd..c93190e9 100644
--- a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs
+++ b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs
@@ -376,10 +376,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var otherVector = target as SparseVector;
if (otherVector == null)
{
- CommonParallel.For(
- 0,
- Count,
- index => target[index] = this[index].Conjugate());
+ base.Conjugate(target);
}
else
{
@@ -1671,16 +1668,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(Complex val1)
- {
- return Complex.One.AlmostEqual(val1);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
index 35709121..ad8acd72 100644
--- a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
@@ -651,15 +651,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return matrix;
}
- ///
- /// Returns the conjugate transpose of this matrix.
- ///
- /// The conjugate transpose of this matrix.
- public override Matrix ConjugateTranspose()
- {
- throw new NotSupportedException("ConjugateTranspose is not supported for real matricies");
- }
-
#region Simple arithmetic of type T
///
/// Add two values T+T
@@ -705,16 +696,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(double val1)
- {
- return 1.0.AlmostEqualInDecimalPlaces(val1, 15);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Double/DenseVector.cs b/src/Numerics/LinearAlgebra/Double/DenseVector.cs
index b95fe041..89fe5674 100644
--- a/src/Numerics/LinearAlgebra/Double/DenseVector.cs
+++ b/src/Numerics/LinearAlgebra/Double/DenseVector.cs
@@ -1498,15 +1498,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Array.Clear(Data, 0, Data.Length);
}
- ///
- /// Conjugates vector and save result to
- ///
- /// Target vector
- public override void Conjugate(Vector target)
- {
- throw new NotSupportedException("Conjugate is not supported for real vectors");
- }
-
#region Simple arithmetic of type T
///
/// Add two values T+T
@@ -1552,16 +1543,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(double val1)
- {
- return val1 == 1.0;
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
index 20e94025..1c50acca 100644
--- a/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
@@ -1584,16 +1584,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
var matrix = CreateMatrix(numberOfRows, numberOfColumns);
- CommonParallel.For(
- 0,
- ColumnCount,
- j =>
- {
- for (var i = 0; i < matrix.RowCount; i++)
- {
- matrix[i, j] = distribution.Sample();
- }
- });
+ var mn = Math.Min(numberOfRows, numberOfColumns);
+ CommonParallel.For(0, mn, i => matrix[i, i] = distribution.Sample());
return matrix;
}
@@ -1622,16 +1614,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
var matrix = CreateMatrix(numberOfRows, numberOfColumns);
- CommonParallel.For(
- 0,
- ColumnCount,
- j =>
- {
- for (var i = 0; i < matrix.RowCount; i++)
- {
- matrix[i, j] = distribution.Sample();
- }
- });
+ var mn = Math.Min(numberOfRows, numberOfColumns);
+ CommonParallel.For(0, mn, i => matrix[i, i] = distribution.Sample());
return matrix;
}
@@ -1671,15 +1655,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return stringBuilder.ToString();
}
- ///
- /// Returns the conjugate transpose of this matrix.
- ///
- /// The conjugate transpose of this matrix.
- public override Matrix ConjugateTranspose()
- {
- throw new NotSupportedException("ConjugateTranspose is not supported for real matricies");
- }
-
#region Simple arithmetic of type T
///
/// Add two values T+T
@@ -1725,16 +1700,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(double val1)
- {
- return 1.0.AlmostEqualInDecimalPlaces(val1, 15);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs b/src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs
index f927d00d..32a60253 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs
@@ -207,15 +207,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Log(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs b/src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs
index a09477bc..b0bcacbe 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs
@@ -199,24 +199,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return val1 * val2;
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
- ///
- /// Get value of type T equal to minus one
- ///
- /// One value
- protected sealed override double MinusOneValueT
- {
- get { return -1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs b/src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs
index 10e9192e..0d559497 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs
@@ -189,14 +189,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
return Math.Abs(val1);
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/DenseSvd.cs b/src/Numerics/LinearAlgebra/Double/Factorization/DenseSvd.cs
index 39ed780a..17845971 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/DenseSvd.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/DenseSvd.cs
@@ -201,16 +201,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Abs(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs
index a906bbb9..7fdc0cd4 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs
@@ -305,15 +305,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Abs(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/SparseCholesky.cs b/src/Numerics/LinearAlgebra/Double/Factorization/SparseCholesky.cs
index dc949953..4ef7ddfc 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/SparseCholesky.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/SparseCholesky.cs
@@ -253,16 +253,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Log(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/SparseLU.cs b/src/Numerics/LinearAlgebra/Double/Factorization/SparseLU.cs
index eabffe81..45d8ef9c 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/SparseLU.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/SparseLU.cs
@@ -312,23 +312,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
return val1 * val2;
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
- ///
- /// Get value of type T equal to minus one
- ///
- /// One value
- protected sealed override double MinusOneValueT
- {
- get { return -1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/SparseQR.cs b/src/Numerics/LinearAlgebra/Double/Factorization/SparseQR.cs
index 95b4d28f..70a8dced 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/SparseQR.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/SparseQR.cs
@@ -353,15 +353,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Abs(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/SparseSvd.cs b/src/Numerics/LinearAlgebra/Double/Factorization/SparseSvd.cs
index bf698f5e..00c87a56 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/SparseSvd.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/SparseSvd.cs
@@ -945,15 +945,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
return Math.Abs(val1);
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/UserCholesky.cs b/src/Numerics/LinearAlgebra/Double/Factorization/UserCholesky.cs
index 4728cf6b..91dacd86 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/UserCholesky.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/UserCholesky.cs
@@ -98,40 +98,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
}
}
- ///
- /// Gets the determinant of the matrix for which the Cholesky matrix was computed.
- ///
- public override double Determinant
- {
- get
- {
- var det = 1.0;
- for (var j = 0; j < CholeskyFactor.RowCount; j++)
- {
- det *= CholeskyFactor[j, j] * CholeskyFactor[j, j];
- }
-
- return det;
- }
- }
-
- ///
- /// Gets the log determinant of the matrix for which the Cholesky matrix was computed.
- ///
- public override double DeterminantLn
- {
- get
- {
- var det = 0.0;
- for (var j = 0; j < CholeskyFactor.RowCount; j++)
- {
- det += 2.0 * Math.Log(CholeskyFactor[j, j]);
- }
-
- return det;
- }
- }
-
///
/// Solves a system of linear equations, AX = B, with A Cholesky factorized.
///
@@ -287,16 +253,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Log(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/UserLU.cs b/src/Numerics/LinearAlgebra/Double/Factorization/UserLU.cs
index a3b49e61..e29c68cb 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/UserLU.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/UserLU.cs
@@ -312,23 +312,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
return val1 * val2;
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
- ///
- /// Get value of type T equal to minus one
- ///
- /// One value
- protected sealed override double MinusOneValueT
- {
- get { return -1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/UserQR.cs b/src/Numerics/LinearAlgebra/Double/Factorization/UserQR.cs
index ee3fcfb2..f3f349c2 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/UserQR.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/UserQR.cs
@@ -352,15 +352,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
return Math.Abs(val1);
}
-
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/UserSvd.cs b/src/Numerics/LinearAlgebra/Double/Factorization/UserSvd.cs
index 0526535b..1eed31dd 100644
--- a/src/Numerics/LinearAlgebra/Double/Factorization/UserSvd.cs
+++ b/src/Numerics/LinearAlgebra/Double/Factorization/UserSvd.cs
@@ -945,15 +945,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
return Math.Abs(val1);
}
- ///
- /// Get value of type T equal to one
- ///
- /// One value
- protected sealed override double OneValueT
- {
- get { return 1.0; }
- }
-
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
index 44b804e8..3715ebe8 100644
--- a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
+++ b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
@@ -1648,15 +1648,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return stringBuilder.ToString();
}
- ///
- /// Returns the conjugate transpose of this matrix.
- ///
- /// The conjugate transpose of this matrix.
- public override Matrix ConjugateTranspose()
- {
- throw new NotSupportedException("ConjugateTranspose is not supported for real matricies");
- }
-
#region Simple arithmetic of type T
///
/// Add two values T+T
@@ -1702,16 +1693,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(double val1)
- {
- return 1.0.AlmostEqualInDecimalPlaces(val1, 15);
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Double/SparseVector.cs b/src/Numerics/LinearAlgebra/Double/SparseVector.cs
index 66e3854e..da281ae0 100644
--- a/src/Numerics/LinearAlgebra/Double/SparseVector.cs
+++ b/src/Numerics/LinearAlgebra/Double/SparseVector.cs
@@ -1618,15 +1618,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return true;
}
- ///
- /// Conjugates vector and save result to
- ///
- /// Target vector
- public override void Conjugate(Vector target)
- {
- throw new NotSupportedException("Conjugate is not supported for real vectors");
- }
-
#region Simple arithmetic of type T
///
/// Add two values T+T
@@ -1672,16 +1663,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return val1 / val2;
}
- ///
- /// Is equal to one?
- ///
- /// Value to check
- /// True if one; otherwise false
- protected sealed override bool IsOneT(double val1)
- {
- return val1 == 1.0;
- }
-
///
/// Take absolute value
///
diff --git a/src/Numerics/LinearAlgebra/Generic/Factorization/Cholesky.cs b/src/Numerics/LinearAlgebra/Generic/Factorization/Cholesky.cs
index 5031cdda..4bb40314 100644
--- a/src/Numerics/LinearAlgebra/Generic/Factorization/Cholesky.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Factorization/Cholesky.cs
@@ -65,6 +65,17 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
return new LinearAlgebra.Double.Factorization.UserCholesky(matrix as Matrix) as Cholesky;
}
+ if (typeof(T) == typeof(float))
+ {
+ var dense = matrix as LinearAlgebra.Single.DenseMatrix;
+ if (dense != null)
+ {
+ return new LinearAlgebra.Single.Factorization.DenseCholesky(dense) as Cholesky;
+ }
+
+ return new LinearAlgebra.Single.Factorization.UserCholesky(matrix as Matrix) as Cholesky;
+ }
+
if (typeof(T) == typeof(Complex))
{
var dense = matrix as LinearAlgebra.Complex.DenseMatrix;
@@ -213,9 +224,36 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
/// Gets value of type T equal to one
///
/// One value
- protected abstract T OneValueT
+ private static T OneValueT
{
- get;
+ get
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object one = Complex.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object one = Complex32.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object one = 1.0d;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object one = 1.0f;
+ return (T)one;
+ }
+
+ throw new NotSupportedException();
+ }
}
#endregion
}
diff --git a/src/Numerics/LinearAlgebra/Generic/Factorization/ExtensionMethods.cs b/src/Numerics/LinearAlgebra/Generic/Factorization/ExtensionMethods.cs
index abab7755..32acc809 100644
--- a/src/Numerics/LinearAlgebra/Generic/Factorization/ExtensionMethods.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Factorization/ExtensionMethods.cs
@@ -85,6 +85,11 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
return new LinearAlgebra.Double.Factorization.GramSchmidt(matrix as Matrix) as QR;
}
+ if (typeof(T) == typeof(float))
+ {
+ return new LinearAlgebra.Single.Factorization.GramSchmidt(matrix as Matrix) as QR;
+ }
+
if (typeof(T) == typeof(Complex))
{
return new LinearAlgebra.Complex.Factorization.GramSchmidt(matrix as Matrix) as QR;
diff --git a/src/Numerics/LinearAlgebra/Generic/Factorization/LU.cs b/src/Numerics/LinearAlgebra/Generic/Factorization/LU.cs
index 60f34bb4..811f062f 100644
--- a/src/Numerics/LinearAlgebra/Generic/Factorization/LU.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Factorization/LU.cs
@@ -80,6 +80,17 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
return new LinearAlgebra.Double.Factorization.UserLU(matrix as Matrix) as LU;
}
+ if (typeof(T) == typeof(float))
+ {
+ var dense = matrix as LinearAlgebra.Single.DenseMatrix;
+ if (dense != null)
+ {
+ return new LinearAlgebra.Single.Factorization.DenseLU(dense) as LU;
+ }
+
+ return new LinearAlgebra.Single.Factorization.UserLU(matrix as Matrix) as LU;
+ }
+
if (typeof(T) == typeof(Complex))
{
var dense = matrix as LinearAlgebra.Complex.DenseMatrix;
@@ -227,18 +238,72 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
/// Gets value of type T equal to one
///
/// One value
- protected abstract T OneValueT
+ private static T OneValueT
{
- get;
+ get
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object one = Complex.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object one = Complex32.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object one = 1.0d;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object one = 1.0f;
+ return (T)one;
+ }
+
+ throw new NotSupportedException();
+ }
}
///
/// Gets value of type T equal to one
///
/// One value
- protected abstract T MinusOneValueT
+ private static T MinusOneValueT
{
- get;
+ get
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object one = -Complex.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object one = -Complex32.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object one = -1.0d;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object one = -1.0f;
+ return (T)one;
+ }
+
+ throw new NotSupportedException();
+ }
}
#endregion
diff --git a/src/Numerics/LinearAlgebra/Generic/Factorization/QR.cs b/src/Numerics/LinearAlgebra/Generic/Factorization/QR.cs
index a973eb4b..23ea413e 100644
--- a/src/Numerics/LinearAlgebra/Generic/Factorization/QR.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Factorization/QR.cs
@@ -80,6 +80,17 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
return new LinearAlgebra.Double.Factorization.UserQR(matrix as Matrix) as QR;
}
+ if (typeof(T) == typeof(float))
+ {
+ var dense = matrix as LinearAlgebra.Single.DenseMatrix;
+ if (dense != null)
+ {
+ return new LinearAlgebra.Single.Factorization.DenseQR(dense) as QR;
+ }
+
+ return new LinearAlgebra.Single.Factorization.UserQR(matrix as Matrix) as QR;
+ }
+
if (typeof(T) == typeof(Complex))
{
var dense = matrix as LinearAlgebra.Complex.DenseMatrix;
@@ -132,7 +143,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
for (var i = 0; i < MatrixR.ColumnCount; i++)
{
det = MultiplyT(det, MatrixR.At(i, i));
- if (AbsoluteT(MatrixR.At(i, i)).AlmostEqualInDecimalPlaces(0.0, 15))
+ if (AbsoluteT(MatrixR.At(i, i)).AlmostEqualInDecimalPlaces(0.0, (typeof(T) == typeof(float)) ? 7 : 15))
{
return 0;
}
@@ -152,7 +163,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
{
for (var i = 0; i < MatrixR.ColumnCount; i++)
{
- if (AbsoluteT(MatrixR.At(i, i)).AlmostEqualInDecimalPlaces(0.0, 15))
+ if (AbsoluteT(MatrixR.At(i, i)).AlmostEqualInDecimalPlaces(0.0, (typeof(T) == typeof(float)) ? 7 : 15))
{
return false;
}
@@ -232,9 +243,36 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
/// Gets value of type T equal to one
///
/// One value
- protected abstract T OneValueT
+ private static T OneValueT
{
- get;
+ get
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object one = Complex.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object one = Complex32.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object one = 1.0d;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object one = 1.0f;
+ return (T)one;
+ }
+
+ throw new NotSupportedException();
+ }
}
#endregion
diff --git a/src/Numerics/LinearAlgebra/Generic/Factorization/Svd.cs b/src/Numerics/LinearAlgebra/Generic/Factorization/Svd.cs
index c4713a9a..9294c215 100644
--- a/src/Numerics/LinearAlgebra/Generic/Factorization/Svd.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Factorization/Svd.cs
@@ -31,6 +31,7 @@
namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
{
using System;
+ using System.Linq;
using System.Numerics;
using Generic;
using Properties;
@@ -97,19 +98,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
{
get
{
- var eps = Math.Pow(2.0, -52.0);
- var tol = Math.Max(MatrixU.RowCount, MatrixVT.ColumnCount) * AbsoluteT(VectorS[0]) * eps;
- var nm = Math.Min(MatrixU.RowCount, MatrixVT.ColumnCount);
- var rank = 0;
- for (var h = 0; h < nm; h++)
- {
- if (AbsoluteT(VectorS[h]) > tol)
- {
- rank++;
- }
- }
-
- return rank;
+ return VectorS.Count(t => !AbsoluteT(t).AlmostEqualInDecimalPlaces(0.0, (typeof(T) == typeof(float)) ? 7 : 15));
}
}
@@ -132,6 +121,17 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
return new LinearAlgebra.Double.Factorization.UserSvd(matrix as Matrix, computeVectors) as Svd;
}
+ if (typeof(T) == typeof(float))
+ {
+ var dense = matrix as LinearAlgebra.Single.DenseMatrix;
+ if (dense != null)
+ {
+ return new LinearAlgebra.Single.Factorization.DenseSvd(dense, computeVectors) as Svd;
+ }
+
+ return new LinearAlgebra.Single.Factorization.UserSvd(matrix as Matrix, computeVectors) as Svd;
+ }
+
if (typeof(T) == typeof(Complex))
{
var dense = matrix as LinearAlgebra.Complex.DenseMatrix;
@@ -187,7 +187,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
for (var i = 0; i < VectorS.Count; i++)
{
det = MultiplyT(det, VectorS[i]);
- if (AbsoluteT(VectorS[i]).AlmostEqualInDecimalPlaces(0.0, 15))
+ if (AbsoluteT(VectorS[i]).AlmostEqualInDecimalPlaces(0.0, (typeof(T) == typeof(float)) ? 7 : 15))
{
return 0;
}
@@ -320,9 +320,36 @@ namespace MathNet.Numerics.LinearAlgebra.Generic.Factorization
/// Gets value of type T equal to one
///
/// One value
- protected abstract T OneValueT
+ private static T OneValueT
{
- get;
+ get
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object one = Complex.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object one = Complex32.One;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object one = 1.0d;
+ return (T)one;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object one = 1.0f;
+ return (T)one;
+ }
+
+ throw new NotSupportedException();
+ }
}
#endregion
diff --git a/src/Numerics/LinearAlgebra/Generic/Matrix.cs b/src/Numerics/LinearAlgebra/Generic/Matrix.cs
index 3d4cd00a..378819ef 100644
--- a/src/Numerics/LinearAlgebra/Generic/Matrix.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Matrix.cs
@@ -1491,7 +1491,25 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// Returns the conjugate transpose of this matrix.
///
/// The conjugate transpose of this matrix.
- public abstract Matrix ConjugateTranspose();
+ public virtual Matrix ConjugateTranspose()
+ {
+ // In case of real return regulart transpose
+ if ((typeof(T) == typeof(double)) || ((typeof(T) == typeof(float))))
+ {
+ return Transpose();
+ }
+
+ var ret = CreateMatrix(ColumnCount, RowCount);
+ for (var j = 0; j < ColumnCount; j++)
+ {
+ for (var i = 0; i < RowCount; i++)
+ {
+ ret.At(j, i, ConjugateT(At(i, j)));
+ }
+ }
+
+ return ret;
+ }
///
/// Permute the rows of a matrix according to a permutation.
@@ -1866,19 +1884,80 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// Result of divide
protected abstract T DivideT(T val1, T val2);
+ ///
+ /// Take absolute value
+ ///
+ /// Source alue
+ /// True if one; otherwise false
+ protected abstract double AbsoluteT(T val1);
+
///
/// Is equal to one?
///
/// Value to check
/// True if one; otherwise false
- protected abstract bool IsOneT(T val1);
+ private static bool IsOneT(T val1)
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object obj1 = val1;
+ return Complex.One.AlmostEqual((Complex)obj1);
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object obj1 = val1;
+ return Complex32.One.AlmostEqual((Complex32)obj1);
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object obj1 = val1;
+ return 1.0.AlmostEqualInDecimalPlaces((double)obj1, 15);
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object obj1 = val1;
+ return 1.0f.AlmostEqualInDecimalPlaces((float)obj1, 7);
+ }
+
+ throw new NotSupportedException();
+ }
///
- /// Take absolute value
+ /// Conjugate complex value. In real case the same value is returned
///
- /// Source alue
- /// True if one; otherwise false
- protected abstract double AbsoluteT(T val1);
+ /// Value to conjugate
+ /// Conjugated value (complex) or the same (real)
+ private static T ConjugateT(T val1)
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object obj = val1;
+ object conj = Complex.Conjugate((Complex)obj);
+ return (T)(conj);
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object obj = val1;
+ object conj = ((Complex32)obj).Conjugate();
+ return (T)(conj);
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ return val1;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ return val1;
+ }
+
+ throw new NotSupportedException();
+ }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Generic/Vector.cs b/src/Numerics/LinearAlgebra/Generic/Vector.cs
index 739076ff..2d2127e3 100644
--- a/src/Numerics/LinearAlgebra/Generic/Vector.cs
+++ b/src/Numerics/LinearAlgebra/Generic/Vector.cs
@@ -1121,7 +1121,37 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// Conjugates vector and save result to
///
/// Target vector
- public abstract void Conjugate(Vector target);
+ public virtual void Conjugate(Vector target)
+ {
+ // In case of real return copy of vector
+ if ((typeof(T) == typeof(double)) || ((typeof(T) == typeof(float))))
+ {
+ CopyTo(target);
+ return;
+ }
+
+ if (target == null)
+ {
+ throw new ArgumentNullException("target");
+ }
+
+ if (Count != target.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
+ }
+
+ if (ReferenceEquals(this, target))
+ {
+ var tmp = CreateVector(Count);
+ Conjugate(tmp);
+ tmp.CopyTo(target);
+ }
+
+ CommonParallel.For(
+ 0,
+ Count,
+ index => target[index] = ConjugateT(this[index]));
+ }
#region Copying and Conversion
@@ -1607,19 +1637,80 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// Result of divide
protected abstract T DivideT(T val1, T val2);
+ ///
+ /// Take absolute value
+ ///
+ /// Source alue
+ /// True if one; otherwise false
+ protected abstract double AbsoluteT(T val1);
+
///
/// Is equal to one?
///
/// Value to check
/// True if one; otherwise false
- protected abstract bool IsOneT(T val1);
+ private static bool IsOneT(T val1)
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object obj1 = val1;
+ return Complex.One.AlmostEqual((Complex)obj1);
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object obj1 = val1;
+ return Complex32.One.AlmostEqual((Complex32)obj1);
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ object obj1 = val1;
+ return 1.0.AlmostEqualInDecimalPlaces((double)obj1, 15);
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ object obj1 = val1;
+ return 1.0f.AlmostEqualInDecimalPlaces((float)obj1, 7);
+ }
+
+ throw new NotSupportedException();
+ }
///
- /// Take absolute value
+ /// Conjugate complex value. In real case the same value is returned
///
- /// Source alue
- /// True if one; otherwise false
- protected abstract double AbsoluteT(T val1);
+ /// Value to conjugate
+ /// Conjugated value (complex) or the same (real)
+ private static T ConjugateT(T val1)
+ {
+ if (typeof(T) == typeof(Complex))
+ {
+ object obj = val1;
+ object conj = Complex.Conjugate((Complex)obj);
+ return (T)(conj);
+ }
+
+ if (typeof(T) == typeof(Complex32))
+ {
+ object obj = val1;
+ object conj = ((Complex32)obj).Conjugate();
+ return (T)(conj);
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ return val1;
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ return val1;
+ }
+
+ throw new NotSupportedException();
+ }
#endregion
}
}
diff --git a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
new file mode 100644
index 00000000..4fab2249
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
@@ -0,0 +1,710 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single
+{
+ using System;
+ using Distributions;
+ using Generic;
+ using Properties;
+ using Threading;
+
+ ///
+ /// A Matrix class with dense storage. The underlying storage is a one dimensional array in column-major order.
+ ///
+ public class DenseMatrix : Matrix
+ {
+ ///
+ /// Initializes a new instance of the class. This matrix is square with a given size.
+ ///
+ /// the size of the square matrix.
+ ///
+ /// If is less than one.
+ ///
+ public DenseMatrix(int order)
+ : base(order)
+ {
+ Data = new float[order * order];
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ public DenseMatrix(int rows, int columns)
+ : base(rows, columns)
+ {
+ Data = new float[rows * columns];
+ }
+
+ ///
+ /// Initializes a new instance of the class with all entries set to a particular value.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ /// The value which we assign to each element of the matrix.
+ public DenseMatrix(int rows, int columns, float value)
+ : base(rows, columns)
+ {
+ Data = new float[rows * columns];
+ for (var i = 0; i < Data.Length; i++)
+ {
+ Data[i] = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class from a one dimensional array. This constructor
+ /// will reference the one dimensional array and not copy it.
+ ///
+ /// The number of rows.
+ /// The number of columns.
+ /// The one dimensional array to create this matrix from. This array should store the matrix in column-major order.
+ public DenseMatrix(int rows, int columns, float[] array)
+ : base(rows, columns)
+ {
+ Data = array;
+ }
+
+ ///
+ /// Initializes a new instance of the class from a 2D array. This constructor
+ /// will allocate a completely new memory block for storing the dense matrix.
+ ///
+ /// The 2D array to create this matrix from.
+ public DenseMatrix(float[,] array)
+ : base(array.GetLength(0), array.GetLength(1))
+ {
+ var rows = array.GetLength(0);
+ var columns = array.GetLength(1);
+ Data = new float[rows * columns];
+ for (var i = 0; i < rows; i++)
+ {
+ for (var j = 0; j < columns; j++)
+ {
+ Data[(j * rows) + i] = array[i, j];
+ }
+ }
+ }
+
+ ///
+ /// Gets the matrix's data.
+ ///
+ /// The matrix's data.
+ internal float[] Data
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Creates a DenseMatrix for the given number of rows and columns.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ ///
+ /// A DenseMatrix with the given dimensions.
+ ///
+ public override Matrix CreateMatrix(int numberOfRows, int numberOfColumns)
+ {
+ return new DenseMatrix(numberOfRows, numberOfColumns);
+ }
+
+ ///
+ /// Creates a with a the given dimension.
+ ///
+ /// The size of the vector.
+ ///
+ /// A with the given dimension.
+ ///
+ public override Vector CreateVector(int size)
+ {
+ return new DenseVector(size);
+ }
+
+ ///
+ /// Retrieves the requested element without range checking.
+ ///
+ ///
+ /// The row of the element.
+ ///
+ ///
+ /// The column of the element.
+ ///
+ ///
+ /// The requested element.
+ ///
+ public override float At(int row, int column)
+ {
+ return Data[(column * RowCount) + row];
+ }
+
+ ///
+ /// Sets the value of the given element.
+ ///
+ ///
+ /// The row of the element.
+ ///
+ ///
+ /// The column of the element.
+ ///
+ ///
+ /// The value to set the element to.
+ ///
+ public override void At(int row, int column, float value)
+ {
+ Data[(column * RowCount) + row] = value;
+ }
+
+ ///
+ /// Sets all values to zero.
+ ///
+ public override void Clear()
+ {
+ Array.Clear(Data, 0, Data.Length);
+ }
+
+ ///
+ /// Returns the transpose of this matrix.
+ ///
+ /// The transpose of this matrix.
+ public override Matrix Transpose()
+ {
+ var ret = new DenseMatrix(ColumnCount, RowCount);
+ for (var j = 0; j < ColumnCount; j++)
+ {
+ var index = j * RowCount;
+ for (var i = 0; i < RowCount; i++)
+ {
+ ret.Data[(i * ColumnCount) + j] = Data[index + i];
+ }
+ }
+
+ return ret;
+ }
+
+ /// Calculates the L1 norm.
+ /// The L1 norm of the matrix.
+ public override double L1Norm()
+ {
+ var norm = 0.0;
+ for (var j = 0; j < ColumnCount; j++)
+ {
+ var s = 0.0;
+ for (var i = 0; i < RowCount; i++)
+ {
+ s += Math.Abs(Data[(j * RowCount) + i]);
+ }
+
+ norm = Math.Max(norm, s);
+ }
+
+ return norm;
+ }
+
+ /// Calculates the Frobenius norm of this matrix.
+ /// The Frobenius norm of this matrix.
+ public override double FrobeniusNorm()
+ {
+ var transpose = (DenseMatrix)Transpose();
+ var aat = this * transpose;
+
+ var norm = 0.0;
+ for (var i = 0; i < RowCount; i++)
+ {
+ norm += Math.Abs(aat.Data[(i * RowCount) + i]);
+ }
+
+ norm = Math.Sqrt(norm);
+ return norm;
+ }
+
+ /// Calculates the infinity norm of this matrix.
+ /// The infinity norm of this matrix.
+ public override double InfinityNorm()
+ {
+ var norm = 0.0;
+ for (var i = 0; i < RowCount; i++)
+ {
+ var s = 0.0;
+ for (var j = 0; j < ColumnCount; j++)
+ {
+ s += Math.Abs(Data[(j * RowCount) + i]);
+ }
+
+ norm = Math.Max(norm, s);
+ }
+
+ return norm;
+ }
+
+ #region Elementary operations
+
+ ///
+ /// Adds another matrix to this matrix. The result will be written into this matrix.
+ ///
+ /// The matrix to add to this matrix.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public override void Add(Matrix other)
+ {
+ var m = other as DenseMatrix;
+ if (m == null)
+ {
+ base.Add(other);
+ }
+ else
+ {
+ Add(m);
+ }
+ }
+
+ ///
+ /// Adds another to this matrix. The result will be written into this matrix.
+ ///
+ /// The to add to this matrix.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public void Add(DenseMatrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (other.RowCount != RowCount || other.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);
+ }
+
+ Control.LinearAlgebraProvider.AddArrays(Data, other.Data, Data);
+ }
+
+ ///
+ /// Subtracts another matrix from this matrix. The result will be written into this matrix.
+ ///
+ /// The matrix to subtract.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public override void Subtract(Matrix other)
+ {
+ var m = other as DenseMatrix;
+ if (m == null)
+ {
+ base.Subtract(other);
+ }
+ else
+ {
+ Subtract(m);
+ }
+ }
+
+ ///
+ /// Subtracts another from this matrix. The result will be written into this matrix.
+ ///
+ /// The to subtract.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public void Subtract(DenseMatrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (other.RowCount != RowCount || other.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);
+ }
+
+ Control.LinearAlgebraProvider.SubtractArrays(Data, other.Data, Data);
+ }
+
+ ///
+ /// Multiplies each element of this matrix with a scalar.
+ ///
+ /// The scalar to multiply with.
+ public override void Multiply(float scalar)
+ {
+ Control.LinearAlgebraProvider.ScaleArray(scalar, Data);
+ }
+
+ ///
+ /// Multiplies this dense matrix with another dense matrix and places the results into the result dense matrix.
+ ///
+ /// The matrix to multiply with.
+ /// The result of the multiplication.
+ /// If the other matrix is .
+ /// If the result matrix is .
+ /// If this.Columns != other.Rows.
+ /// If the result matrix's dimensions are not the this.Rows x other.Columns.
+ public override void Multiply(Matrix other, Matrix result)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (ColumnCount != other.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ if (result.RowCount != RowCount || result.ColumnCount != other.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var m = other as DenseMatrix;
+ var r = result as DenseMatrix;
+
+ if (m == null || r == null)
+ {
+ base.Multiply(other, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.MatrixMultiply(
+ Data,
+ RowCount,
+ ColumnCount,
+ m.Data,
+ m.RowCount,
+ m.ColumnCount,
+ r.Data);
+ }
+ }
+
+ ///
+ /// Multiplies this matrix with another matrix and returns the result.
+ ///
+ /// The matrix to multiply with.
+ /// If this.Columns != other.Rows.
+ /// If the other matrix is .
+ /// The result of multiplication.
+ public override Matrix Multiply(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (ColumnCount != other.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var m = other as DenseMatrix;
+ if (m == null)
+ {
+ return base.Multiply(other);
+ }
+
+ var result = (DenseMatrix)CreateMatrix(RowCount, other.ColumnCount);
+ Multiply(other, result);
+ return result;
+ }
+
+ ///
+ /// Multiplies this dense matrix with transpose of another dense matrix and places the results into the result dense matrix.
+ ///
+ /// The matrix to multiply with.
+ /// The result of the multiplication.
+ /// If the other matrix is .
+ /// If the result matrix is .
+ /// If this.Columns != other.Rows.
+ /// If the result matrix's dimensions are not the this.Rows x other.Columns.
+ public override void TransposeAndMultiply(Matrix other, Matrix result)
+ {
+ var otherDense = other as DenseMatrix;
+ var resultDense = result as DenseMatrix;
+
+ if (otherDense == null || resultDense == null)
+ {
+ base.TransposeAndMultiply(other, result);
+ return;
+ }
+
+ if (ColumnCount != otherDense.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ if ((resultDense.RowCount != RowCount) || (resultDense.ColumnCount != otherDense.RowCount))
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ Control.LinearAlgebraProvider.MatrixMultiplyWithUpdate(
+ Algorithms.LinearAlgebra.Transpose.DontTranspose,
+ Algorithms.LinearAlgebra.Transpose.Transpose,
+ 1.0f,
+ Data,
+ RowCount,
+ ColumnCount,
+ otherDense.Data,
+ otherDense.RowCount,
+ otherDense.ColumnCount,
+ 1.0f,
+ resultDense.Data);
+ }
+
+ ///
+ /// Multiplies this matrix with transpose of another matrix and returns the result.
+ ///
+ /// The matrix to multiply with.
+ /// If this.Columns != other.Rows.
+ /// If the other matrix is .
+ /// The result of multiplication.
+ public override Matrix TransposeAndMultiply(Matrix other)
+ {
+ var otherDense = other as DenseMatrix;
+ if (otherDense == null)
+ {
+ return base.TransposeAndMultiply(other);
+ }
+
+ if (ColumnCount != otherDense.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var result = (DenseMatrix)CreateMatrix(RowCount, other.RowCount);
+ TransposeAndMultiply(other, result);
+ return result;
+ }
+
+ ///
+ /// Multiplies two dense matrices.
+ ///
+ /// The left matrix to multiply.
+ /// The right matrix to multiply.
+ /// The result of multiplication.
+ /// If or is .
+ /// If the dimensions of or don't conform.
+ public static DenseMatrix operator *(DenseMatrix leftSide, DenseMatrix rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide.ColumnCount != rightSide.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ return (DenseMatrix)leftSide.Multiply(rightSide);
+ }
+
+ #endregion
+
+ #region Static constructors for special matrices.
+
+ ///
+ /// Initializes a square with all zero's except for ones on the diagonal.
+ ///
+ /// the size of the square matrix.
+ /// A dense identity matrix.
+ ///
+ /// If is less than one.
+ ///
+ public static DenseMatrix Identity(int order)
+ {
+ var m = new DenseMatrix(order);
+ for (var i = 0; i < order; i++)
+ {
+ m[i, i] = 1.0f;
+ }
+
+ return m;
+ }
+
+ #endregion
+
+ ///
+ /// Negates each element of this matrix.
+ ///
+ public override void Negate()
+ {
+ Multiply(-1);
+ }
+
+ ///
+ /// Generates matrix with random elements.
+ ///
+ /// Number of rows.
+ /// Number of columns.
+ /// Continuous Random Distribution or Source
+ ///
+ /// An numberOfRows-by-numberOfColumns matrix with elements distributed according to the provided distribution.
+ ///
+ /// If the parameter is not positive.
+ /// If the parameter is not positive.
+ public override Matrix Random(int numberOfRows, int numberOfColumns, IContinuousDistribution distribution)
+ {
+ if (numberOfRows < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfRows");
+ }
+
+ if (numberOfColumns < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfColumns");
+ }
+
+ var matrix = CreateMatrix(numberOfRows, numberOfColumns);
+ CommonParallel.For(
+ 0,
+ ColumnCount,
+ j =>
+ {
+ for (var i = 0; i < matrix.RowCount; i++)
+ {
+ matrix[i, j] = (float)distribution.Sample();
+ }
+ });
+
+ return matrix;
+ }
+
+ ///
+ /// Generates matrix with random elements.
+ ///
+ /// Number of rows.
+ /// Number of columns.
+ /// Continuous Random Distribution or Source
+ ///
+ /// An numberOfRows-by-numberOfColumns matrix with elements distributed according to the provided distribution.
+ ///
+ /// If the parameter is not positive.
+ /// If the parameter is not positive.
+ public override Matrix Random(int numberOfRows, int numberOfColumns, IDiscreteDistribution distribution)
+ {
+ if (numberOfRows < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfRows");
+ }
+
+ if (numberOfColumns < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfColumns");
+ }
+
+ var matrix = CreateMatrix(numberOfRows, numberOfColumns);
+ CommonParallel.For(
+ 0,
+ ColumnCount,
+ j =>
+ {
+ for (var i = 0; i < matrix.RowCount; i++)
+ {
+ matrix[i, j] = distribution.Sample();
+ }
+ });
+
+ return matrix;
+ }
+
+ #region Simple arithmetic of type T
+ ///
+ /// Add two values T+T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of addition
+ protected sealed override float AddT(float val1, float val2)
+ {
+ return val1 + val2;
+ }
+
+ ///
+ /// Subtract two values T-T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of subtract
+ protected sealed override float SubtractT(float val1, float val2)
+ {
+ return val1 - val2;
+ }
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Divide two values T/T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of divide
+ protected sealed override float DivideT(float val1, float val2)
+ {
+ return val1 / val2;
+ }
+
+ ///
+ /// Take absolute value
+ ///
+ /// Source alue
+ /// True if one; otherwise false
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/DenseVector.cs b/src/Numerics/LinearAlgebra/Single/DenseVector.cs
new file mode 100644
index 00000000..f1459ece
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/DenseVector.cs
@@ -0,0 +1,1557 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Linq;
+ using Distributions;
+ using Generic;
+ using NumberTheory;
+ using Properties;
+ using Threading;
+
+ ///
+ /// A vector using dense storage.
+ ///
+ public class DenseVector : Vector
+ {
+ ///
+ /// Initializes a new instance of the class with a given size.
+ ///
+ ///
+ /// the size of the vector.
+ ///
+ ///
+ /// If is less than one.
+ ///
+ public DenseVector(int size)
+ : base(size)
+ {
+ Data = new float[size];
+ }
+
+ ///
+ /// Initializes a new instance of the class with a given size
+ /// and each element set to the given value;
+ ///
+ ///
+ /// the size of the vector.
+ ///
+ ///
+ /// the value to set each element to.
+ ///
+ ///
+ /// If is less than one.
+ ///
+ public DenseVector(int size, float value)
+ : this(size)
+ {
+ for (var index = 0; index < Data.Length; index++)
+ {
+ Data[index] = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class by
+ /// copying the values from another.
+ ///
+ ///
+ /// The vector to create the new vector from.
+ ///
+ public DenseVector(Vector other)
+ : this(other.Count)
+ {
+ var vector = other as DenseVector;
+ if (vector == null)
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => this[index] = other[index]);
+ }
+ else
+ {
+ Buffer.BlockCopy(vector.Data, 0, Data, 0, Data.Length * Constants.SizeOfFloat);
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class by
+ /// copying the values from another.
+ ///
+ ///
+ /// The vector to create the new vector from.
+ ///
+ public DenseVector(DenseVector other)
+ : this(other.Count)
+ {
+ Buffer.BlockCopy(other.Data, 0, Data, 0, Data.Length * Constants.SizeOfFloat);
+ }
+
+ ///
+ /// Initializes a new instance of the class for an array.
+ ///
+ /// The array to create this vector from.
+ /// The vector does not copy the array, but keeps a reference to it. Any
+ /// changes to the vector will also change the array.
+ public DenseVector(float[] array) : base(array.Length)
+ {
+ Data = array;
+ }
+
+ ///
+ /// Gets the vector's internal data.
+ ///
+ /// The vector's internal data.
+ /// Changing values in the array also changes the corresponding value in vector. Use with care.
+ internal float[] Data
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Returns a reference to the internal data structure.
+ ///
+ /// The DenseVector whose internal data we are
+ /// returning.
+ ///
+ /// A reference to the internal date of the given vector.
+ ///
+ public static implicit operator float[](DenseVector vector)
+ {
+ if (vector == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ return vector.Data;
+ }
+
+ ///
+ /// Returns a vector bound directly to a reference of the provided array.
+ ///
+ /// The array to bind to the DenseVector object.
+ ///
+ /// A DenseVector whose values are bound to the given array.
+ ///
+ public static implicit operator DenseVector(float[] array)
+ {
+ if (array == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ return new DenseVector(array);
+ }
+
+ ///
+ /// Create a matrix based on this vector in column form (one single column).
+ ///
+ /// This vector as a column matrix.
+ public override Matrix ToColumnMatrix()
+ {
+ var matrix = new DenseMatrix(Count, 1);
+ for (var i = 0; i < Data.Length; i++)
+ {
+ matrix[i, 0] = Data[i];
+ }
+
+ return matrix;
+ }
+
+ ///
+ /// Create a matrix based on this vector in row form (one single row).
+ ///
+ /// This vector as a row matrix.
+ public override Matrix ToRowMatrix()
+ {
+ var matrix = new DenseMatrix(1, Count);
+ for (var i = 0; i < Data.Length; i++)
+ {
+ matrix[0, i] = Data[i];
+ }
+
+ return matrix;
+ }
+
+ /// Gets or sets the value at the given .
+ /// The index of the value to get or set.
+ /// The value of the vector at the given .
+ /// If is negative or
+ /// greater than the size of the vector.
+ public override float this[int index]
+ {
+ get
+ {
+ return Data[index];
+ }
+
+ set
+ {
+ Data[index] = value;
+ }
+ }
+
+ ///
+ /// Creates a matrix with the given dimensions using the same storage type
+ /// as this vector.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ ///
+ /// A matrix with the given dimensions.
+ ///
+ public override Matrix CreateMatrix(int rows, int columns)
+ {
+ return new DenseMatrix(rows, columns);
+ }
+
+ ///
+ /// Creates a Vector of the given size using the same storage type
+ /// as this vector.
+ ///
+ ///
+ /// The size of the Vector to create.
+ ///
+ ///
+ /// The new Vector.
+ ///
+ public override Vector CreateVector(int size)
+ {
+ return new DenseVector(size);
+ }
+
+ ///
+ /// Copies the values of this vector into the target vector.
+ ///
+ ///
+ /// The vector to copy elements into.
+ ///
+ ///
+ /// If is .
+ ///
+ ///
+ /// If is not the same size as this vector.
+ ///
+ public override void CopyTo(Vector target)
+ {
+ if (target == null)
+ {
+ throw new ArgumentNullException("target");
+ }
+
+ if (Count != target.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
+ }
+
+ if (ReferenceEquals(this, target))
+ {
+ return;
+ }
+
+ var otherVector = target as DenseVector;
+ if (otherVector == null)
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => target[index] = Data[index]);
+ }
+ else
+ {
+ Buffer.BlockCopy(Data, 0, otherVector.Data, 0, Data.Length * Constants.SizeOfFloat);
+ }
+ }
+
+ ///
+ /// Adds a scalar to each element of the vector.
+ ///
+ /// The scalar to add.
+ /// A copy of the vector with the scalar added.
+ public override Vector Add(float scalar)
+ {
+ if (scalar == 0.0)
+ {
+ return Clone();
+ }
+
+ var copy = (DenseVector)Clone();
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => copy.Data[index] += scalar);
+ return copy;
+ }
+
+ ///
+ /// Adds a scalar to each element of the vector and stores the result in the result vector.
+ ///
+ /// The scalar to add.
+ /// The vector to store the result of the addition.
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ public override void Add(float scalar, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ var dense = result as DenseVector;
+ if (dense == null)
+ {
+ base.Add(scalar, result);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => dense.Data[index] = Data[index] + scalar);
+ }
+ }
+
+ ///
+ /// Adds another vector to this vector.
+ ///
+ /// The vector to add to this one.
+ /// A new vector containing the sum of both vectors.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ public override Vector Add(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ var denseVector = other as DenseVector;
+
+ if (denseVector == null)
+ {
+ return base.Add(other);
+ }
+
+ var copy = (DenseVector)Clone();
+ Control.LinearAlgebraProvider.AddVectorToScaledVector(copy.Data, 1.0f, denseVector.Data);
+ return copy;
+ }
+
+ ///
+ /// Adds another vector to this vector and stores the result into the result vector.
+ ///
+ /// The vector to add to this one.
+ /// The vector to store the result of the addition.
+ /// If the other vector is .
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ /// If this vector and are not the same size.
+ public override void Add(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ if (ReferenceEquals(this, result) || ReferenceEquals(other, result))
+ {
+ var tmp = Add(other);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ var rdense = result as DenseVector;
+ var odense = other as DenseVector;
+ if (rdense != null && odense != null)
+ {
+ CopyTo(result);
+ Control.LinearAlgebraProvider.AddVectorToScaledVector(rdense.Data, 1.0f, odense.Data);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => result[index] = Data[index] + other[index]);
+ }
+ }
+ }
+
+ ///
+ /// Returns a Vector containing the same values of .
+ ///
+ /// This method is included for completeness.
+ /// The vector to get the values from.
+ /// A vector containing a the same values as .
+ /// If is .
+ public static Vector operator +(DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return rightSide.Plus();
+ }
+
+ ///
+ /// Adds two Vectors together and returns the results.
+ ///
+ /// One of the vectors to add.
+ /// The other vector to add.
+ /// The result of the addition.
+ /// If and are not the same size.
+ /// If or is .
+ public static Vector operator +(DenseVector leftSide, DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.Count != rightSide.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
+ }
+
+ return leftSide.Add(rightSide);
+ }
+
+ ///
+ /// Subtracts a scalar from each element of the vector.
+ ///
+ /// The scalar to subtract.
+ /// A new vector containing the subtraction of this vector and the scalar.
+ public override Vector Subtract(float scalar)
+ {
+ if (scalar == 0.0)
+ {
+ return Clone();
+ }
+
+ var copy = (DenseVector)Clone();
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => copy.Data[index] -= scalar);
+ return copy;
+ }
+
+ ///
+ /// Subtracts a scalar from each element of the vector and stores the result in the result vector.
+ ///
+ /// The scalar to subtract.
+ /// The vector to store the result of the subtraction.
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ public override void Subtract(float scalar, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ var dense = result as DenseVector;
+ if (dense == null)
+ {
+ base.Subtract(scalar, result);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => dense.Data[index] = Data[index] - scalar);
+ }
+ }
+
+ ///
+ /// Subtracts another vector from this vector.
+ ///
+ /// The vector to subtract from this one.
+ /// A new vector containing the subtraction of the the two vectors.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ public override Vector Subtract(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ var denseVector = other as DenseVector;
+
+ if (denseVector == null)
+ {
+ return base.Subtract(other);
+ }
+
+ var copy = (DenseVector)Clone();
+ Control.LinearAlgebraProvider.AddVectorToScaledVector(copy.Data, -1.0f, denseVector.Data);
+ return copy;
+ }
+
+ ///
+ /// Subtracts another vector to this vector and stores the result into the result vector.
+ ///
+ /// The vector to subtract from this one.
+ /// The vector to store the result of the subtraction.
+ /// If the other vector is .
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ /// If this vector and are not the same size.
+ public override void Subtract(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ if (ReferenceEquals(this, result) || ReferenceEquals(other, result))
+ {
+ var tmp = Subtract(other);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ var rdense = result as DenseVector;
+ var odense = other as DenseVector;
+ if (rdense != null && odense != null)
+ {
+ CopyTo(result);
+ Control.LinearAlgebraProvider.AddVectorToScaledVector(rdense.Data, -1.0f, odense.Data);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => result[index] = Data[index] - other[index]);
+ }
+ }
+ }
+
+ ///
+ /// Returns a Vector containing the negated values of .
+ ///
+ /// The vector to get the values from.
+ /// A vector containing the negated values as .
+ /// If is .
+ public static Vector operator -(DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return rightSide.Negate();
+ }
+
+ ///
+ /// Subtracts two Vectors and returns the results.
+ ///
+ /// The vector to subtract from.
+ /// The vector to subtract.
+ /// The result of the subtraction.
+ /// If and are not the same size.
+ /// If or is .
+ public static Vector operator -(DenseVector leftSide, DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.Count != rightSide.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
+ }
+
+ return leftSide.Subtract(rightSide);
+ }
+
+ ///
+ /// Returns a negated vector.
+ ///
+ /// The negated vector.
+ /// Added as an alternative to the unary negation operator.
+ public override Vector Negate()
+ {
+ var result = new DenseVector(Count);
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => result[index] = -Data[index]);
+
+ return result;
+ }
+
+ ///
+ /// Multiplies a scalar to each element of the vector.
+ ///
+ /// The scalar to multiply.
+ /// A new vector that is the multiplication of the vector and the scalar.
+ public override Vector Multiply(float scalar)
+ {
+ if (scalar == 1.0)
+ {
+ return Clone();
+ }
+
+ var copy = (DenseVector)Clone();
+ Control.LinearAlgebraProvider.ScaleArray(scalar, copy.Data);
+ return copy;
+ }
+
+ ///
+ /// Computes the dot product between this vector and another vector.
+ ///
+ /// The other vector to add.
+ /// The result of the addition.
+ /// If is not of the same size.
+ /// If is .
+ public override float DotProduct(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ var denseVector = other as DenseVector;
+
+ if (denseVector == null)
+ {
+ return base.DotProduct(other);
+ }
+
+ return Control.LinearAlgebraProvider.DotProduct(Data, denseVector.Data);
+ }
+
+ ///
+ /// Multiplies a vector with a scalar.
+ ///
+ /// The vector to scale.
+ /// The scalar value.
+ /// The result of the multiplication.
+ /// If is .
+ public static DenseVector operator *(DenseVector leftSide, float rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ return (DenseVector)leftSide.Multiply(rightSide);
+ }
+
+ ///
+ /// Multiplies a vector with a scalar.
+ ///
+ /// The scalar value.
+ /// The vector to scale.
+ /// The result of the multiplication.
+ /// If is .
+ public static DenseVector operator *(float leftSide, DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return (DenseVector)rightSide.Multiply(leftSide);
+ }
+
+ ///
+ /// Computes the dot product between two Vectors.
+ ///
+ /// The left row vector.
+ /// The right column vector.
+ /// The dot product between the two vectors.
+ /// If and are not the same size.
+ /// If or is .
+ public static float operator *(DenseVector leftSide, DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.Count != rightSide.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
+ }
+
+ return Control.LinearAlgebraProvider.DotProduct(leftSide.Data, rightSide.Data);
+ }
+
+ ///
+ /// Divides a vector with a scalar.
+ ///
+ /// The vector to divide.
+ /// The scalar value.
+ /// The result of the division.
+ /// If is .
+ public static DenseVector operator /(DenseVector leftSide, float rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ return (DenseVector)leftSide.Multiply(1f / rightSide);
+ }
+
+ ///
+ /// Returns the index of the absolute minimum element.
+ ///
+ /// The index of absolute minimum element.
+ public override int AbsoluteMinimumIndex()
+ {
+ var index = 0;
+ var min = Math.Abs(Data[index]);
+ for (var i = 1; i < Count; i++)
+ {
+ var test = Math.Abs(Data[i]);
+ if (test < min)
+ {
+ index = i;
+ min = test;
+ }
+ }
+
+ return index;
+ }
+
+ ///
+ /// Returns the value of the absolute minimum element.
+ ///
+ /// The value of the absolute minimum element.
+ public override double AbsoluteMinimum()
+ {
+ return Math.Abs(Data[AbsoluteMinimumIndex()]);
+ }
+
+ ///
+ /// Returns the value of the absolute maximum element.
+ ///
+ /// The value of the absolute maximum element.
+ public override double AbsoluteMaximum()
+ {
+ return Math.Abs(Data[AbsoluteMaximumIndex()]);
+ }
+
+ ///
+ /// Returns the index of the absolute maximum element.
+ ///
+ /// The index of absolute maximum element.
+ public override int AbsoluteMaximumIndex()
+ {
+ var index = 0;
+ var max = Math.Abs(Data[index]);
+ for (var i = 1; i < Count; i++)
+ {
+ var test = Math.Abs(Data[i]);
+ if (test > max)
+ {
+ index = i;
+ max = test;
+ }
+ }
+
+ return index;
+ }
+
+ ///
+ /// Creates a vector containing specified elements.
+ ///
+ /// The first element to begin copying from.
+ /// The number of elements to copy.
+ /// A vector containing a copy of the specified elements.
+ /// - If is not positive or
+ /// greater than or equal to the size of the vector.
+ /// - If + is greater than or equal to the size of the vector.
+ ///
+ /// If is not positive.
+ public override Vector SubVector(int index, int length)
+ {
+ if (index < 0 || index >= Count)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ if (length <= 0)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (index + length > Count)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ var result = new DenseVector(length);
+
+ CommonParallel.For(
+ index,
+ index + length,
+ i => result.Data[i - index] = Data[i]);
+ return result;
+ }
+
+ ///
+ /// Set the values of this vector to the given values.
+ ///
+ /// The array containing the values to use.
+ /// If is .
+ /// If is not the same size as this vector.
+ public override void SetValues(float[] values)
+ {
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+
+ if (values.Length != Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
+ }
+
+ CommonParallel.For(
+ 0,
+ values.Length,
+ i => Data[i] = values[i]);
+ }
+
+ ///
+ /// Returns the index of the absolute maximum element.
+ ///
+ /// The index of absolute maximum element.
+ public override int MaximumIndex()
+ {
+ var index = 0;
+ var max = Data[0];
+ for (var i = 1; i < Count; i++)
+ {
+ if (max < Data[i])
+ {
+ index = i;
+ max = Data[i];
+ }
+ }
+
+ return index;
+ }
+
+ ///
+ /// Returns the index of the minimum element.
+ ///
+ /// The index of minimum element.
+ public override int MinimumIndex()
+ {
+ var index = 0;
+ var min = Data[0];
+ for (var i = 1; i < Count; i++)
+ {
+ if (min > Data[i])
+ {
+ index = i;
+ min = Data[i];
+ }
+ }
+
+ return index;
+ }
+
+ ///
+ /// Computes the sum of the vector's elements.
+ ///
+ /// The sum of the vector's elements.
+ public override float Sum()
+ {
+ float result = 0;
+ for (var i = 0; i < Count; i++)
+ {
+ result += Data[i];
+ }
+
+ return result;
+ }
+
+ ///
+ /// Computes the sum of the absolute value of the vector's elements.
+ ///
+ /// The sum of the absolute value of the vector's elements.
+ public override double SumMagnitudes()
+ {
+ float result = 0;
+ for (var i = 0; i < Count; i++)
+ {
+ result += Math.Abs(Data[i]);
+ }
+
+ return result;
+ }
+
+ ///
+ /// Pointwise multiplies this vector with another vector.
+ ///
+ /// The vector to pointwise multiply with this one.
+ /// A new vector which is the pointwise multiplication of the two vectors.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ public override Vector PointwiseMultiply(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ var denseVector = other as DenseVector;
+
+ if (denseVector == null)
+ {
+ return base.PointwiseMultiply(other);
+ }
+
+ var copy = (DenseVector)Clone();
+ CommonParallel.For(
+ 0,
+ Count,
+ index => copy[index] *= other[index]);
+ return copy;
+ }
+
+ ///
+ /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
+ ///
+ /// The vector to pointwise multiply with this one.
+ /// The vector to store the result of the pointwise multiplication.
+ /// If the other vector is .
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ /// If this vector and are not the same size.
+ public override void PointwiseMultiply(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ if (ReferenceEquals(this, result) || ReferenceEquals(other, result))
+ {
+ var tmp = PointwiseMultiply(other);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ var dense = result as DenseVector;
+ if (dense == null)
+ {
+ base.PointwiseMultiply(other, result);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => dense.Data[index] = Data[index] * other[index]);
+ }
+ }
+ }
+
+ ///
+ /// Pointwise divide this vector with another vector.
+ ///
+ /// The vector to pointwise divide this one by.
+ /// A new vector which is the pointwise division of the two vectors.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ public override Vector PointwiseDivide(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ var denseVector = other as DenseVector;
+
+ if (denseVector == null)
+ {
+ return base.PointwiseMultiply(other);
+ }
+
+ var copy = (DenseVector)Clone();
+ CommonParallel.For(
+ 0,
+ Count,
+ index => copy[index] /= other[index]);
+ return copy;
+ }
+
+ ///
+ /// Pointwise divide this vector with another vector and stores the result into the result vector.
+ ///
+ /// The vector to pointwise divide this one by.
+ /// The vector to store the result of the pointwise division.
+ /// If the other vector is .
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ /// If this vector and are not the same size.
+ public override void PointwiseDivide(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ if (ReferenceEquals(this, result) || ReferenceEquals(other, result))
+ {
+ var tmp = PointwiseDivide(other);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ var dense = result as DenseVector;
+ if (dense == null)
+ {
+ base.PointwiseDivide(other, result);
+ }
+ else
+ {
+ CommonParallel.For(
+ 0,
+ Data.Length,
+ index => dense.Data[index] = Data[index] / other[index]);
+ }
+ }
+ }
+
+ ///
+ /// Outer product of two vectors
+ ///
+ /// First vector
+ /// Second vector
+ /// Matrix M[i,j] = u[i]*v[j]
+ /// If the u vector is .
+ /// If the v vector is .
+ public static DenseMatrix OuterProduct(DenseVector u, DenseVector v)
+ {
+ if (u == null)
+ {
+ throw new ArgumentNullException("u");
+ }
+
+ if (v == null)
+ {
+ throw new ArgumentNullException("v");
+ }
+
+ var matrix = new DenseMatrix(u.Count, v.Count);
+ CommonParallel.For(
+ 0,
+ u.Count,
+ i =>
+ {
+ for (var j = 0; j < v.Count; j++)
+ {
+ matrix.At(i, j, u.Data[i] * v.Data[j]);
+ }
+ });
+ return matrix;
+ }
+
+ ///
+ /// Generates a vector with random elements
+ ///
+ /// Number of elements in the vector.
+ /// Continuous Random Distribution or Source
+ ///
+ /// A vector with n-random elements distributed according
+ /// to the specified random distribution.
+ ///
+ /// If the n vector is non positive.
+ public override Vector Random(int length, IContinuousDistribution randomDistribution)
+ {
+ if (length < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "length");
+ }
+
+ var v = (DenseVector)CreateVector(length);
+ for (var index = 0; index < v.Data.Length; index++)
+ {
+ v.Data[index] = (float)randomDistribution.Sample();
+ }
+
+ return v;
+ }
+
+ ///
+ /// Generates a vector with random elements
+ ///
+ /// Number of elements in the vector.
+ /// Continuous Random Distribution or Source
+ ///
+ /// A vector with n-random elements distributed according
+ /// to the specified random distribution.
+ ///
+ /// If the n vector is non positive.
+ public override Vector Random(int length, IDiscreteDistribution randomDistribution)
+ {
+ if (length < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "length");
+ }
+
+ var v = (DenseVector)CreateVector(length);
+ for (var index = 0; index < v.Data.Length; index++)
+ {
+ v.Data[index] = randomDistribution.Sample();
+ }
+
+ return v;
+ }
+
+ ///
+ /// Tensor Product (Dyadic) of this and another vector.
+ ///
+ /// The vector to operate on.
+ ///
+ /// Matrix M[i,j] = this[i] * v[j].
+ ///
+ ///
+ public Matrix TensorMultiply(DenseVector v)
+ {
+ return OuterProduct(this, v);
+ }
+
+ #region Vector Norms
+
+ ///
+ /// Computes the p-Norm.
+ ///
+ /// The p value.
+ /// Scalar ret = (sum(abs(this[i])^p))^(1/p)
+ public override double Norm(double p)
+ {
+ if (p < 0.0)
+ {
+ throw new ArgumentOutOfRangeException("p");
+ }
+
+ if (1.0 == p)
+ {
+ return CommonParallel.Aggregate(
+ 0,
+ Count,
+ index => Math.Abs(Data[index]));
+ }
+
+ if (2.0 == p)
+ {
+ return Data.Aggregate(0f, SpecialFunctions.Hypotenuse);
+ }
+
+ if (Double.IsPositiveInfinity(p))
+ {
+ return CommonParallel.Select(
+ 0,
+ Count,
+ (index, localData) => Math.Max(localData, Math.Abs(Data[index])),
+ Math.Max);
+ }
+
+ var sum = CommonParallel.Aggregate(
+ 0,
+ Count,
+ index => Math.Pow(Math.Abs(Data[index]), p));
+
+ return Math.Pow(sum, 1.0 / p);
+ }
+
+ ///
+ /// Normalizes this vector to a unit vector with respect to the p-norm.
+ ///
+ ///
+ /// The p value.
+ ///
+ ///
+ /// This vector normalized to a unit vector with respect to the p-norm.
+ ///
+ public override Vector Normalize(double p)
+ {
+ if (p < 0.0)
+ {
+ throw new ArgumentOutOfRangeException("p");
+ }
+
+ var norm = Norm(p);
+ var clone = Clone();
+ if (norm == 0.0)
+ {
+ return clone;
+ }
+
+ clone.Multiply(1.0f / (float)norm, clone);
+
+ return clone;
+ }
+ #endregion
+
+ #region Parse Functions
+
+ ///
+ /// Creates a float dense vector based on a string. The string can be in the following formats (without the
+ /// quotes): 'n', 'n,n,..', '(n,n,..)', '[n,n,...]', where n is a float.
+ ///
+ ///
+ /// A float dense vector containing the values specified by the given string.
+ ///
+ ///
+ /// The string to parse.
+ ///
+ public static DenseVector Parse(string value)
+ {
+ return Parse(value, null);
+ }
+
+ ///
+ /// Creates a float dense vector based on a string. The string can be in the following formats (without the
+ /// quotes): 'n', 'n,n,..', '(n,n,..)', '[n,n,...]', where n is a float.
+ ///
+ ///
+ /// A float dense vector containing the values specified by the given string.
+ ///
+ ///
+ /// the string to parse.
+ ///
+ ///
+ /// An that supplies culture-specific formatting information.
+ ///
+ public static DenseVector Parse(string value, IFormatProvider formatProvider)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(value);
+ }
+
+ value = value.Trim();
+ if (value.Length == 0)
+ {
+ throw new FormatException();
+ }
+
+ // strip out parens
+ if (value.StartsWith("(", StringComparison.Ordinal))
+ {
+ if (!value.EndsWith(")", StringComparison.Ordinal))
+ {
+ throw new FormatException();
+ }
+
+ value = value.Substring(1, value.Length - 2).Trim();
+ }
+
+ if (value.StartsWith("[", StringComparison.Ordinal))
+ {
+ if (!value.EndsWith("]", StringComparison.Ordinal))
+ {
+ throw new FormatException();
+ }
+
+ value = value.Substring(1, value.Length - 2).Trim();
+ }
+
+ // keywords
+ var textInfo = formatProvider.GetTextInfo();
+ var keywords = new[] { textInfo.ListSeparator };
+
+ // lexing
+ var tokens = new LinkedList();
+ GlobalizationHelper.Tokenize(tokens.AddFirst(value), keywords, 0);
+ var token = tokens.First;
+
+ if (token == null || tokens.Count.IsEven())
+ {
+ throw new FormatException();
+ }
+
+ // parsing
+ var data = new float[(tokens.Count + 1) >> 1];
+ for (var i = 0; i < data.Length; i++)
+ {
+ if (token == null || token.Value == textInfo.ListSeparator)
+ {
+ throw new FormatException();
+ }
+
+ data[i] = float.Parse(token.Value, NumberStyles.Any, formatProvider);
+
+ token = token.Next;
+ if (token != null)
+ {
+ token = token.Next;
+ }
+ }
+
+ return new DenseVector(data);
+ }
+
+ ///
+ /// Converts the string representation of a real dense vector to float-precision dense vector equivalent.
+ /// A return value indicates whether the conversion succeeded or failed.
+ ///
+ ///
+ /// A string containing a real vector to convert.
+ ///
+ ///
+ /// The parsed value.
+ ///
+ ///
+ /// If the conversion succeeds, the result will contain a complex number equivalent to value.
+ /// Otherwise the result will be null.
+ ///
+ public static bool TryParse(string value, out DenseVector result)
+ {
+ return TryParse(value, null, out result);
+ }
+
+ ///
+ /// Converts the string representation of a real dense vector to float-precision dense vector equivalent.
+ /// A return value indicates whether the conversion succeeded or failed.
+ ///
+ ///
+ /// A string containing a real vector to convert.
+ ///
+ ///
+ /// An that supplies culture-specific formatting information about value.
+ ///
+ ///
+ /// The parsed value.
+ ///
+ ///
+ /// If the conversion succeeds, the result will contain a complex number equivalent to value.
+ /// Otherwise the result will be null.
+ ///
+ public static bool TryParse(string value, IFormatProvider formatProvider, out DenseVector result)
+ {
+ bool ret;
+ try
+ {
+ result = Parse(value, formatProvider);
+ ret = true;
+ }
+ catch (ArgumentNullException)
+ {
+ result = null;
+ ret = false;
+ }
+ catch (FormatException)
+ {
+ result = null;
+ ret = false;
+ }
+
+ return ret;
+ }
+
+ #endregion
+
+ ///
+ /// Resets all values to zero.
+ ///
+ public override void Clear()
+ {
+ Array.Clear(Data, 0, Data.Length);
+ }
+
+ #region Simple arithmetic of type T
+ ///
+ /// Add two values T+T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of addition
+ protected sealed override float AddT(float val1, float val2)
+ {
+ return val1 + val2;
+ }
+
+ ///
+ /// Subtract two values T-T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of subtract
+ protected sealed override float SubtractT(float val1, float val2)
+ {
+ return val1 - val2;
+ }
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Divide two values T/T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of divide
+ protected sealed override float DivideT(float val1, float val2)
+ {
+ return val1 / val2;
+ }
+
+ ///
+ /// Take absolute value
+ ///
+ /// Source alue
+ /// True if one; otherwise false
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
new file mode 100644
index 00000000..d4b1decd
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
@@ -0,0 +1,1723 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single
+{
+ using System;
+ using System.Linq;
+ using System.Text;
+ using Distributions;
+ using Generic;
+ using Properties;
+ using Threading;
+
+ ///
+ /// A matrix type for diagonal matrices.
+ ///
+ ///
+ /// Diagonal matrices can be non-square matrices but the diagonal always starts
+ /// at element 0,0. A diagonal matrix will throw an exception if non diagonal
+ /// entries are set. The exception to this is when the off diagonal elements are
+ /// 0.0 or NaN; these settings will cause no change to the diagonal matrix.
+ ///
+ public class DiagonalMatrix : Matrix
+ {
+ ///
+ /// Initializes a new instance of the class. This matrix is square with a given size.
+ ///
+ /// the size of the square matrix.
+ ///
+ /// If is less than one.
+ ///
+ public DiagonalMatrix(int order) : base(order)
+ {
+ Data = new float[order * order];
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ public DiagonalMatrix(int rows, int columns) : base(rows, columns)
+ {
+ Data = new float[Math.Min(rows, columns)];
+ }
+
+ ///
+ /// Initializes a new instance of the class with all entries set to a particular value.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ /// The value which we assign to each element of the matrix.
+ public DiagonalMatrix(int rows, int columns, float value) : base(rows, columns)
+ {
+ Data = new float[Math.Min(rows, columns)];
+ for (var i = 0; i < Data.Length; i++)
+ {
+ Data[i] = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class from a one dimensional array with diagonal elements. This constructor
+ /// will reference the one dimensional array and not copy it.
+ ///
+ /// The number of rows.
+ /// The number of columns.
+ /// The one dimensional array which contain diagonal elements.
+ public DiagonalMatrix(int rows, int columns, float[] diagonalArray) : base(rows, columns)
+ {
+ Data = diagonalArray;
+ }
+
+ ///
+ /// Initializes a new instance of the class from a 2D array.
+ ///
+ /// The 2D array to create this matrix from.
+ /// When contains an off-diagonal element.
+ /// Depending on the implementation, an
+ /// may be thrown if one of the indices is outside the dimensions of the matrix.
+ public DiagonalMatrix(float[,] array) : this(array.GetLength(0), array.GetLength(1))
+ {
+ var rows = array.GetLength(0);
+ var columns = array.GetLength(1);
+
+ for (var i = 0; i < rows; i++)
+ {
+ for (var j = 0; j < columns; j++)
+ {
+ if (i == j)
+ {
+ Data[i] = array[i, j];
+ }
+ else if (array[i, j] != 0.0 && !Double.IsNaN(array[i, j]))
+ {
+ throw new IndexOutOfRangeException("Cannot set an off-diagonal element in a diagonal matrix.");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets the matrix's data.
+ ///
+ /// The matrix's data.
+ internal float[] Data
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Retrieves the requested element without range checking.
+ ///
+ ///
+ /// The row of the element.
+ ///
+ ///
+ /// The column of the element.
+ ///
+ ///
+ /// The requested element.
+ ///
+ /// Depending on the implementation, an
+ /// may be thrown if one of the indices is outside the dimensions of the matrix.
+ public override float At(int row, int column)
+ {
+ return row == column ? Data[row] : 0.0f;
+ }
+
+ ///
+ /// Sets the value of the given element.
+ ///
+ ///
+ /// The row of the element.
+ ///
+ ///
+ /// The column of the element.
+ ///
+ ///
+ /// The value to set the element to.
+ ///
+ /// When trying to set an off diagonal element.
+ /// Depending on the implementation, an
+ /// may be thrown if one of the indices is outside the dimensions of the matrix.
+ public override void At(int row, int column, float value)
+ {
+ if (row == column)
+ {
+ Data[row] = value;
+ }
+ else if (value != 0.0 && !Double.IsNaN(value))
+ {
+ throw new IndexOutOfRangeException("Cannot set an off-diagonal element in a diagonal matrix.");
+ }
+ }
+
+ ///
+ /// Creates a DiagonalMatrix for the given number of rows and columns.
+ ///
+ ///
+ /// The number of rows.
+ ///
+ ///
+ /// The number of columns.
+ ///
+ ///
+ /// A DiagonalMatrix with the given dimensions.
+ ///
+ public override Matrix CreateMatrix(int numberOfRows, int numberOfColumns)
+ {
+ return new DiagonalMatrix(numberOfRows, numberOfColumns);
+ }
+
+ ///
+ /// Creates a with a the given dimension.
+ ///
+ /// The size of the vector.
+ ///
+ /// A with the given dimension.
+ ///
+ public override Vector CreateVector(int size)
+ {
+ return new SparseVector(size);
+ }
+
+ ///
+ /// Sets all values to zero.
+ ///
+ public override void Clear()
+ {
+ Array.Clear(Data, 0, Data.Length);
+ }
+
+ ///
+ /// Indicates whether the current object is equal to another object of the same type.
+ ///
+ ///
+ /// An object to compare with this object.
+ ///
+ ///
+ /// true if the current object is equal to the parameter; otherwise, false.
+ ///
+ public override bool Equals(object obj)
+ {
+ var diagonalMatrix = obj as DiagonalMatrix;
+
+ if (diagonalMatrix == null)
+ {
+ return base.Equals(obj);
+ }
+
+ // Accept if the argument is the same object as this
+ if (ReferenceEquals(this, diagonalMatrix))
+ {
+ return true;
+ }
+
+ if (diagonalMatrix.Data.Length != Data.Length)
+ {
+ return false;
+ }
+
+ // If all else fails, perform element wise comparison.
+ return !Data.Where((t, i) => t != diagonalMatrix.Data[i]).Any();
+ }
+
+ ///
+ /// Returns a hash code for this instance.
+ ///
+ ///
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ ///
+ public override int GetHashCode()
+ {
+ var hashNum = Math.Min(Data.Length, 25);
+ long hash = 0;
+ for (var i = 0; i < hashNum; i++)
+ {
+#if SILVERLIGHT
+ hash ^= Precision.DoubleToInt64Bits(Data[i]);
+#else
+ hash ^= BitConverter.DoubleToInt64Bits(Data[i]);
+#endif
+ }
+
+ return BitConverter.ToInt32(BitConverter.GetBytes(hash), 4);
+ }
+
+ #region Elementary operations
+ ///
+ /// Adds another matrix to this matrix. The result will be written into this matrix.
+ ///
+ /// The matrix to add to this matrix.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ /// If is not .
+ public override void Add(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ var m = other as DiagonalMatrix;
+ if (m == null)
+ {
+ throw new ArgumentException(Resources.ArgumentTypeMismatch);
+ }
+
+ Add(m);
+ }
+
+ ///
+ /// Adds another to this matrix. The result will be written into this matrix.
+ ///
+ /// The to add to this matrix.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public void Add(DiagonalMatrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (other.RowCount != RowCount || other.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);
+ }
+
+ Control.LinearAlgebraProvider.AddArrays(Data, other.Data, Data);
+ }
+
+ ///
+ /// Subtracts another matrix from this matrix. The result will be written into this matrix.
+ ///
+ /// The matrix to subtract.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ /// If is not .
+ public override void Subtract(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ var m = other as DiagonalMatrix;
+ if (m == null)
+ {
+ throw new ArgumentException(Resources.ArgumentTypeMismatch);
+ }
+
+ Subtract(m);
+ }
+
+ ///
+ /// Subtracts another from this matrix. The result will be written into this matrix.
+ ///
+ /// The to subtract.
+ /// If the other matrix is .
+ /// If the two matrices don't have the same dimensions.
+ public void Subtract(DiagonalMatrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (other.RowCount != RowCount || other.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException(Resources.ArgumentMatrixDimensions);
+ }
+
+ Control.LinearAlgebraProvider.SubtractArrays(Data, other.Data, Data);
+ }
+
+ ///
+ /// Copies the values of the given array to the diagonal.
+ ///
+ /// The array to copy the values from. The length of the vector should be
+ /// Min(Rows, Columns).
+ /// If is .
+ /// If the length of does not
+ /// equal Min(Rows, Columns).
+ /// For non-square matrices, the elements of are copied to
+ /// this[i,i].
+ public override void SetDiagonal(float[] source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+
+ if (source.Length != Data.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "source");
+ }
+
+ Buffer.BlockCopy(source, 0, Data, 0, source.Length * Constants.SizeOfFloat);
+ }
+
+ ///
+ /// Copies the values of the given to the diagonal.
+ ///
+ /// The vector to copy the values from. The length of the vector should be
+ /// Min(Rows, Columns).
+ /// If is .
+ /// If the length of does not
+ /// equal Min(Rows, Columns).
+ /// For non-square matrices, the elements of are copied to
+ /// this[i,i].
+ public override void SetDiagonal(Vector source)
+ {
+ var denseSource = source as DenseVector;
+ if (denseSource == null)
+ {
+ base.SetDiagonal(source);
+ return;
+ }
+
+ if (Data.Length != denseSource.Data.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "source");
+ }
+
+ Buffer.BlockCopy(denseSource.Data, 0, Data, 0, denseSource.Data.Length * Constants.SizeOfFloat);
+ }
+
+ ///
+ /// Multiplies each element of this matrix with a scalar.
+ ///
+ /// The scalar to multiply with.
+ public override void Multiply(float scalar)
+ {
+ if (scalar == 0.0)
+ {
+ Clear();
+ return;
+ }
+
+ if (scalar == 1.0)
+ {
+ return;
+ }
+
+ Control.LinearAlgebraProvider.ScaleArray(scalar, Data);
+ }
+
+ ///
+ /// Multiplies this diagonal matrix with another diagonal matrix and places the results into the result diagonal matrix.
+ ///
+ /// The matrix to multiply with.
+ /// The result of the multiplication.
+ /// If the other matrix is .
+ /// If the result matrix is .
+ /// If this.Columns != other.Rows.
+ /// If the result matrix's dimensions are not the this.Rows x other.Columns.
+ public override void Multiply(Matrix other, Matrix result)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (ColumnCount != other.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ if (result.RowCount != RowCount || result.ColumnCount != other.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var m = other as DiagonalMatrix;
+ var r = result as DiagonalMatrix;
+
+ if (m == null || r == null)
+ {
+ base.Multiply(other, result);
+ }
+ else
+ {
+ var thisDataCopy = new float[r.Data.Length];
+ var otherDataCopy = new float[r.Data.Length];
+ Buffer.BlockCopy(Data, 0, thisDataCopy, 0, (r.Data.Length > Data.Length) ? Data.Length * Constants.SizeOfFloat : r.Data.Length * Constants.SizeOfFloat);
+ Buffer.BlockCopy(m.Data, 0, otherDataCopy, 0, (r.Data.Length > m.Data.Length) ? m.Data.Length * Constants.SizeOfFloat : r.Data.Length * Constants.SizeOfFloat);
+
+ Control.LinearAlgebraProvider.PointWiseMultiplyArrays(thisDataCopy, otherDataCopy, r.Data);
+ }
+ }
+
+ ///
+ /// Multiplies this matrix with another matrix and returns the result.
+ ///
+ /// The matrix to multiply with.
+ /// If this.Columns != other.Rows.
+ /// If the other matrix is .
+ /// The result of multiplication.
+ public override Matrix Multiply(Matrix other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (ColumnCount != other.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var m = other as DiagonalMatrix;
+ if (m == null)
+ {
+ return base.Multiply(other);
+ }
+
+ var result = (DiagonalMatrix)CreateMatrix(RowCount, other.ColumnCount);
+ Multiply(other, result);
+ return result;
+ }
+
+ ///
+ /// Multiplies this matrix with a vector and places the results into the result matrix.
+ ///
+ /// The vector to multiply with.
+ /// The result of the multiplication.
+ /// If is .
+ /// If is .
+ /// If result.Count != this.RowCount.
+ /// If this.ColumnCount != .Count.
+ public override void Multiply(Vector rightSide, Vector result)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (ColumnCount != rightSide.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "rightSide");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (RowCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ if (ReferenceEquals(rightSide, result))
+ {
+ var tmp = result.CreateVector(result.Count);
+ Multiply(rightSide, tmp);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ // Clear the result vector
+ result.Clear();
+
+ // Multiply the elements in the vector with the corresponding diagonal element in this.
+ for (var r = 0; r < Data.Length; r++)
+ {
+ result[r] = Data[r] * rightSide[r];
+ }
+ }
+ }
+
+ ///
+ /// Left multiply a matrix with a vector ( = vector * matrix ) and place the result in the result vector.
+ ///
+ /// The vector to multiply with.
+ /// The result of the multiplication.
+ /// If is .
+ /// If the result matrix is .
+ /// If result.Count != this.ColumnCount.
+ /// If this.RowCount != .Count.
+ public override void LeftMultiply(Vector leftSide, Vector result)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (RowCount != leftSide.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "leftSide");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (ColumnCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ if (ReferenceEquals(leftSide, result))
+ {
+ var tmp = result.CreateVector(result.Count);
+ LeftMultiply(leftSide, tmp);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ // Clear the result vector
+ result.Clear();
+
+ // Multiply the elements in the vector with the corresponding diagonal element in this.
+ for (var r = 0; r < Data.Length; r++)
+ {
+ result[r] = Data[r] * leftSide[r];
+ }
+ }
+ }
+
+ ///
+ /// Computes the determinant of this matrix.
+ ///
+ /// The determinant of this matrix.
+ public override float Determinant()
+ {
+ if (RowCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ return Data.Aggregate(1.0f, (current, t) => current * t);
+ }
+
+ ///
+ /// Returns the elements of the diagonal in a .
+ ///
+ /// The elements of the diagonal.
+ /// For non-square matrices, the method returns Min(Rows, Columns) elements where
+ /// i == j (i is the row index, and j is the column index).
+ public override Vector Diagonal()
+ {
+ // TODO: Should we return reference to array? In current implementation we return copy of array, so changes in DenseVector will
+ // not influence onto diagonal elements
+ return new DenseVector((float[])Data.Clone());
+ }
+
+ ///
+ /// Multiplies this diagonal matrix with transpose of another diagonal matrix and places the results into the result diagonal matrix.
+ ///
+ /// The matrix to multiply with.
+ /// The result of the multiplication.
+ /// If the other matrix is .
+ /// If the result matrix is .
+ /// If this.Columns != other.Rows.
+ /// If the result matrix's dimensions are not the this.Rows x other.Columns.
+ public override void TransposeAndMultiply(Matrix other, Matrix result)
+ {
+ var otherDiagonal = other as DiagonalMatrix;
+ var resultDiagonal = result as DiagonalMatrix;
+
+ if (otherDiagonal == null || resultDiagonal == null)
+ {
+ base.TransposeAndMultiply(other, result);
+ return;
+ }
+
+ Multiply(otherDiagonal.Transpose(), result);
+ }
+
+ ///
+ /// Multiplies this matrix with transpose of another matrix and returns the result.
+ ///
+ /// The matrix to multiply with.
+ /// If this.Columns != other.Rows.
+ /// If the other matrix is .
+ /// The result of multiplication.
+ public override Matrix TransposeAndMultiply(Matrix other)
+ {
+ var otherDiagonal = other as DiagonalMatrix;
+ if (otherDiagonal == null)
+ {
+ return base.TransposeAndMultiply(other);
+ }
+
+ if (ColumnCount != otherDiagonal.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var result = (DiagonalMatrix)CreateMatrix(RowCount, other.RowCount);
+ TransposeAndMultiply(other, result);
+ return result;
+ }
+
+ ///
+ /// Multiplies two diagonal matrices.
+ ///
+ /// The left matrix to multiply.
+ /// The right matrix to multiply.
+ /// The result of multiplication.
+ /// If or is .
+ /// If the dimensions of or don't conform.
+ public static DiagonalMatrix operator *(DiagonalMatrix leftSide, DiagonalMatrix rightSide)
+ {
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide.ColumnCount != rightSide.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ return (DiagonalMatrix)leftSide.Multiply(rightSide);
+ }
+
+ #endregion
+
+ ///
+ /// Copies the elements of this matrix to the given matrix.
+ ///
+ ///
+ /// The matrix to copy values into.
+ ///
+ ///
+ /// If target is .
+ ///
+ ///
+ /// If this and the target matrix do not have the same dimensions..
+ ///
+ public override void CopyTo(Matrix target)
+ {
+ var diagonalTarget = target as DiagonalMatrix;
+
+ if (diagonalTarget == null)
+ {
+ base.CopyTo(target);
+ return;
+ }
+
+ if (ReferenceEquals(this, target))
+ {
+ return;
+ }
+
+ if (RowCount != target.RowCount || ColumnCount != target.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "target");
+ }
+
+ Buffer.BlockCopy(Data, 0, diagonalTarget.Data, 0, Data.Length * Constants.SizeOfFloat);
+ }
+
+ ///
+ /// Returns the transpose of this matrix.
+ ///
+ /// The transpose of this matrix.
+ public override Matrix Transpose()
+ {
+ var ret = new DiagonalMatrix(ColumnCount, RowCount);
+ Buffer.BlockCopy(Data, 0, ret.Data, 0, Data.Length * Constants.SizeOfFloat);
+ return ret;
+ }
+
+ ///
+ /// Copies the requested column elements into the given vector.
+ ///
+ /// The column to copy elements from.
+ /// The row to start copying from.
+ /// The number of elements to copy.
+ /// The to copy the column into.
+ /// If the result is .
+ /// If is negative,
+ /// or greater than or equal to the number of columns.
+ /// If is negative,
+ /// or greater than or equal to the number of rows.
+ /// If +
+ /// is greater than or equal to the number of rows.
+ /// If is not positive.
+ /// If result.Count < length.
+ public override void Column(int columnIndex, int rowIndex, int length, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (columnIndex >= ColumnCount || columnIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("columnIndex");
+ }
+
+ if (rowIndex >= RowCount || rowIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("rowIndex");
+ }
+
+ if (rowIndex + length > RowCount)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (length < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "length");
+ }
+
+ if (result.Count < length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ // Clear the result and copy the diagonal entry.
+ result.Clear();
+ if (columnIndex >= rowIndex && columnIndex < rowIndex + length && columnIndex < Data.Length)
+ {
+ result[columnIndex - rowIndex] = Data[columnIndex];
+ }
+ }
+
+ ///
+ /// Copies the requested row elements into a new .
+ ///
+ /// The row to copy elements from.
+ /// The column to start copying from.
+ /// The number of elements to copy.
+ /// The to copy the column into.
+ /// If the result is .
+ /// If is negative,
+ /// or greater than or equal to the number of columns.
+ /// If is negative,
+ /// or greater than or equal to the number of rows.
+ /// If +
+ /// is greater than or equal to the number of rows.
+ /// If is not positive.
+ /// If result.Count < length.
+ public override void Row(int rowIndex, int columnIndex, int length, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (rowIndex >= RowCount || rowIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("rowIndex");
+ }
+
+ if (columnIndex >= ColumnCount || columnIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("columnIndex");
+ }
+
+ if (columnIndex + length > ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (length < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "length");
+ }
+
+ if (result.Count < length)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ // Clear the result and copy the diagonal entry.
+ result.Clear();
+ if (rowIndex >= columnIndex && rowIndex < columnIndex + length && rowIndex < Data.Length)
+ {
+ result[rowIndex - columnIndex] = Data[rowIndex];
+ }
+ }
+
+ /// Calculates the L1 norm.
+ /// The L1 norm of the matrix.
+ public override double L1Norm()
+ {
+ return Data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t)));
+ }
+
+ /// Calculates the L2 norm.
+ /// The L2 norm of the matrix.
+ public override double L2Norm()
+ {
+ return Data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t)));
+ }
+
+ /// Calculates the Frobenius norm of this matrix.
+ /// The Frobenius norm of this matrix.
+ public override double FrobeniusNorm()
+ {
+ var norm = Data.Sum(t => t * t);
+ return Math.Sqrt(norm);
+ }
+
+ /// Calculates the infinity norm of this matrix.
+ /// The infinity norm of this matrix.
+ public override double InfinityNorm()
+ {
+ return L1Norm();
+ }
+
+ /// Calculates the condition number of this matrix.
+ /// The condition number of the matrix.
+ public override double ConditionNumber()
+ {
+ var maxSv = float.NegativeInfinity;
+ var minSv = float.PositiveInfinity;
+ foreach (var t in Data)
+ {
+ maxSv = Math.Max(maxSv, Math.Abs(t));
+ minSv = Math.Min(minSv, Math.Abs(t));
+ }
+
+ return maxSv / minSv;
+ }
+
+ /// Computes the inverse of this matrix.
+ /// If is not a square matrix.
+ /// If is singular.
+ /// The inverse of this matrix.
+ public override Matrix Inverse()
+ {
+ if (RowCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ var inverse = (DiagonalMatrix)Clone();
+ for (var i = 0; i < Data.Length; i++)
+ {
+ if (Data[i] != 0.0)
+ {
+ inverse.Data[i] = 1.0f / Data[i];
+ }
+ else
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixNotSingular);
+ }
+ }
+
+ return inverse;
+ }
+
+ ///
+ /// Returns a new matrix containing the lower triangle of this matrix.
+ ///
+ /// The lower triangle of this matrix.
+ public override Matrix LowerTriangle()
+ {
+ return Clone();
+ }
+
+ ///
+ /// Puts the lower triangle of this matrix into the result matrix.
+ ///
+ /// Where to store the lower triangle.
+ /// If is .
+ /// If the result matrix's dimensions are not the same as this matrix.
+ public override void LowerTriangle(Matrix result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ if (ReferenceEquals(this, result))
+ {
+ return;
+ }
+
+ result.Clear();
+ for (var i = 0; i < Data.Length; i++)
+ {
+ result[i, i] = Data[i];
+ }
+ }
+
+ ///
+ /// Returns a new matrix containing the lower triangle of this matrix. The new matrix
+ /// does not contain the diagonal elements of this matrix.
+ ///
+ /// The lower triangle of this matrix.
+ public override Matrix StrictlyLowerTriangle()
+ {
+ return new DiagonalMatrix(RowCount, ColumnCount);
+ }
+
+ ///
+ /// Puts the strictly lower triangle of this matrix into the result matrix.
+ ///
+ /// Where to store the lower triangle.
+ /// If is .
+ /// If the result matrix's dimensions are not the same as this matrix.
+ public override void StrictlyLowerTriangle(Matrix result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ result.Clear();
+ }
+
+ ///
+ /// Returns a new matrix containing the upper triangle of this matrix.
+ ///
+ /// The upper triangle of this matrix.
+ public override Matrix UpperTriangle()
+ {
+ return Clone();
+ }
+
+ ///
+ /// Puts the upper triangle of this matrix into the result matrix.
+ ///
+ /// Where to store the lower triangle.
+ /// If is .
+ /// If the result matrix's dimensions are not the same as this matrix.
+ public override void UpperTriangle(Matrix result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ result.Clear();
+ for (var i = 0; i < Data.Length; i++)
+ {
+ result[i, i] = Data[i];
+ }
+ }
+
+ ///
+ /// Returns a new matrix containing the upper triangle of this matrix. The new matrix
+ /// does not contain the diagonal elements of this matrix.
+ ///
+ /// The upper triangle of this matrix.
+ public override Matrix StrictlyUpperTriangle()
+ {
+ return new DiagonalMatrix(RowCount, ColumnCount);
+ }
+
+ ///
+ /// Puts the strictly upper triangle of this matrix into the result matrix.
+ ///
+ /// Where to store the lower triangle.
+ /// If is .
+ /// If the result matrix's dimensions are not the same as this matrix.
+ public override void StrictlyUpperTriangle(Matrix result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ result.Clear();
+ }
+
+ ///
+ /// Creates a matrix that contains the values from the requested sub-matrix.
+ ///
+ /// The row to start copying from.
+ /// The number of rows to copy. Must be positive.
+ /// The column to start copying from.
+ /// The number of columns to copy. Must be positive.
+ /// The requested sub-matrix.
+ /// If: - is
+ /// negative, or greater than or equal to the number of rows.
+ /// - is negative, or greater than or equal to the number
+ /// of columns.
+ /// - (columnIndex + columnLength) >= Columns
+ /// - (rowIndex + rowLength) >= Rows
+ /// If or
+ /// is not positive.
+ public override Matrix SubMatrix(int rowIndex, int rowLength, int columnIndex, int columnLength)
+ {
+ if (rowIndex >= RowCount || rowIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("rowIndex");
+ }
+
+ if (columnIndex >= ColumnCount || columnIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("columnIndex");
+ }
+
+ if (rowLength < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "rowLength");
+ }
+
+ if (columnLength < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "columnLength");
+ }
+
+ var colMax = columnIndex + columnLength;
+ var rowMax = rowIndex + rowLength;
+
+ if (rowMax > RowCount)
+ {
+ throw new ArgumentOutOfRangeException("rowLength");
+ }
+
+ if (colMax > ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException("columnLength");
+ }
+
+ var result = new SparseMatrix(rowLength, columnLength);
+
+ if (rowIndex > columnIndex && columnIndex + columnLength > rowIndex)
+ {
+ for (var i = 0; rowIndex - columnIndex + i < Math.Min(columnLength, rowLength); i++)
+ {
+ result[i, rowIndex - columnIndex + i] = Data[rowIndex + i];
+ }
+ }
+ else if (rowIndex < columnIndex && rowIndex + rowLength > columnIndex)
+ {
+ for (var i = 0; rowIndex - columnIndex + i < Math.Min(columnLength, rowLength); i++)
+ {
+ result[columnIndex - rowIndex + i, i] = Data[columnIndex + i];
+ }
+ }
+ else
+ {
+ for (var i = 0; i < Math.Min(columnLength, rowLength); i++)
+ {
+ result[i, i] = Data[rowIndex + i];
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Returns this matrix as a multidimensional array.
+ ///
+ /// A multidimensional containing the values of this matrix.
+ public override float[,] ToArray()
+ {
+ var result = new float[RowCount, ColumnCount];
+ for (var i = 0; i < Data.Length; i++)
+ {
+ result[i, i] = Data[i];
+ }
+
+ return result;
+ }
+
+ ///
+ /// Creates a new and inserts the given column at the given index.
+ ///
+ /// The index of where to insert the column.
+ /// The column to insert.
+ /// A new with the inserted column.
+ /// If is .
+ /// If is < zero or > the number of columns.
+ /// If the size of != the number of rows.
+ public override Matrix InsertColumn(int columnIndex, Vector column)
+ {
+ if (column == null)
+ {
+ throw new ArgumentNullException("column");
+ }
+
+ if (columnIndex < 0 || columnIndex > ColumnCount)
+ {
+ throw new ArgumentOutOfRangeException("columnIndex");
+ }
+
+ if (column.Count != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "column");
+ }
+
+ var result = new SparseMatrix(RowCount, ColumnCount + 1);
+
+ for (var i = 0; i < columnIndex; i++)
+ {
+ result.SetColumn(i, Column(i));
+ }
+
+ result.SetColumn(columnIndex, column);
+
+ for (var i = columnIndex + 1; i < ColumnCount + 1; i++)
+ {
+ result.SetColumn(i, Column(i - 1));
+ }
+
+ return result;
+ }
+
+ ///
+ /// Creates a new and inserts the given row at the given index.
+ ///
+ /// The index of where to insert the row.
+ /// The row to insert.
+ /// A new with the inserted column.
+ /// If is .
+ /// If is < zero or > the number of rows.
+ /// If the size of != the number of columns.
+ public override Matrix InsertRow(int rowIndex, Vector row)
+ {
+ if (row == null)
+ {
+ throw new ArgumentNullException("row");
+ }
+
+ if (rowIndex < 0 || rowIndex > RowCount)
+ {
+ throw new ArgumentOutOfRangeException("rowIndex");
+ }
+
+ if (row.Count != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "row");
+ }
+
+ var result = new SparseMatrix(RowCount + 1, ColumnCount);
+
+ for (var i = 0; i < rowIndex; i++)
+ {
+ result.SetRow(i, Row(i));
+ }
+
+ result.SetRow(rowIndex, row);
+
+ for (var i = rowIndex + 1; i < RowCount; i++)
+ {
+ result.SetRow(i, Row(i - 1));
+ }
+
+ return result;
+ }
+
+ ///
+ /// Stacks this matrix on top of the given matrix and places the result into the result .
+ ///
+ /// The matrix to stack this matrix upon.
+ /// The combined .
+ /// If lower is .
+ /// If upper.Columns != lower.Columns.
+ public override Matrix Stack(Matrix lower)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ if (lower.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "lower");
+ }
+
+ var result = new SparseMatrix(RowCount + lower.RowCount, ColumnCount);
+ Stack(lower, result);
+ return result;
+ }
+
+ ///
+ /// Stacks this matrix on top of the given matrix and places the result into the result .
+ ///
+ /// The matrix to stack this matrix upon.
+ /// The combined .
+ /// If lower is .
+ /// If upper.Columns != lower.Columns.
+ public override void Stack(Matrix lower, Matrix result)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ if (lower.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "lower");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != (RowCount + lower.RowCount) || result.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ // Clear the result matrix
+ result.Clear();
+
+ // Copy the diagonal part into the result matrix.
+ for (var i = 0; i < Data.Length; i++)
+ {
+ result[i, i] = Data[i];
+ }
+
+ // Copy the lower matrix into the result matrix.
+ for (var i = 0; i < lower.RowCount; i++)
+ {
+ for (var j = 0; j < lower.ColumnCount; j++)
+ {
+ result[i + RowCount, j] = lower[i, j];
+ }
+ }
+ }
+
+ ///
+ /// Concatenates this matrix with the given matrix.
+ ///
+ /// The matrix to concatenate.
+ /// The combined .
+ public override Matrix Append(Matrix right)
+ {
+ if (right == null)
+ {
+ throw new ArgumentNullException("right");
+ }
+
+ if (right.RowCount != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ var result = new SparseMatrix(RowCount, ColumnCount + right.ColumnCount);
+ Append(right, result);
+ return result;
+ }
+
+ ///
+ /// Concatenates this matrix with the given matrix and places the result into the result .
+ ///
+ /// The matrix to concatenate.
+ /// The combined .
+ public override void Append(Matrix right, Matrix result)
+ {
+ if (right == null)
+ {
+ throw new ArgumentNullException("right");
+ }
+
+ if (right.RowCount != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.ColumnCount != (ColumnCount + right.ColumnCount) || result.RowCount != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ // Clear the result matrix
+ result.Clear();
+
+ // Copy the diagonal part into the result matrix.
+ for (var i = 0; i < Data.Length; i++)
+ {
+ result[i, i] = Data[i];
+ }
+
+ // Copy the lower matrix into the result matrix.
+ for (var i = 0; i < right.RowCount; i++)
+ {
+ for (var j = 0; j < right.ColumnCount; j++)
+ {
+ result[i, j + RowCount] = right[i, j];
+ }
+ }
+ }
+
+ ///
+ /// Diagonally stacks his matrix on top of the given matrix. The new matrix is a M-by-N matrix,
+ /// where M = this.Rows + lower.Rows and N = this.Columns + lower.Columns.
+ /// The values of off the off diagonal matrices/blocks are set to zero.
+ ///
+ /// The lower, right matrix.
+ /// If lower is .
+ /// the combined matrix
+ public override Matrix DiagonalStack(Matrix lower)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ var result = new SparseMatrix(RowCount + lower.RowCount, ColumnCount + lower.ColumnCount);
+ DiagonalStack(lower, result);
+ return result;
+ }
+
+ ///
+ /// Diagonally stacks his matrix on top of the given matrix and places the combined matrix into the result matrix.
+ ///
+ /// The lower, right matrix.
+ /// The combined matrix
+ /// If lower is .
+ /// If the result matrix is .
+ /// If the result matrix's dimensions are not (this.Rows + lower.rows) x (this.Columns + lower.Columns).
+ public override void DiagonalStack(Matrix lower, Matrix result)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != RowCount + lower.RowCount || result.ColumnCount != ColumnCount + lower.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ // Clear the result matrix
+ result.Clear();
+
+ // Copy the diagonal part into the result matrix.
+ for (var i = 0; i < Data.Length; i++)
+ {
+ result[i, i] = Data[i];
+ }
+
+ // Copy the lower matrix into the result matrix.
+ CommonParallel.For(0, lower.RowCount, i => CommonParallel.For(0, lower.ColumnCount, j => result.At(i + RowCount, j + ColumnCount, lower.At(i, j))));
+ }
+
+ ///
+ /// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
+ ///
+ /// The matrix to pointwise multiply with this one.
+ /// The matrix to store the result of the pointwise multiplication.
+ /// If the other matrix is .
+ /// If the result matrix is .
+ /// If this matrix and are not the same size.
+ /// If this matrix and are not the same size.
+ public override void PointwiseMultiply(Matrix other, Matrix result)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ if (ColumnCount != result.ColumnCount || RowCount != result.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
+ }
+
+ var m = other as DiagonalMatrix;
+ var r = result as DiagonalMatrix;
+
+ if (m == null || r == null)
+ {
+ base.PointwiseMultiply(other, result);
+ }
+ else
+ {
+ Control.LinearAlgebraProvider.PointWiseMultiplyArrays(Data, m.Data, r.Data);
+ }
+ }
+
+ ///
+ /// Permute the columns of a matrix according to a permutation.
+ ///
+ /// The column permutation to apply to this matrix.
+ /// Always thrown
+ /// Permutation in diagonal matrix are senseless, because of matrix nature
+ public override void PermuteColumns(Permutation p)
+ {
+ throw new InvalidOperationException("Permutations in diagonal matrix are not allowed");
+ }
+
+ ///
+ /// Permute the rows of a matrix according to a permutation.
+ ///
+ /// The row permutation to apply to this matrix.
+ /// Always thrown
+ /// Permutation in diagonal matrix are senseless, because of matrix nature
+ public override void PermuteRows(Permutation p)
+ {
+ throw new InvalidOperationException("Permutations in diagonal matrix are not allowed");
+ }
+ #region Static constructors for special matrices.
+
+ ///
+ /// Initializes a square with all zero's except for ones on the diagonal.
+ ///
+ /// the size of the square matrix.
+ /// A diagonal identity matrix.
+ ///
+ /// If is less than one.
+ ///
+ public static DiagonalMatrix Identity(int order)
+ {
+ var m = new DiagonalMatrix(order);
+ for (var i = 0; i < order; i++)
+ {
+ m.Data[i] = 1.0f;
+ }
+
+ return m;
+ }
+
+ #endregion
+
+ ///
+ /// Negates each element of this matrix.
+ ///
+ public override void Negate()
+ {
+ Multiply(-1);
+ }
+
+ ///
+ /// Generates matrix with random elements.
+ ///
+ /// Number of rows.
+ /// Number of columns.
+ /// Continuous Random Distribution or Source
+ ///
+ /// An numberOfRows-by-numberOfColumns matrix with elements distributed according to the provided distribution.
+ ///
+ /// If the parameter is not positive.
+ /// If the parameter is not positive.
+ public override Matrix Random(int numberOfRows, int numberOfColumns, IContinuousDistribution distribution)
+ {
+ if (numberOfRows < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfRows");
+ }
+
+ if (numberOfColumns < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfColumns");
+ }
+
+ var matrix = CreateMatrix(numberOfRows, numberOfColumns);
+ var mn = Math.Min(numberOfRows, numberOfColumns);
+ CommonParallel.For(0, mn, i => matrix[i, i] = (float)distribution.Sample());
+
+ return matrix;
+ }
+
+ ///
+ /// Generates matrix with random elements.
+ ///
+ /// Number of rows.
+ /// Number of columns.
+ /// Continuous Random Distribution or Source
+ ///
+ /// An numberOfRows-by-numberOfColumns matrix with elements distributed according to the provided distribution.
+ ///
+ /// If the parameter is not positive.
+ /// If the parameter is not positive.
+ public override Matrix Random(int numberOfRows, int numberOfColumns, IDiscreteDistribution distribution)
+ {
+ if (numberOfRows < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfRows");
+ }
+
+ if (numberOfColumns < 1)
+ {
+ throw new ArgumentException(Resources.ArgumentMustBePositive, "numberOfColumns");
+ }
+
+ var matrix = CreateMatrix(numberOfRows, numberOfColumns);
+ CommonParallel.For(
+ 0,
+ ColumnCount,
+ j =>
+ {
+ for (var i = 0; i < matrix.RowCount; i++)
+ {
+ matrix[i, j] = distribution.Sample();
+ }
+ });
+
+ return matrix;
+ }
+
+ ///
+ /// Returns a that represents this instance.
+ ///
+ ///
+ /// The format to use.
+ ///
+ ///
+ /// The format provider to use.
+ ///
+ ///
+ /// A that represents this instance.
+ ///
+ public override string ToString(string format, IFormatProvider formatProvider)
+ {
+ var stringBuilder = new StringBuilder();
+ for (var row = 0; row < RowCount; row++)
+ {
+ for (var column = 0; column < ColumnCount; column++)
+ {
+ stringBuilder.Append(At(row, column).ToString(format, formatProvider));
+ if (column != ColumnCount - 1)
+ {
+ stringBuilder.Append(formatProvider.GetTextInfo().ListSeparator);
+ }
+ }
+
+ if (row != RowCount - 1)
+ {
+ stringBuilder.Append(Environment.NewLine);
+ }
+ }
+
+ return stringBuilder.ToString();
+ }
+
+ #region Simple arithmetic of type T
+ ///
+ /// Add two values T+T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of addition
+ protected sealed override float AddT(float val1, float val2)
+ {
+ return val1 + val2;
+ }
+
+ ///
+ /// Subtract two values T-T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of subtract
+ protected sealed override float SubtractT(float val1, float val2)
+ {
+ return val1 - val2;
+ }
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Divide two values T/T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of divide
+ protected sealed override float DivideT(float val1, float val2)
+ {
+ return val1 / val2;
+ }
+
+ ///
+ /// Take absolute value
+ ///
+ /// Source alue
+ /// True if one; otherwise false
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs b/src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs
new file mode 100644
index 00000000..2463a627
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs
@@ -0,0 +1,212 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of a Cholesky factorization for dense matrices.
+ /// For a symmetric, positive definite matrix A, the Cholesky factorization
+ /// is an lower triangular matrix L so that A = L*L'.
+ ///
+ ///
+ /// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
+ /// or positive definite, the constructor will throw an exception.
+ ///
+ public class DenseCholesky : Cholesky
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// Cholesky factorization when the constructor is called and cache it's factorization.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ /// If is not a square matrix.
+ /// If is not positive definite.
+ public DenseCholesky(DenseMatrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount != matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
+ var factor = (DenseMatrix)matrix.Clone();
+ Control.LinearAlgebraProvider.CholeskyFactor(factor.Data, factor.RowCount);
+ CholeskyFactor = factor;
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A Cholesky factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (result.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ if (result.ColumnCount != input.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ if (input.RowCount != CholeskyFactor.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var dinput = input as DenseMatrix;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do Cholesky factorization for dense matrices at the moment.");
+ }
+
+ var dresult = result as DenseMatrix;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do Cholesky factorization for dense matrices at the moment.");
+ }
+
+ // Copy the contents of input to result.
+ Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfFloat);
+
+ // Cholesky solve by overwriting result.
+ var dfactor = (DenseMatrix)CholeskyFactor;
+ Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, dresult.RowCount, dresult.ColumnCount);
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A Cholesky factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (input.Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ if (input.Count != CholeskyFactor.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var dinput = input as DenseVector;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do Cholesky factorization for dense vectors at the moment.");
+ }
+
+ var dresult = result as DenseVector;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do Cholesky factorization for dense vectors at the moment.");
+ }
+
+ // Copy the contents of input to result.
+ Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfFloat);
+
+ // Cholesky solve by overwriting result.
+ var dfactor = (DenseMatrix)CholeskyFactor;
+ Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, dresult.Count, 1);
+ }
+
+ #region Simple arithmetic of type T
+ ///
+ /// Add two values T+T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of addition
+ protected sealed override float AddT(float val1, float val2)
+ {
+ return val1 + val2;
+ }
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the natural (base e) logarithm of a specified number.
+ ///
+ /// A number whose logarithm is to be found
+ /// Natural (base e) logarithm
+ protected sealed override float LogT(float val1)
+ {
+ return (float)Math.Log(val1);
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/DenseLU.cs b/src/Numerics/LinearAlgebra/Single/Factorization/DenseLU.cs
new file mode 100644
index 00000000..f4dcebe2
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/DenseLU.cs
@@ -0,0 +1,204 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of an LU factorization.
+ /// For a matrix A, the LU factorization is a pair of lower triangular matrix L and
+ /// upper triangular matrix U so that A = L*U.
+ ///
+ ///
+ /// The computation of the LU factorization is done at construction time.
+ ///
+ public class DenseLU : LU
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// LU factorization when the constructor is called and cache it's factorization.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ /// If is not a square matrix.
+ public DenseLU(DenseMatrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount != matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ // Create an array for the pivot indices.
+ Pivots = new int[matrix.RowCount];
+
+ // Create a new matrix for the LU factors, then perform factorization (while overwriting).
+ var factors = (DenseMatrix)matrix.Clone();
+ Control.LinearAlgebraProvider.LUFactor(factors.Data, factors.RowCount, Pivots);
+ Factors = factors;
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A LU factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (result.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ if (result.ColumnCount != input.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ if (input.RowCount != Factors.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var dinput = input as DenseMatrix;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do LU factorization for dense matrices at the moment.");
+ }
+
+ var dresult = result as DenseMatrix;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do LU factorization for dense matrices at the moment.");
+ }
+
+ // Copy the contents of input to result.
+ Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfFloat);
+
+ // LU solve by overwriting result.
+ var dfactors = (DenseMatrix)Factors;
+ Control.LinearAlgebraProvider.LUSolveFactored(input.ColumnCount, dfactors.Data, dfactors.RowCount, Pivots, dresult.Data);
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A LU factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (input.Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ if (input.Count != Factors.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var dinput = input as DenseVector;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do LU factorization for dense vectors at the moment.");
+ }
+
+ var dresult = result as DenseVector;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do LU factorization for dense vectors at the moment.");
+ }
+
+ // Copy the contents of input to result.
+ Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfFloat);
+
+ // LU solve by overwriting result.
+ var dfactors = (DenseMatrix)Factors;
+ Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Data);
+ }
+
+ ///
+ /// Returns the inverse of this matrix. The inverse is calculated using LU decomposition.
+ ///
+ /// The inverse of this matrix.
+ public override Matrix Inverse()
+ {
+ var result = (DenseMatrix)Factors.Clone();
+ Control.LinearAlgebraProvider.LUInverseFactored(result.Data, result.RowCount, Pivots);
+ return result;
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs b/src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs
new file mode 100644
index 00000000..6936dd21
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs
@@ -0,0 +1,194 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of the QR decomposition.
+ /// Any real square matrix A may be decomposed as A = QR where Q is an orthogonal matrix
+ /// (its columns are orthogonal unit vectors meaning QTQ = I) and R is an upper triangular matrix
+ /// (also called right triangular matrix).
+ ///
+ ///
+ /// The computation of the QR decomposition is done at construction time by Householder transformation.
+ ///
+ public class DenseQR : QR
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// QR factorization when the constructor is called and cache it's factorization.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ /// If row count is less then column count
+ public DenseQR(DenseMatrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount < matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ MatrixR = matrix.Clone();
+ MatrixQ = new DenseMatrix(matrix.RowCount);
+ Control.LinearAlgebraProvider.QRFactor(((DenseMatrix)MatrixR).Data, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix)MatrixQ).Data);
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A QR factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // The solution X should have the same number of columns as B
+ if (input.ColumnCount != result.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
+ if (MatrixR.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ // The solution X row dimension is equal to the column dimension of A
+ if (MatrixR.ColumnCount != result.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ var dinput = input as DenseMatrix;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do QR factorization for dense matrices at the moment.");
+ }
+
+ var dresult = result as DenseMatrix;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do QR factorization for dense matrices at the moment.");
+ }
+
+ Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, dinput.Data, input.ColumnCount, dresult.Data);
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A QR factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Ax=b where A is an m x n matrix
+ // Check that b is a column vector with m entries
+ if (MatrixR.RowCount != input.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ // Check that x is a column vector with n entries
+ if (MatrixR.ColumnCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var dinput = input as DenseVector;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do QR factorization for dense vectors at the moment.");
+ }
+
+ var dresult = result as DenseVector;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do QR factorization for dense vectors at the moment.");
+ }
+
+ Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, dinput.Data, 1, dresult.Data);
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the absolute value of a specified number.
+ ///
+ /// A number whose absolute is to be found
+ /// Absolute value
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/DenseSvd.cs b/src/Numerics/LinearAlgebra/Single/Factorization/DenseSvd.cs
new file mode 100644
index 00000000..d791c857
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/DenseSvd.cs
@@ -0,0 +1,206 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of the singular value decomposition (SVD) for .
+ /// Suppose M is an m-by-n matrix whose entries are real numbers.
+ /// Then there exists a factorization of the form M = UΣVT where:
+ /// - U is an m-by-m unitary matrix;
+ /// - Σ is m-by-n diagonal matrix with nonnegative real numbers on the diagonal;
+ /// - VT denotes transpose of V, an n-by-n unitary matrix;
+ /// Such a factorization is called a singular-value decomposition of M. A common convention is to order the diagonal
+ /// entries Σ(i,i) in descending order. In this case, the diagonal matrix Σ is uniquely determined
+ /// by M (though the matrices U and V are not). The diagonal entries of Σ are known as the singular values of M.
+ ///
+ ///
+ /// The computation of the singular value decomposition is done at construction time.
+ ///
+ public class DenseSvd : Svd
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// the singular value decomposition when the constructor is called and cache it's decomposition.
+ ///
+ /// The matrix to factor.
+ /// Compute the singular U and VT vectors or not.
+ /// If is null.
+ /// If SVD algorithm failed to converge with matrix .
+ public DenseSvd(DenseMatrix matrix, bool computeVectors)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ ComputeVectors = computeVectors;
+ var nm = Math.Min(matrix.RowCount, matrix.ColumnCount);
+ VectorS = new DenseVector(nm);
+ MatrixU = new DenseMatrix(matrix.RowCount);
+ MatrixVT = new DenseMatrix(matrix.ColumnCount);
+ Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A SVD factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (!ComputeVectors)
+ {
+ throw new InvalidOperationException(Resources.SingularVectorsNotComputed);
+ }
+
+ // The solution X should have the same number of columns as B
+ if (input.ColumnCount != result.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
+ if (MatrixU.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ // The solution X row dimension is equal to the column dimension of A
+ if (MatrixVT.ColumnCount != result.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ var dinput = input as DenseMatrix;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do SVD factorization for dense matrices at the moment.");
+ }
+
+ var dresult = result as DenseMatrix;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do SVD factorization for dense matrices at the moment.");
+ }
+
+ Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A SVD factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (!ComputeVectors)
+ {
+ throw new InvalidOperationException(Resources.SingularVectorsNotComputed);
+ }
+
+ // Ax=b where A is an m x n matrix
+ // Check that b is a column vector with m entries
+ if (MatrixU.RowCount != input.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ // Check that x is a column vector with n entries
+ if (MatrixVT.ColumnCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var dinput = input as DenseVector;
+ if (dinput == null)
+ {
+ throw new NotImplementedException("Can only do SVD factorization for dense vectors at the moment.");
+ }
+
+ var dresult = result as DenseVector;
+ if (dresult == null)
+ {
+ throw new NotImplementedException("Can only do SVD factorization for dense vectors at the moment.");
+ }
+
+ Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, 1, dresult.Data);
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the absolute value of a specified number.
+ ///
+ /// A number whose absolute is to be found
+ /// Absolute value
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs
new file mode 100644
index 00000000..a84c7362
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs
@@ -0,0 +1,311 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization.
+ /// Any real square matrix A may be decomposed as A = QR where Q is an orthogonal mxn matrix and R is an nxn upper triangular matrix.
+ ///
+ ///
+ /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization.
+ ///
+ public class GramSchmidt : QR
+ {
+ ///
+ /// Initializes a new instance of the class. This object creates an orthogonal matrix
+ /// using the modified Gram-Schmidt method.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ /// If row count is less then column count
+ /// If is rank deficient
+ public GramSchmidt(Matrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount < matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ MatrixQ = matrix.Clone();
+ MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount);
+
+ for (var k = 0; k < MatrixQ.ColumnCount; k++)
+ {
+ var norm = (float)MatrixQ.Column(k).Norm(2);
+ if (norm == 0.0)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);
+ }
+
+ MatrixR.At(k, k, norm);
+ for (var i = 0; i < MatrixQ.RowCount; i++)
+ {
+ MatrixQ.At(i, k, MatrixQ.At(i, k) / norm);
+ }
+
+ for (var j = k + 1; j < MatrixQ.ColumnCount; j++)
+ {
+ var dot = MatrixQ.Column(k).DotProduct(MatrixQ.Column(j));
+ MatrixR.At(k, j, dot);
+ for (var i = 0; i < MatrixQ.RowCount; i++)
+ {
+ var value = MatrixQ.At(i, j) - (MatrixQ.At(i, k) * dot);
+ MatrixQ.At(i, j, value);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the matrix is full rank or not.
+ ///
+ /// true if the matrix is full rank; otherwise false.
+ public override bool IsFullRank
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets the determinant of the matrix for which the QR matrix was computed.
+ ///
+ public override double Determinant
+ {
+ get
+ {
+ if (MatrixQ.RowCount != MatrixQ.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ var det = 1.0;
+ for (var i = 0; i < MatrixR.ColumnCount; i++)
+ {
+ det *= MatrixR.At(i, i);
+ if (Math.Abs(MatrixR.At(i, i)).AlmostEqualInDecimalPlaces(0.0f, 7))
+ {
+ return 0;
+ }
+ }
+
+ return Math.Abs(det);
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A QR factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // The solution X should have the same number of columns as B
+ if (input.ColumnCount != result.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
+ if (MatrixQ.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ // The solution X row dimension is equal to the column dimension of A
+ if (MatrixQ.ColumnCount != result.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ var inputCopy = input.Clone();
+
+ // Compute Y = transpose(Q)*B
+ var column = new float[MatrixQ.RowCount];
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ for (var k = 0; k < MatrixQ.RowCount; k++)
+ {
+ column[k] = inputCopy.At(k, j);
+ }
+
+ for (var i = 0; i < MatrixQ.ColumnCount; i++)
+ {
+ float s = 0;
+ for (var k = 0; k < MatrixQ.RowCount; k++)
+ {
+ s += MatrixQ.At(k, i) * column[k];
+ }
+
+ inputCopy.At(i, j, s);
+ }
+ }
+
+ // Solve R*X = Y;
+ for (var k = MatrixQ.ColumnCount - 1; k >= 0; k--)
+ {
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ inputCopy.At(k, j, inputCopy.At(k, j) / MatrixR.At(k, k));
+ }
+
+ for (var i = 0; i < k; i++)
+ {
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ inputCopy.At(i, j, inputCopy.At(i, j) - (inputCopy.At(k, j) * MatrixR.At(i, k)));
+ }
+ }
+ }
+
+ for (var i = 0; i < MatrixR.ColumnCount; i++)
+ {
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ result.At(i, j, inputCopy.At(i, j));
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A QR factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Ax=b where A is an m x n matrix
+ // Check that b is a column vector with m entries
+ if (MatrixQ.RowCount != input.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ // Check that x is a column vector with n entries
+ if (MatrixQ.ColumnCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var inputCopy = input.Clone();
+
+ // Compute Y = transpose(Q)*B
+ var column = new float[MatrixQ.RowCount];
+ for (var k = 0; k < MatrixQ.RowCount; k++)
+ {
+ column[k] = inputCopy[k];
+ }
+
+ for (var i = 0; i < MatrixQ.ColumnCount; i++)
+ {
+ float s = 0;
+ for (var k = 0; k < MatrixQ.RowCount; k++)
+ {
+ s += MatrixQ.At(k, i) * column[k];
+ }
+
+ inputCopy[i] = s;
+ }
+
+ // Solve R*X = Y;
+ for (var k = MatrixQ.ColumnCount - 1; k >= 0; k--)
+ {
+ inputCopy[k] /= MatrixR.At(k, k);
+ for (var i = 0; i < k; i++)
+ {
+ inputCopy[i] -= inputCopy[k] * MatrixR.At(i, k);
+ }
+ }
+
+ for (var i = 0; i < MatrixR.ColumnCount; i++)
+ {
+ result[i] = inputCopy[i];
+ }
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the absolute value of a specified number.
+ ///
+ /// A number whose absolute is to be found
+ /// Absolute value
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/UserCholesky.cs b/src/Numerics/LinearAlgebra/Single/Factorization/UserCholesky.cs
new file mode 100644
index 00000000..f2aa0719
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/UserCholesky.cs
@@ -0,0 +1,259 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of a Cholesky factorization for user matrices.
+ /// For a symmetric, positive definite matrix A, the Cholesky factorization
+ /// is an lower triangular matrix L so that A = L*L'.
+ ///
+ ///
+ /// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
+ /// or positive definite, the constructor will throw an exception.
+ ///
+ public class UserCholesky : Cholesky
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// Cholesky factorization when the constructor is called and cache it's factorization.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ /// If is not a square matrix.
+ /// If is not positive definite.
+ public UserCholesky(Matrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount != matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
+ CholeskyFactor = matrix.Clone();
+ for (var j = 0; j < CholeskyFactor.RowCount; j++)
+ {
+ var d = 0.0;
+ for (var k = 0; k < j; k++)
+ {
+ var s = 0.0f;
+ for (var i = 0; i < k; i++)
+ {
+ s += CholeskyFactor.At(k, i) * CholeskyFactor.At(j, i);
+ }
+
+ s = (matrix.At(j, k) - s) / CholeskyFactor.At(k, k);
+ CholeskyFactor.At(j, k, s);
+ d += s * s;
+ }
+
+ d = matrix.At(j, j) - d;
+ if (d <= 0.0)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
+ }
+
+ CholeskyFactor.At(j, j, (float)Math.Sqrt(d));
+ for (var k = j + 1; k < CholeskyFactor.RowCount; k++)
+ {
+ CholeskyFactor.At(j, k, 0.0f);
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A Cholesky factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (result.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ if (result.ColumnCount != input.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ if (input.RowCount != CholeskyFactor.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ input.CopyTo(result);
+ var order = CholeskyFactor.RowCount;
+
+ for (var c = 0; c < result.ColumnCount; c++)
+ {
+ // Solve L*Y = B;
+ float sum;
+ for (var i = 0; i < order; i++)
+ {
+ sum = result.At(i, c);
+ for (var k = i - 1; k >= 0; k--)
+ {
+ sum -= CholeskyFactor.At(i, k) * result.At(k, c);
+ }
+
+ result.At(i, c, sum / CholeskyFactor.At(i, i));
+ }
+
+ // Solve L'*X = Y;
+ for (var i = order - 1; i >= 0; i--)
+ {
+ sum = result.At(i, c);
+ for (var k = i + 1; k < order; k++)
+ {
+ sum -= CholeskyFactor.At(k, i) * result.At(k, c);
+ }
+
+ result.At(i, c, sum / CholeskyFactor.At(i, i));
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A Cholesky factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (input.Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ if (input.Count != CholeskyFactor.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ input.CopyTo(result);
+ var order = CholeskyFactor.RowCount;
+
+ // Solve L*Y = B;
+ float sum;
+ for (var i = 0; i < order; i++)
+ {
+ sum = result[i];
+ for (var k = i - 1; k >= 0; k--)
+ {
+ sum -= CholeskyFactor.At(i, k) * result[k];
+ }
+
+ result[i] = sum / CholeskyFactor.At(i, i);
+ }
+
+ // Solve L'*X = Y;
+ for (var i = order - 1; i >= 0; i--)
+ {
+ sum = result[i];
+ for (var k = i + 1; k < order; k++)
+ {
+ sum -= CholeskyFactor.At(k, i) * result[k];
+ }
+
+ result[i] = sum / CholeskyFactor.At(i, i);
+ }
+ }
+
+ #region Simple T Mathematics
+ ///
+ /// Add two values T+T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of addition
+ protected sealed override float AddT(float val1, float val2)
+ {
+ return val1 + val2;
+ }
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the natural (base e) logarithm of a specified number.
+ ///
+ /// A number whose logarithm is to be found
+ /// Natural (base e) logarithm
+ protected sealed override float LogT(float val1)
+ {
+ return (float)Math.Log(val1);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/UserLU.cs b/src/Numerics/LinearAlgebra/Single/Factorization/UserLU.cs
new file mode 100644
index 00000000..4be798b9
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/UserLU.cs
@@ -0,0 +1,316 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of an LU factorization.
+ /// For a matrix A, the LU factorization is a pair of lower triangular matrix L and
+ /// upper triangular matrix U so that A = L*U.
+ ///
+ ///
+ /// The computation of the LU factorization is done at construction time.
+ ///
+ public class UserLU : LU
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// LU factorization when the constructor is called and cache it's factorization.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ /// If is not a square matrix.
+ public UserLU(Matrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount != matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ // Create an array for the pivot indices.
+ var order = matrix.RowCount;
+ Factors = matrix.Clone();
+ Pivots = new int[order];
+
+ // Initialize the pivot matrix to the identity permutation.
+ for (var i = 0; i < order; i++)
+ {
+ Pivots[i] = i;
+ }
+
+ var vectorLUcolj = new float[order];
+ for (var j = 0; j < order; j++)
+ {
+ // Make a copy of the j-th column to localize references.
+ for (var i = 0; i < order; i++)
+ {
+ vectorLUcolj[i] = Factors.At(i, j);
+ }
+
+ // Apply previous transformations.
+ for (var i = 0; i < order; i++)
+ {
+ var kmax = Math.Min(i, j);
+ var s = 0.0f;
+ for (var k = 0; k < kmax; k++)
+ {
+ s += Factors.At(i, k) * vectorLUcolj[k];
+ }
+
+ vectorLUcolj[i] -= s;
+ Factors.At(i, j, vectorLUcolj[i]);
+ }
+
+ // Find pivot and exchange if necessary.
+ var p = j;
+ for (var i = j + 1; i < order; i++)
+ {
+ if (Math.Abs(vectorLUcolj[i]) > Math.Abs(vectorLUcolj[p]))
+ {
+ p = i;
+ }
+ }
+
+ if (p != j)
+ {
+ for (var k = 0; k < order; k++)
+ {
+ var temp = Factors.At(p, k);
+ Factors.At(p, k, Factors.At(j, k));
+ Factors.At(j, k, temp);
+ }
+
+ Pivots[j] = p;
+ }
+
+ // Compute multipliers.
+ if (j < order & Factors.At(j, j) != 0.0)
+ {
+ for (var i = j + 1; i < order; i++)
+ {
+ Factors.At(i, j, (Factors.At(i, j) / Factors.At(j, j)));
+ }
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A LU factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (result.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ if (result.ColumnCount != input.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ if (input.RowCount != Factors.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ // Copy the contents of input to result.
+ input.CopyTo(result);
+ for (var i = 0; i < Pivots.Length; i++)
+ {
+ if (Pivots[i] == i)
+ {
+ continue;
+ }
+
+ var p = Pivots[i];
+ for (var j = 0; j < result.ColumnCount; j++)
+ {
+ var temp = result.At(p, j);
+ result.At(p, j, result.At(i, j));
+ result.At(i, j, temp);
+ }
+ }
+
+ var order = Factors.RowCount;
+
+ // Solve L*Y = P*B
+ for (var k = 0; k < order; k++)
+ {
+ for (var i = k + 1; i < order; i++)
+ {
+ for (var j = 0; j < result.ColumnCount; j++)
+ {
+ var temp = result.At(k, j) * Factors.At(i, k);
+ result.At(i, j, result.At(i, j) - temp);
+ }
+ }
+ }
+
+ // Solve U*X = Y;
+ for (var k = order - 1; k >= 0; k--)
+ {
+ for (var j = 0; j < result.ColumnCount; j++)
+ {
+ result.At(k, j, (result.At(k, j) / Factors.At(k, k)));
+ }
+
+ for (var i = 0; i < k; i++)
+ {
+ for (var j = 0; j < result.ColumnCount; j++)
+ {
+ var temp = result.At(k, j) * Factors.At(i, k);
+ result.At(i, j, result.At(i, j) - temp);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A LU factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Check for proper dimensions.
+ if (input.Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ if (input.Count != Factors.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ // Copy the contents of input to result.
+ input.CopyTo(result);
+ for (var i = 0; i < Pivots.Length; i++)
+ {
+ if (Pivots[i] == i)
+ {
+ continue;
+ }
+
+ var p = Pivots[i];
+ var temp = result[p];
+ result[p] = result[i];
+ result[i] = temp;
+ }
+
+ var order = Factors.RowCount;
+
+ // Solve L*Y = P*B
+ for (var k = 0; k < order; k++)
+ {
+ for (var i = k + 1; i < order; i++)
+ {
+ result[i] -= result[k] * Factors.At(i, k);
+ }
+ }
+
+ // Solve U*X = Y;
+ for (var k = order - 1; k >= 0; k--)
+ {
+ result[k] /= Factors.At(k, k);
+ for (var i = 0; i < k; i++)
+ {
+ result[i] -= result[k] * Factors.At(i, k);
+ }
+ }
+ }
+
+ ///
+ /// Returns the inverse of this matrix. The inverse is calculated using LU decomposition.
+ ///
+ /// The inverse of this matrix.
+ public override Matrix Inverse()
+ {
+ var order = Factors.RowCount;
+ var inverse = Factors.CreateMatrix(order, order);
+ for (var i = 0; i < order; i++)
+ {
+ inverse.At(i, i, 1.0f);
+ }
+
+ return Solve(inverse);
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/UserQR.cs b/src/Numerics/LinearAlgebra/Single/Factorization/UserQR.cs
new file mode 100644
index 00000000..5c573594
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/UserQR.cs
@@ -0,0 +1,357 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using System.Linq;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of the QR decomposition.
+ /// Any real square matrix A may be decomposed as A = QR where Q is an orthogonal matrix
+ /// (its columns are orthogonal unit vectors meaning QTQ = I) and R is an upper triangular matrix
+ /// (also called right triangular matrix).
+ ///
+ ///
+ /// The computation of the QR decomposition is done at construction time by Householder transformation.
+ ///
+ public class UserQR : QR
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// QR factorization when the constructor is called and cache it's factorization.
+ ///
+ /// The matrix to factor.
+ /// If is null.
+ public UserQR(Matrix matrix)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount < matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ MatrixR = matrix.Clone();
+ MatrixQ = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount);
+
+ for (var i = 0; i < matrix.RowCount; i++)
+ {
+ MatrixQ.At(i, i, 1.0f);
+ }
+
+ var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount);
+ var u = new float[minmn][];
+ for (var i = 0; i < minmn; i++)
+ {
+ u[i] = GenerateColumn(MatrixR, i, matrix.RowCount - 1, i);
+ ComputeQR(u[i], MatrixR, i, matrix.RowCount - 1, i + 1, matrix.ColumnCount - 1);
+ }
+
+ for (var i = minmn - 1; i >= 0; i--)
+ {
+ ComputeQR(u[i], MatrixQ, i, matrix.RowCount - 1, i, matrix.RowCount - 1);
+ }
+ }
+
+ ///
+ /// Generate column from initial matrix to work array
+ ///
+ /// Initial matrix
+ /// The firts row
+ /// The last row
+ /// Column index
+ /// Generated vector
+ private static float[] GenerateColumn(Matrix a, int rowStart, int rowEnd, int column)
+ {
+ var ru = rowEnd - rowStart + 1;
+ var u = new float[ru];
+
+ for (var i = rowStart; i <= rowEnd; i++)
+ {
+ u[i - rowStart] = a.At(i, rowStart);
+ a.At(i, rowStart, 0.0f);
+ }
+
+ var norm = u.Sum(t => t * t);
+ norm = (float)Math.Sqrt(norm);
+
+ if (rowStart == rowEnd || norm == 0)
+ {
+ a.At(rowStart, column, -u[0]);
+ u[0] = (float)Math.Sqrt(2.0);
+ return u;
+ }
+
+ var scale = 1.0f / norm;
+ if (u[0] < 0.0)
+ {
+ scale *= -1.0f;
+ }
+
+ a.At(rowStart, column, -1.0f / scale);
+
+ for (var i = 0; i < ru; i++)
+ {
+ u[i] *= scale;
+ }
+
+ u[0] += 1.0f;
+ var s = (float)Math.Sqrt(1.0 / u[0]);
+
+ for (var i = 0; i < ru; i++)
+ {
+ u[i] *= s;
+ }
+
+ return u;
+ }
+
+ ///
+ /// Perform calculation of Q or R
+ ///
+ /// Work array
+ /// Q or R matrices
+ /// The first row
+ /// The last row
+ /// The first column
+ /// The last column
+ private static void ComputeQR(float[] u, Matrix a, int rowStart, int rowEnd, int columnStart, int columnEnd)
+ {
+ if (rowEnd < rowStart || columnEnd < columnStart)
+ {
+ return;
+ }
+
+ var v = new float[columnEnd - columnStart + 1];
+ for (var j = columnStart; j <= columnEnd; j++)
+ {
+ v[j - columnStart] = 0.0f;
+ }
+
+ for (var i = rowStart; i <= rowEnd; i++)
+ {
+ for (var j = columnStart; j <= columnEnd; j++)
+ {
+ v[j - columnStart] = v[j - columnStart] + (u[i - rowStart] * a.At(i, j));
+ }
+ }
+
+ for (var i = rowStart; i <= rowEnd; i++)
+ {
+ for (var j = columnStart; j <= columnEnd; j++)
+ {
+ a.At(i, j, a.At(i, j) - (u[i - rowStart] * v[j - columnStart]));
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A QR factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // The solution X should have the same number of columns as B
+ if (input.ColumnCount != result.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
+ if (MatrixR.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ // The solution X row dimension is equal to the column dimension of A
+ if (MatrixR.ColumnCount != result.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ var inputCopy = input.Clone();
+
+ // Compute Y = transpose(Q)*B
+ var column = new float[MatrixR.RowCount];
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ for (var k = 0; k < MatrixR.RowCount; k++)
+ {
+ column[k] = inputCopy.At(k, j);
+ }
+
+ for (var i = 0; i < MatrixR.RowCount; i++)
+ {
+ float s = 0;
+ for (var k = 0; k < MatrixR.RowCount; k++)
+ {
+ s += MatrixQ.At(k, i) * column[k];
+ }
+
+ inputCopy.At(i, j, s);
+ }
+ }
+
+ // Solve R*X = Y;
+ for (var k = MatrixR.ColumnCount - 1; k >= 0; k--)
+ {
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ inputCopy.At(k, j, inputCopy.At(k, j) / MatrixR.At(k, k));
+ }
+
+ for (var i = 0; i < k; i++)
+ {
+ for (var j = 0; j < input.ColumnCount; j++)
+ {
+ inputCopy.At(i, j, inputCopy.At(i, j) - (inputCopy.At(k, j) * MatrixR.At(i, k)));
+ }
+ }
+ }
+
+ for (var i = 0; i < MatrixR.ColumnCount; i++)
+ {
+ for (var j = 0; j < inputCopy.ColumnCount; j++)
+ {
+ result.At(i, j, inputCopy.At(i, j));
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A QR factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ // Ax=b where A is an m x n matrix
+ // Check that b is a column vector with m entries
+ if (MatrixR.RowCount != input.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ // Check that x is a column vector with n entries
+ if (MatrixR.ColumnCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var inputCopy = input.Clone();
+
+ // Compute Y = transpose(Q)*B
+ var column = new float[MatrixR.RowCount];
+ for (var k = 0; k < MatrixR.RowCount; k++)
+ {
+ column[k] = inputCopy[k];
+ }
+
+ for (var i = 0; i < MatrixR.RowCount; i++)
+ {
+ float s = 0;
+ for (var k = 0; k < MatrixR.RowCount; k++)
+ {
+ s += MatrixQ.At(k, i) * column[k];
+ }
+
+ inputCopy[i] = s;
+ }
+
+ // Solve R*X = Y;
+ for (var k = MatrixR.ColumnCount - 1; k >= 0; k--)
+ {
+ inputCopy[k] /= MatrixR.At(k, k);
+ for (var i = 0; i < k; i++)
+ {
+ inputCopy[i] -= inputCopy[k] * MatrixR.At(i, k);
+ }
+ }
+
+ for (var i = 0; i < MatrixR.ColumnCount; i++)
+ {
+ result[i] = inputCopy[i];
+ }
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the absolute value of a specified number.
+ ///
+ /// A number whose absolute is to be found
+ /// Absolute value
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/UserSvd.cs b/src/Numerics/LinearAlgebra/Single/Factorization/UserSvd.cs
new file mode 100644
index 00000000..8cba9b96
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Factorization/UserSvd.cs
@@ -0,0 +1,950 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
+{
+ using System;
+ using Generic;
+ using Generic.Factorization;
+ using Properties;
+
+ ///
+ /// A class which encapsulates the functionality of the singular value decomposition (SVD) for .
+ /// Suppose M is an m-by-n matrix whose entries are real numbers.
+ /// Then there exists a factorization of the form M = UΣVT where:
+ /// - U is an m-by-m unitary matrix;
+ /// - Σ is m-by-n diagonal matrix with nonnegative real numbers on the diagonal;
+ /// - VT denotes transpose of V, an n-by-n unitary matrix;
+ /// Such a factorization is called a singular-value decomposition of M. A common convention is to order the diagonal
+ /// entries Σ(i,i) in descending order. In this case, the diagonal matrix Σ is uniquely determined
+ /// by M (though the matrices U and V are not). The diagonal entries of Σ are known as the singular values of M.
+ ///
+ ///
+ /// The computation of the singular value decomposition is done at construction time.
+ ///
+ public class UserSvd : Svd
+ {
+ ///
+ /// Initializes a new instance of the class. This object will compute the
+ /// the singular value decomposition when the constructor is called and cache it's decomposition.
+ ///
+ /// The matrix to factor.
+ /// Compute the singular U and VT vectors or not.
+ /// If is null.
+ /// If SVD algorithm failed to converge with matrix .
+ public UserSvd(Matrix matrix, bool computeVectors)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ ComputeVectors = computeVectors;
+ var nm = Math.Min(matrix.RowCount + 1, matrix.ColumnCount);
+ var matrixCopy = matrix.Clone();
+
+ VectorS = matrixCopy.CreateVector(nm);
+ MatrixU = matrixCopy.CreateMatrix(matrixCopy.RowCount, matrixCopy.RowCount);
+ MatrixVT = matrixCopy.CreateMatrix(matrixCopy.ColumnCount, matrixCopy.ColumnCount);
+
+ const int Maxiter = 1000;
+ var e = new float[matrixCopy.ColumnCount];
+ var work = new float[matrixCopy.RowCount];
+
+ int i, j;
+ int l, lp1;
+ var cs = 0.0f;
+ var sn = 0.0f;
+ float t;
+
+ var ncu = matrixCopy.RowCount;
+
+ // Reduce matrixCopy to bidiagonal form, storing the diagonal elements
+ // In s and the super-diagonal elements in e.
+ var nct = Math.Min(matrixCopy.RowCount - 1, matrixCopy.ColumnCount);
+ var nrt = Math.Max(0, Math.Min(matrixCopy.ColumnCount - 2, matrixCopy.RowCount));
+ var lu = Math.Max(nct, nrt);
+ for (l = 0; l < lu; l++)
+ {
+ lp1 = l + 1;
+ if (l < nct)
+ {
+ // Compute the transformation for the l-th column and place the l-th diagonal in VectorS[l].
+ var xnorm = Dnrm2Column(matrixCopy, matrixCopy.RowCount, l, l);
+ VectorS[l] = xnorm;
+ if (VectorS[l] != 0.0)
+ {
+ if (matrixCopy.At(l, l) != 0.0)
+ {
+ VectorS[l] = Dsign(VectorS[l], matrixCopy.At(l, l));
+ }
+
+ DscalColumn(matrixCopy, matrixCopy.RowCount, l, l, 1.0f / VectorS[l]);
+ matrixCopy.At(l, l, (1.0f + matrixCopy.At(l, l)));
+ }
+
+ VectorS[l] = -VectorS[l];
+ }
+
+ for (j = lp1; j < matrixCopy.ColumnCount; j++)
+ {
+ if (l < nct)
+ {
+ if (VectorS[l] != 0.0)
+ {
+ // Apply the transformation.
+ t = -Ddot(matrixCopy, matrixCopy.RowCount, l, j, l) / matrixCopy.At(l, l);
+ for (var ii = l; ii < matrixCopy.RowCount; ii++)
+ {
+ matrixCopy.At(ii, j, matrixCopy.At(ii, j) + (t * matrixCopy.At(ii, l)));
+ }
+ }
+ }
+
+ // Place the l-th row of matrixCopy into e for the
+ // Subsequent calculation of the row transformation.
+ e[j] = matrixCopy.At(l, j);
+ }
+
+ if (ComputeVectors && l < nct)
+ {
+ // Place the transformation in u for subsequent back multiplication.
+ for (i = l; i < matrixCopy.RowCount; i++)
+ {
+ MatrixU.At(i, l, matrixCopy.At(i, l));
+ }
+ }
+
+ if (l >= nrt)
+ {
+ continue;
+ }
+
+ // Compute the l-th row transformation and place the l-th super-diagonal in e(l).
+ var enorm = Dnrm2Vector(e, lp1);
+ e[l] = enorm;
+ if (e[l] != 0.0)
+ {
+ if (e[lp1] != 0.0)
+ {
+ e[l] = Dsign(e[l], e[lp1]);
+ }
+
+ DscalVector(e, lp1, 1.0f / e[l]);
+ e[lp1] = 1.0f + e[lp1];
+ }
+
+ e[l] = -e[l];
+ if (lp1 < matrixCopy.RowCount && e[l] != 0.0)
+ {
+ // Apply the transformation.
+ for (i = lp1; i < matrixCopy.RowCount; i++)
+ {
+ work[i] = 0.0f;
+ }
+
+ for (j = lp1; j < matrixCopy.ColumnCount; j++)
+ {
+ for (var ii = lp1; ii < matrixCopy.RowCount; ii++)
+ {
+ work[ii] += e[j] * matrixCopy.At(ii, j);
+ }
+ }
+
+ for (j = lp1; j < matrixCopy.ColumnCount; j++)
+ {
+ var ww = -e[j] / e[lp1];
+ for (var ii = lp1; ii < matrixCopy.RowCount; ii++)
+ {
+ matrixCopy.At(ii, j, matrixCopy.At(ii, j) + (ww * work[ii]));
+ }
+ }
+ }
+
+ if (ComputeVectors)
+ {
+ // Place the transformation in v for subsequent back multiplication.
+ for (i = lp1; i < matrixCopy.ColumnCount; i++)
+ {
+ MatrixVT.At(i, l, e[i]);
+ }
+ }
+ }
+
+ // Set up the final bidiagonal matrixCopy or order m.
+ var m = Math.Min(matrixCopy.ColumnCount, matrixCopy.RowCount + 1);
+ var nctp1 = nct + 1;
+ var nrtp1 = nrt + 1;
+ if (nct < matrixCopy.ColumnCount)
+ {
+ VectorS[nctp1 - 1] = matrixCopy.At((nctp1 - 1), (nctp1 - 1));
+ }
+
+ if (matrixCopy.RowCount < m)
+ {
+ VectorS[m - 1] = 0.0f;
+ }
+
+ if (nrtp1 < m)
+ {
+ e[nrtp1 - 1] = matrixCopy.At((nrtp1 - 1), (m - 1));
+ }
+
+ e[m - 1] = 0.0f;
+
+ // If required, generate u.
+ if (ComputeVectors)
+ {
+ for (j = nctp1 - 1; j < ncu; j++)
+ {
+ for (i = 0; i < matrixCopy.RowCount; i++)
+ {
+ MatrixU.At(i, j, 0.0f);
+ }
+
+ MatrixU.At(j, j, 1.0f);
+ }
+
+ for (l = nct - 1; l >= 0; l--)
+ {
+ if (VectorS[l] != 0.0)
+ {
+ for (j = l + 1; j < ncu; j++)
+ {
+ t = -Ddot(MatrixU, matrixCopy.RowCount, l, j, l) / MatrixU.At(l, l);
+ for (var ii = l; ii < matrixCopy.RowCount; ii++)
+ {
+ MatrixU.At(ii, j, MatrixU.At(ii, j) + (t * MatrixU.At(ii, l)));
+ }
+ }
+
+ DscalColumn(MatrixU, matrixCopy.RowCount, l, l, -1.0f);
+ MatrixU.At(l, l, 1.0f + MatrixU.At(l, l));
+ for (i = 0; i < l; i++)
+ {
+ MatrixU.At(i, l, 0.0f);
+ }
+ }
+ else
+ {
+ for (i = 0; i < matrixCopy.RowCount; i++)
+ {
+ MatrixU.At(i, l, 0.0f);
+ }
+
+ MatrixU.At(l, l, 1.0f);
+ }
+ }
+ }
+
+ // If it is required, generate v.
+ if (ComputeVectors)
+ {
+ for (l = matrixCopy.ColumnCount - 1; l >= 0; l--)
+ {
+ lp1 = l + 1;
+ if (l < nrt)
+ {
+ if (e[l] != 0.0)
+ {
+ for (j = lp1; j < matrixCopy.ColumnCount; j++)
+ {
+ t = -Ddot(MatrixVT, matrixCopy.ColumnCount, l, j, lp1) / MatrixVT.At(lp1, l);
+ for (var ii = l; ii < matrixCopy.ColumnCount; ii++)
+ {
+ MatrixVT.At(ii, j, MatrixVT.At(ii, j) + (t * MatrixVT.At(ii, l)));
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < matrixCopy.ColumnCount; i++)
+ {
+ MatrixVT.At(i, l, 0.0f);
+ }
+
+ MatrixVT.At(l, l, 1.0f);
+ }
+ }
+
+ // Transform s and e so that they are float .
+ for (i = 0; i < m; i++)
+ {
+ float r;
+ if (VectorS[i] != 0.0)
+ {
+ t = VectorS[i];
+ r = VectorS[i] / t;
+ VectorS[i] = t;
+ if (i < m - 1)
+ {
+ e[i] = e[i] / r;
+ }
+
+ if (ComputeVectors)
+ {
+ DscalColumn(MatrixU, matrixCopy.RowCount, i, 0, r);
+ }
+ }
+
+ // Exit
+ if (i == m - 1)
+ {
+ break;
+ }
+
+ if (e[i] != 0.0)
+ {
+ t = e[i];
+ r = t / e[i];
+ e[i] = t;
+ VectorS[i + 1] = VectorS[i + 1] * r;
+ if (ComputeVectors)
+ {
+ DscalColumn(MatrixVT, matrixCopy.ColumnCount, i + 1, 0, r);
+ }
+ }
+ }
+
+ // Main iteration loop for the singular values.
+ var mn = m;
+ var iter = 0;
+
+ while (m > 0)
+ {
+ // Quit if all the singular values have been found. If too many iterations have been performed,
+ // throw exception that Convergence Failed
+ if (iter >= Maxiter)
+ {
+ throw new ArgumentException(Resources.ConvergenceFailed);
+ }
+
+ // This section of the program inspects for negligible elements in the s and e arrays. On
+ // completion the variables kase and l are set as follows.
+ // Kase = 1 if VectorS[m] and e[l-1] are negligible and l < m
+ // Kase = 2 if VectorS[l] is negligible and l < m
+ // Kase = 3 if e[l-1] is negligible, l < m, and VectorS[l, ..., VectorS[m] are not negligible (qr step).
+ // Лase = 4 if e[m-1] is negligible (convergence).
+ float ztest;
+ float test;
+ for (l = m - 2; l >= 0; l--)
+ {
+ test = Math.Abs(VectorS[l]) + Math.Abs(VectorS[l + 1]);
+ ztest = test + Math.Abs(e[l]);
+ if (ztest.AlmostEqualInDecimalPlaces(test, 7))
+ {
+ e[l] = 0.0f;
+ break;
+ }
+ }
+
+ int kase;
+ if (l == m - 2)
+ {
+ kase = 4;
+ }
+ else
+ {
+ int ls;
+ for (ls = m - 1; ls > l; ls--)
+ {
+ test = 0.0f;
+ if (ls != m - 1)
+ {
+ test = test + Math.Abs(e[ls]);
+ }
+
+ if (ls != l + 1)
+ {
+ test = test + Math.Abs(e[ls - 1]);
+ }
+
+ ztest = test + Math.Abs(VectorS[ls]);
+ if (ztest.AlmostEqualInDecimalPlaces(test, 7))
+ {
+ VectorS[ls] = 0.0f;
+ break;
+ }
+ }
+
+ if (ls == l)
+ {
+ kase = 3;
+ }
+ else if (ls == m - 1)
+ {
+ kase = 1;
+ }
+ else
+ {
+ kase = 2;
+ l = ls;
+ }
+ }
+
+ l = l + 1;
+
+ // Perform the task indicated by kase.
+ int k;
+ float f;
+ switch (kase)
+ {
+ // Deflate negligible VectorS[m].
+ case 1:
+ f = e[m - 2];
+ e[m - 2] = 0.0f;
+ float t1;
+ for (var kk = l; kk < m - 1; kk++)
+ {
+ k = m - 2 - kk + l;
+ t1 = VectorS[k];
+ Drotg(ref t1, ref f, ref cs, ref sn);
+ VectorS[k] = t1;
+ if (k != l)
+ {
+ f = -sn * e[k - 1];
+ e[k - 1] = cs * e[k - 1];
+ }
+
+ if (ComputeVectors)
+ {
+ Drot(MatrixVT, matrixCopy.ColumnCount, k, m - 1, cs, sn);
+ }
+ }
+
+ break;
+
+ // Split at negligible VectorS[l].
+ case 2:
+ f = e[l - 1];
+ e[l - 1] = 0.0f;
+ for (k = l; k < m; k++)
+ {
+ t1 = VectorS[k];
+ Drotg(ref t1, ref f, ref cs, ref sn);
+ VectorS[k] = t1;
+ f = -sn * e[k];
+ e[k] = cs * e[k];
+ if (ComputeVectors)
+ {
+ Drot(MatrixU, matrixCopy.RowCount, k, l - 1, cs, sn);
+ }
+ }
+
+ break;
+
+ // Perform one qr step.
+ case 3:
+ // Calculate the shift.
+ var scale = 0.0f;
+ scale = Math.Max(scale, Math.Abs(VectorS[m - 1]));
+ scale = Math.Max(scale, Math.Abs(VectorS[m - 2]));
+ scale = Math.Max(scale, Math.Abs(e[m - 2]));
+ scale = Math.Max(scale, Math.Abs(VectorS[l]));
+ scale = Math.Max(scale, Math.Abs(e[l]));
+ var sm = VectorS[m - 1] / scale;
+ var smm1 = VectorS[m - 2] / scale;
+ var emm1 = e[m - 2] / scale;
+ var sl = VectorS[l] / scale;
+ var el = e[l] / scale;
+ var b = (((smm1 + sm) * (smm1 - sm)) + (emm1 * emm1)) / 2.0f;
+ var c = (sm * emm1) * (sm * emm1);
+ var shift = 0.0f;
+ if (b != 0.0 || c != 0.0)
+ {
+ shift = (float) Math.Sqrt((b * b) + c);
+ if (b < 0.0)
+ {
+ shift = -shift;
+ }
+
+ shift = c / (b + shift);
+ }
+
+ f = ((sl + sm) * (sl - sm)) + shift;
+ var g = sl * el;
+
+ // Chase zeros.
+ for (k = l; k < m - 1; k++)
+ {
+ Drotg(ref f, ref g, ref cs, ref sn);
+ if (k != l)
+ {
+ e[k - 1] = f;
+ }
+
+ f = (cs * VectorS[k]) + (sn * e[k]);
+ e[k] = (cs * e[k]) - (sn * VectorS[k]);
+ g = sn * VectorS[k + 1];
+ VectorS[k + 1] = cs * VectorS[k + 1];
+ if (ComputeVectors)
+ {
+ Drot(MatrixVT, matrixCopy.ColumnCount, k, k + 1, cs, sn);
+ }
+
+ Drotg(ref f, ref g, ref cs, ref sn);
+ VectorS[k] = f;
+ f = (cs * e[k]) + (sn * VectorS[k + 1]);
+ VectorS[k + 1] = (-sn * e[k]) + (cs * VectorS[k + 1]);
+ g = sn * e[k + 1];
+ e[k + 1] = cs * e[k + 1];
+ if (ComputeVectors && k < matrixCopy.RowCount)
+ {
+ Drot(MatrixU, matrixCopy.RowCount, k, k + 1, cs, sn);
+ }
+ }
+
+ e[m - 2] = f;
+ iter = iter + 1;
+ break;
+
+ // Convergence.
+ case 4:
+ // Make the singular value positive
+ if (VectorS[l] < 0.0)
+ {
+ VectorS[l] = -VectorS[l];
+ if (ComputeVectors)
+ {
+ DscalColumn(MatrixVT, matrixCopy.ColumnCount, l, 0, -1.0f);
+ }
+ }
+
+ // Order the singular value.
+ while (l != mn - 1)
+ {
+ if (VectorS[l] >= VectorS[l + 1])
+ {
+ break;
+ }
+
+ t = VectorS[l];
+ VectorS[l] = VectorS[l + 1];
+ VectorS[l + 1] = t;
+ if (ComputeVectors && l < matrixCopy.ColumnCount)
+ {
+ Dswap(MatrixVT, matrixCopy.ColumnCount, l, l + 1);
+ }
+
+ if (ComputeVectors && l < matrixCopy.RowCount)
+ {
+ Dswap(MatrixU, matrixCopy.RowCount, l, l + 1);
+ }
+
+ l = l + 1;
+ }
+
+ iter = 0;
+ m = m - 1;
+ break;
+ }
+ }
+
+ if (ComputeVectors)
+ {
+ MatrixVT = MatrixVT.Transpose();
+ }
+
+ // Adjust the size of s if rows < columns. We are using ported copy of linpack's svd code and it uses
+ // a singular vector of length mRows+1 when mRows < mColumns. The last element is not used and needs to be removed.
+ // we should port lapack's svd routine to remove this problem.
+ if (matrixCopy.RowCount < matrixCopy.ColumnCount)
+ {
+ nm--;
+ var tmp = matrixCopy.CreateVector(nm);
+ for (i = 0; i < nm; i++)
+ {
+ tmp[i] = VectorS[i];
+ }
+
+ VectorS = tmp;
+ }
+ }
+
+ ///
+ /// Calculates absolute value of multiplied on signum function of
+ ///
+ /// Double value z1
+ /// Double value z2
+ /// Result multiplication of signum function and absolute value
+ private static float Dsign(float z1, float z2)
+ {
+ return Math.Abs(z1) * (z2 / Math.Abs(z2));
+ }
+
+ ///
+ /// Swap column and
+ ///
+ /// Source matrix
+ /// The number of rows in
+ /// Column A index to swap
+ /// Column B index to swap
+ private static void Dswap(Matrix a, int rowCount, int columnA, int columnB)
+ {
+ for (var i = 0; i < rowCount; i++)
+ {
+ var z = a.At(i, columnA);
+ a.At(i, columnA, a.At(i, columnB));
+ a.At(i, columnB, z);
+ }
+ }
+
+ ///
+ /// Scale column by starting from row
+ ///
+ /// Source matrix
+ /// The number of rows in
+ /// Column to scale
+ /// Row to scale from
+ /// Scale value
+ private static void DscalColumn(Matrix a, int rowCount, int column, int rowStart, float z)
+ {
+ for (var i = rowStart; i < rowCount; i++)
+ {
+ a.At(i, column, a.At(i, column) * z);
+ }
+ }
+
+ ///
+ /// Scale vector by starting from index
+ ///
+ /// Source vector
+ /// Row to scale from
+ /// Scale value
+ private static void DscalVector(float[] a, int start, float z)
+ {
+ for (var i = start; i < a.Length; i++)
+ {
+ a[i] = a[i] * z;
+ }
+ }
+
+ ///
+ /// Given the Cartesian coordinates (da, db) of a point p, these fucntion return the parameters da, db, c, and s
+ /// associated with the Givens rotation that zeros the y-coordinate of the point.
+ ///
+ /// Provides the x-coordinate of the point p. On exit contains the parameter r associated with the Givens rotation
+ /// Provides the y-coordinate of the point p. On exit contains the parameter z associated with the Givens rotation
+ /// Contains the parameter c associated with the Givens rotation
+ /// Contains the parameter s associated with the Givens rotation
+ /// This is equivalent to the DROTG LAPACK routine.
+ private static void Drotg(ref float da, ref float db, ref float c, ref float s)
+ {
+ float r, z;
+
+ var roe = db;
+ var absda = Math.Abs(da);
+ var absdb = Math.Abs(db);
+ if (absda > absdb)
+ {
+ roe = da;
+ }
+
+ var scale = absda + absdb;
+ if (scale == 0.0)
+ {
+ c = 1.0f;
+ s = 0.0f;
+ r = 0.0f;
+ z = 0.0f;
+ }
+ else
+ {
+ var sda = da / scale;
+ var sdb = db / scale;
+ r = scale * (float)Math.Sqrt((sda * sda) + (sdb * sdb));
+ if (roe < 0.0)
+ {
+ r = -r;
+ }
+
+ c = da / r;
+ s = db / r;
+ z = 1.0f;
+ if (absda > absdb)
+ {
+ z = s;
+ }
+
+ if (absdb >= absda && c != 0.0)
+ {
+ z = 1.0f / c;
+ }
+ }
+
+ da = r;
+ db = z;
+ }
+
+ /// dded
+ /// Calculate Norm 2 of the column in matrix starting from row
+ ///
+ /// Source matrix
+ /// The number of rows in
+ /// Column index
+ /// Start row index
+ /// Norm2 (Euclidean norm) of trhe column
+ private static float Dnrm2Column(Matrix a, int rowCount, int column, int rowStart)
+ {
+ float s = 0;
+ for (var i = rowStart; i < rowCount; i++)
+ {
+ s += a.At(i, column) * a.At(i, column);
+ }
+
+ return (float)Math.Sqrt(s);
+ }
+
+ ///
+ /// Calculate Norm 2 of the vector starting from index
+ ///
+ /// Source vector
+ /// Start index
+ /// Norm2 (Euclidean norm) of the vector
+ private static float Dnrm2Vector(float[] a, int rowStart)
+ {
+ float s = 0;
+ for (var i = rowStart; i < a.Length; i++)
+ {
+ s += a[i] * a[i];
+ }
+
+ return (float)Math.Sqrt(s);
+ }
+
+ ///
+ /// Calculate dot product of and
+ ///
+ /// Source matrix
+ /// The number of rows in
+ /// Index of column A
+ /// Index of column B
+ /// Starting row index
+ /// Dot product value
+ private static float Ddot(Matrix a, int rowCount, int columnA, int columnB, int rowStart)
+ {
+ var z = 0.0f;
+ for (var i = rowStart; i < rowCount; i++)
+ {
+ z += a.At(i, columnB) * a.At(i, columnA);
+ }
+
+ return z;
+ }
+
+ ///
+ /// Performs rotation of points in the plane. Given two vectors x and y ,
+ /// each vector element of these vectors is replaced as follows: x(i) = c*x(i) + s*y(i); y(i) = c*y(i) - s*x(i)
+ ///
+ /// Source matrix
+ /// The number of rows in
+ /// Index of column A
+ /// Index of column B
+ /// Scalar "c" value
+ /// Scalar "s" value
+ private static void Drot(Matrix a, int rowCount, int columnA, int columnB, float c, float s)
+ {
+ for (var i = 0; i < rowCount; i++)
+ {
+ var z = (c * a.At(i, columnA)) + (s * a.At(i, columnB));
+ var tmp = (c * a.At(i, columnB)) - (s * a.At(i, columnA));
+ a.At(i, columnB, tmp);
+ a.At(i, columnA, z);
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, AX = B, with A SVD factorized.
+ ///
+ /// The right hand side , B.
+ /// The left hand side , X.
+ public override void Solve(Matrix input, Matrix result)
+ {
+ // Check for proper arguments.
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (!ComputeVectors)
+ {
+ throw new InvalidOperationException(Resources.SingularVectorsNotComputed);
+ }
+
+ // The solution X should have the same number of columns as B
+ if (input.ColumnCount != result.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
+ if (MatrixU.RowCount != input.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ // The solution X row dimension is equal to the column dimension of A
+ if (MatrixVT.ColumnCount != result.RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ var mn = Math.Min(MatrixU.RowCount, MatrixVT.ColumnCount);
+ var bn = input.ColumnCount;
+
+ var tmp = new float[MatrixVT.ColumnCount];
+
+ for (var k = 0; k < bn; k++)
+ {
+ for (var j = 0; j < MatrixVT.ColumnCount; j++)
+ {
+ float value = 0;
+ if (j < mn)
+ {
+ for (var i = 0; i < MatrixU.RowCount; i++)
+ {
+ value += MatrixU.At(i, j) * input.At(i, k);
+ }
+
+ value /= VectorS[j];
+ }
+
+ tmp[j] = value;
+ }
+
+ for (var j = 0; j < MatrixVT.ColumnCount; j++)
+ {
+ float value = 0;
+ for (var i = 0; i < MatrixVT.ColumnCount; i++)
+ {
+ value += MatrixVT.At(i, j) * tmp[i];
+ }
+
+ result[j, k] = value;
+ }
+ }
+ }
+
+ ///
+ /// Solves a system of linear equations, Ax = b, with A SVD factorized.
+ ///
+ /// The right hand side vector, b.
+ /// The left hand side , x.
+ public override void Solve(Vector input, Vector result)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (!ComputeVectors)
+ {
+ throw new InvalidOperationException(Resources.SingularVectorsNotComputed);
+ }
+
+ // Ax=b where A is an m x n matrix
+ // Check that b is a column vector with m entries
+ if (MatrixU.RowCount != input.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ // Check that x is a column vector with n entries
+ if (MatrixVT.ColumnCount != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixDimensions);
+ }
+
+ var mn = Math.Min(MatrixU.RowCount, MatrixVT.ColumnCount);
+ var tmp = new float[MatrixVT.ColumnCount];
+ float value;
+ for (var j = 0; j < MatrixVT.ColumnCount; j++)
+ {
+ value = 0;
+ if (j < mn)
+ {
+ for (var i = 0; i < MatrixU.RowCount; i++)
+ {
+ value += MatrixU.At(i, j) * input[i];
+ }
+
+ value /= VectorS[j];
+ }
+
+ tmp[j] = value;
+ }
+
+ for (var j = 0; j < MatrixVT.ColumnCount; j++)
+ {
+ value = 0;
+ for (int i = 0; i < MatrixVT.ColumnCount; i++)
+ {
+ value += MatrixVT.At(i, j) * tmp[i];
+ }
+
+ result[j] = value;
+ }
+ }
+
+ #region Simple arithmetic of type T
+
+ ///
+ /// Multiply two values T*T
+ ///
+ /// Left operand value
+ /// Right operand value
+ /// Result of multiplication
+ protected sealed override float MultiplyT(float val1, float val2)
+ {
+ return val1 * val2;
+ }
+
+ ///
+ /// Returns the absolute value of a specified number.
+ ///
+ /// A number whose absolute is to be found
+ /// Absolute value
+ protected sealed override double AbsoluteT(float val1)
+ {
+ return Math.Abs(val1);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs b/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs
new file mode 100644
index 00000000..8ffed659
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/DelimitedReader.cs
@@ -0,0 +1,197 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using System.Reflection;
+ using System.Text.RegularExpressions;
+ using Generic;
+
+ ///
+ /// Creates a from a delimited text file. If the user does not
+ /// specify a delimiter, then any whitespace is used.
+ ///
+ /// The type of the matrix to return.
+ public class DelimitedReader : MatrixReader
+ where TMatrix : Matrix
+ {
+ ///
+ /// Constructor to create matrix instance.
+ ///
+ private static readonly ConstructorInfo Constructor = typeof(TMatrix).GetConstructor(new[] { typeof(int), typeof(int) });
+
+ ///
+ /// Whitespace regular expression.
+ ///
+ private static readonly Regex WhiteSpace = new Regex(@"[\s]+");
+
+ ///
+ /// The delimiter to use.
+ ///
+ private readonly Regex _delimiter;
+
+ ///
+ /// The to use.
+ ///
+ private CultureInfo _cultureInfo = CultureInfo.CurrentCulture;
+
+ ///
+ /// Initializes a new instance of the class using
+ /// any whitespace as the delimiter.
+ ///
+ public DelimitedReader()
+ {
+ _delimiter = WhiteSpace;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The delimiter to use.
+ public DelimitedReader(char delimiter)
+ {
+ _delimiter = new Regex("[" + new string(delimiter, 1) + "]+");
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The delimiter to use.
+ ///
+ ///
+ /// If is .
+ ///
+ public DelimitedReader(string delimiter)
+ {
+ if (delimiter == null)
+ {
+ throw new ArgumentNullException("delimiter");
+ }
+
+ _delimiter = new Regex("[" + delimiter + "]+");
+ }
+
+ ///
+ /// Gets or sets the to use when parsing the numbers.
+ ///
+ /// The culture info.
+ /// Defaults to CultureInfo.CurrentCulture.
+ public CultureInfo CultureInfo
+ {
+ get
+ {
+ return _cultureInfo;
+ }
+
+ set
+ {
+ if (value != null)
+ {
+ _cultureInfo = value;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the files has a header row.
+ ///
+ ///
+ /// true if this instance has a header row; otherwise, false.
+ ///
+ /// Defaults to .
+ public bool HasHeaderRow
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Performs the actual reading.
+ ///
+ /// The to read the matrix from.
+ ///
+ /// A matrix containing the data from the . is returned if the is empty.
+ ///
+ protected override TMatrix DoReadMatrix(Stream stream)
+ {
+ var data = new List();
+
+ // max is used to supports files like:
+ // 1,2
+ // 3,4,5,6
+ // 7
+ // this creates a 3x4 matrix:
+ // 1, 2, 0 ,0
+ // 3, 4, 5, 6
+ // 7, 0, 0, 0
+ var max = -1;
+ var reader = new StreamReader(stream);
+ var line = reader.ReadLine();
+ if (HasHeaderRow)
+ {
+ line = reader.ReadLine();
+ }
+
+ while (line != null)
+ {
+ line = line.Trim();
+ if (line.Length > 0)
+ {
+ var row = _delimiter.Split(line);
+ max = Math.Max(max, row.Length);
+ data.Add(row);
+ }
+
+ line = reader.ReadLine();
+ }
+
+ var ret = (TMatrix)Constructor.Invoke(new object[] { data.Count, max });
+
+ if (data.Count != 0)
+ {
+ for (var i = 0; i < data.Count; i++)
+ {
+ var row = data[i];
+ for (var j = 0; j < row.Length; j++)
+ {
+ // strip off quotes
+ var value = row[j].Replace("'", string.Empty).Replace("\"", string.Empty);
+ ret[i, j] = float.Parse(value, NumberStyles.Any, _cultureInfo);
+ }
+ }
+ }
+
+ reader.Close();
+ reader.Dispose();
+ return ret;
+ }
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/DelimitedWriter.cs b/src/Numerics/LinearAlgebra/Single/IO/DelimitedWriter.cs
new file mode 100644
index 00000000..416764c9
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/DelimitedWriter.cs
@@ -0,0 +1,168 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using Generic;
+
+ ///
+ /// Writes an to delimited text file. If the user does not
+ /// specify a delimiter, a tab separator is used.
+ ///
+ public class DelimitedWriter : MatrixWriter
+ {
+ ///
+ /// The delimiter to use.
+ ///
+ private readonly string _delimiter;
+
+ ///
+ /// The to use.
+ ///
+ private CultureInfo _cultureInfo = CultureInfo.CurrentCulture;
+
+ ///
+ /// Initializes a new instance of the class using
+ /// a comma as the delimiter.
+ ///
+ public DelimitedWriter()
+ {
+ _delimiter = ",";
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// using the given delimiter.
+ ///
+ ///
+ /// the delimiter to use.
+ ///
+ public DelimitedWriter(char delimiter)
+ {
+ _delimiter = new string(delimiter, 1);
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// using the given delimiter.
+ ///
+ ///
+ /// the delimiter to use.
+ ///
+ public DelimitedWriter(string delimiter)
+ {
+ _delimiter = delimiter;
+ }
+
+ ///
+ /// Gets or sets the column header values.
+ ///
+ /// The column header values.
+ /// Will write the column headers if the list is not empty or null.
+ public IList ColumnHeaders
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Gets or sets the to use when parsing the numbers.
+ ///
+ /// The culture info.
+ /// Defaults to CultureInfo.CurrentCulture.
+ public CultureInfo CultureInfo
+ {
+ get
+ {
+ return _cultureInfo;
+ }
+
+ set
+ {
+ if (value != null)
+ {
+ _cultureInfo = value;
+ }
+ }
+ }
+
+ ///
+ /// Writes the given to the given .
+ ///
+ /// The matrix to write.
+ /// The to write the matrix to.
+ /// The format to use on each element.
+ /// If either or is null.
+ protected override void DoWriteMatrix(Matrix matrix, TextWriter writer, string format)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ if (ColumnHeaders != null && ColumnHeaders.Count > 0)
+ {
+ for (var i = 0; i < ColumnHeaders.Count - 1; i++)
+ {
+ writer.Write(ColumnHeaders[i]);
+ writer.Write(_delimiter);
+ }
+
+ writer.WriteLine(ColumnHeaders[ColumnHeaders.Count - 1]);
+ }
+
+ var cols = matrix.ColumnCount - 1;
+ var rows = matrix.RowCount - 1;
+ for (var i = 0; i < matrix.RowCount; i++)
+ {
+ for (var j = 0; j < matrix.ColumnCount; j++)
+ {
+ writer.Write(matrix[i, j].ToString(format, _cultureInfo));
+ if (j != cols)
+ {
+ writer.Write(_delimiter);
+ }
+ }
+
+ if (i != rows)
+ {
+ writer.Write(Environment.NewLine);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/Matlab/MatlabFile.cs b/src/Numerics/LinearAlgebra/Single/IO/Matlab/MatlabFile.cs
new file mode 100644
index 00000000..01b216fe
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/Matlab/MatlabFile.cs
@@ -0,0 +1,219 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO.Matlab
+{
+ using System.Collections.Generic;
+ using Generic;
+
+ ///
+ /// Represents a Matlab file
+ ///
+ internal class MatlabFile
+ {
+ ///
+ /// Matrices in a matlab file stored as 1-D arrays
+ ///
+ private readonly IDictionary> _matrices = new SortedList>();
+
+ ///
+ /// Gets or sets the header text.
+ ///
+ /// The header text.
+ public string HeaderText { get; set; }
+
+ ///
+ /// Gets or sets the first name of the matrix.
+ ///
+ /// The first name of the matrix.
+ public string FirstMatrixName { get; set; }
+
+ ///
+ /// Gets the first matrix.
+ ///
+ /// The first matrix.
+ public Matrix FirstMatrix
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(FirstMatrixName) || !_matrices.ContainsKey(FirstMatrixName))
+ {
+ return null;
+ }
+
+ return _matrices[FirstMatrixName];
+ }
+ }
+
+ ///
+ /// Gets the matrices.
+ ///
+ /// The matrices.
+ public IDictionary> Matrices
+ {
+ get { return _matrices; }
+ }
+ }
+
+ /*
+ ///
+ /// An
+ ///
+ ///
+ ///
+ internal class ListDictionary : IDictionary
+ {
+ private readonly IList _keys = new List();
+ private readonly IList _values = new List();
+
+ public void Add(T key, K value)
+ {
+ _keys.Add(key);
+ _values.Add(value);
+ }
+
+ public bool ContainsKey(T key)
+ {
+ return _keys.Contains(key);
+ }
+
+ public ICollection Keys
+ {
+ get { return _keys; }
+ }
+
+ public bool Remove(T key)
+ {
+ if (_keys.Contains(key))
+ {
+ int pos = _keys.IndexOf(key);
+ _values.RemoveAt(pos);
+ _values.RemoveAt(pos);
+ return true;
+ }
+ return false;
+ }
+
+ public bool TryGetValue(T key, out K value)
+ {
+ if (_keys.Contains(key))
+ {
+ value = _values[_keys.IndexOf(key)];
+ return true;
+ }
+ value = default(K);
+ return false;
+ }
+
+ public ICollection Values
+ {
+ get { return _values; }
+ }
+
+ public K this[T key]
+ {
+ get
+ {
+ if (_keys.Contains(key))
+ {
+ return _values[_keys.IndexOf(key)];
+ }
+ throw new KeyNotFoundException();
+ }
+ set
+ {
+ if (_keys.Contains(key))
+ {
+ _values[_keys.IndexOf(key)] = value;
+ }
+ else
+ {
+ Add(key, value);
+ }
+ }
+ }
+
+ public void Add(KeyValuePair item)
+ {
+ Add(item.Key, item.Value);
+ }
+
+ public void Clear()
+ {
+ _keys.Clear();
+ _values.Clear();
+ }
+
+ public bool Contains(KeyValuePair item)
+ {
+ return _keys.Contains(item.Key) && _values[_keys.IndexOf(item.Key)].Equals(item.Value);
+ }
+
+ public void CopyTo(KeyValuePair[] array, int arrayIndex)
+ {
+ for (int i = 0; i < _keys.Count; i++)
+ {
+ array[arrayIndex + i] = new KeyValuePair(_keys[i], _values[i]);
+ }
+ }
+
+ public int Count
+ {
+ get { return _keys.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool Remove(KeyValuePair item)
+ {
+ if (Contains(item))
+ {
+ Remove(item.Key);
+ return true;
+ }
+ return false;
+ }
+
+ public IEnumerator> GetEnumerator()
+ {
+ for (int i = 0; i < _keys.Count; i++)
+ {
+ yield return new KeyValuePair(_keys[i], _values[i]);
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ }*/
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/Matlab/MatlabParser.cs b/src/Numerics/LinearAlgebra/Single/IO/Matlab/MatlabParser.cs
new file mode 100644
index 00000000..5c626022
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/Matlab/MatlabParser.cs
@@ -0,0 +1,536 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO.Matlab
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+ using Common.IO.Matlab;
+ using Generic;
+ using Properties;
+ using zlib;
+
+ ///
+ /// Parse a Matlab file
+ ///
+ internal class MatlabParser
+ {
+ ///
+ /// Large Block Size
+ ///
+ private const int LargeBlockSize = 8;
+
+ ///
+ /// Little Endian Indicator
+ ///
+ private const byte LittleEndianIndicator = 0x49;
+
+ ///
+ /// Small Block Size
+ ///
+ private const int SmallBlockSize = 4;
+
+ ///
+ /// Holds the names of the matrices in the file.
+ ///
+ private readonly IList _names = new List();
+
+ ///
+ /// The stream to read the matlab file from.
+ ///
+ private readonly Stream _stream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the file.
+ public MatlabParser(string fileName)
+ : this(fileName, new string[0])
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream to read from.
+ public MatlabParser(Stream stream)
+ : this(stream, new string[0])
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream to read from.
+ /// The name of the objects to retrieve.
+ public MatlabParser(Stream stream, IEnumerable objectNames)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+
+ _stream = stream;
+ SetNames(objectNames);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the file.
+ /// The name of the objects to retrieve.
+ public MatlabParser(string fileName, IEnumerable objectNames)
+ {
+ if (string.IsNullOrEmpty(fileName))
+ {
+ throw new ArgumentException(Resources.StringNullOrEmpty, "filename");
+ }
+
+ _stream = File.OpenRead(fileName);
+ SetNames(objectNames);
+ }
+
+ ///
+ /// Copies the names of the objects to retrieve to a local field.
+ ///
+ /// The name of the objects to retrieve.
+ private void SetNames(IEnumerable objectNames)
+ {
+ foreach (var name in objectNames)
+ {
+ _names.Add(name);
+ }
+ }
+
+ ///
+ /// Parses the file.
+ ///
+ /// The parsed Matlab file as a object.
+ public MatlabFile Parse()
+ {
+ var file = new MatlabFile();
+
+ using (var reader = new BinaryReader(_stream))
+ {
+ file.HeaderText = Encoding.ASCII.GetString(reader.ReadBytes(116));
+
+ // skipping subsystem offsets
+ reader.BaseStream.Position = 126;
+
+ if (reader.ReadByte() != LittleEndianIndicator)
+ {
+ throw new NotSupportedException(Resources.BigEndianNotSupported);
+ }
+
+ // skip version since it is always 0x0100.
+ reader.BaseStream.Position = 128;
+ var length = _stream.Length;
+
+ // for each data block add a matlab object to the file.
+ while (reader.BaseStream.Position < length)
+ {
+ var type = (DataType)reader.ReadInt16();
+ int size = reader.ReadInt16();
+ var smallBlock = true;
+ if (size == 0)
+ {
+ size = reader.ReadInt32();
+ smallBlock = false;
+ }
+
+ byte[] data;
+ if (type == DataType.Compressed)
+ {
+ data = DecompressBlock(reader.ReadBytes(size), ref type);
+ }
+ else
+ {
+ data = new byte[size];
+ reader.Read(data, 0, size);
+ AlignData(reader.BaseStream, size, smallBlock);
+ }
+
+ if (type == DataType.Matrix)
+ {
+ AddMatrix(data, file);
+ }
+ else
+ {
+ throw new NotSupportedException(string.Format(Resources.NotSupportedType, type));
+ }
+ }
+ }
+
+ return file;
+ }
+
+ ///
+ /// Aligns the data.
+ ///
+ /// The stream.
+ /// The size of the array.
+ /// if set to true if reading from a small block.
+ private static void AlignData(Stream stream, int size, bool smallBlock)
+ {
+ var blockSize = smallBlock ? SmallBlockSize : LargeBlockSize;
+ var offset = 0;
+ var mod = size % blockSize;
+ if (mod != 0)
+ {
+ offset = blockSize - mod;
+ }
+
+ stream.Seek(offset, SeekOrigin.Current);
+ }
+
+ ///
+ /// Decompresses the block.
+ ///
+ /// The compressed data.
+ /// The type data type contained in the block.
+ /// The decompressed block.
+ private static byte[] DecompressBlock(byte[] compressed, ref DataType type)
+ {
+ byte[] data;
+ using (var decompressed = new MemoryStream())
+ {
+ using (var decompressor = new ZOutputStream(decompressed))
+ {
+ decompressor.Write(compressed, 0, compressed.Length);
+ decompressed.Position = 0;
+ var buf = new byte[4];
+ decompressed.Read(buf, 0, 4);
+ type = (DataType)BitConverter.ToInt32(buf, 0);
+ decompressed.Read(buf, 0, 4);
+ var size = BitConverter.ToInt32(buf, 0);
+ data = new byte[size];
+ decompressed.Read(data, 0, size);
+ }
+ }
+
+ return data;
+ }
+
+ ///
+ /// Adds a matrix from the actual file into our presentation of a matlab file.
+ ///
+ /// The data of the matrix.
+ /// The instance.
+ private void AddMatrix(byte[] data, MatlabFile file)
+ {
+ using (var ms = new MemoryStream(data))
+ {
+ using (var reader = new BinaryReader(ms))
+ {
+ // skip tag - doesn't tell us anything we don't already know
+ reader.BaseStream.Seek(8, SeekOrigin.Current);
+
+ var arrayClass = (ArrayClass)reader.ReadByte();
+ var flags = reader.ReadByte();
+ var isComplex = (flags & (byte)ArrayFlags.Complex) == (byte)ArrayFlags.Complex;
+
+ if (isComplex)
+ {
+ throw new NotSupportedException(Resources.ComplexMatricesNotSupported);
+ }
+
+ // skip unneeded bytes
+ reader.BaseStream.Seek(10, SeekOrigin.Current);
+
+ var numDimensions = reader.ReadInt32() / 8;
+ if (numDimensions > 2)
+ {
+ throw new NotSupportedException(Resources.MoreThan2D);
+ }
+
+ var rows = reader.ReadInt32();
+ var columns = reader.ReadInt32();
+
+ // skip unneeded bytes
+ reader.BaseStream.Seek(2, SeekOrigin.Current);
+ int size = reader.ReadInt16();
+ var smallBlock = true;
+ if (size == 0)
+ {
+ size = reader.ReadInt32();
+ smallBlock = false;
+ }
+
+ var name = Encoding.ASCII.GetString(reader.ReadBytes(size));
+ AlignData(reader.BaseStream, size, smallBlock);
+
+ // only grab wanted objects
+ if (_names.Count != 0 && !_names.Contains(name))
+ {
+ return;
+ }
+
+ var type = (DataType)reader.ReadInt16();
+ size = reader.ReadInt16();
+ if (size == 0)
+ {
+ size = reader.ReadInt32();
+ }
+
+ Matrix matrix;
+ switch (arrayClass)
+ {
+ case ArrayClass.Sparse:
+ matrix = PopulateSparseMatrix(reader, rows, columns, size);
+ break;
+ case ArrayClass.Function:
+ case ArrayClass.Character:
+ case ArrayClass.Object:
+ case ArrayClass.Structure:
+ case ArrayClass.Cell:
+ case ArrayClass.Unknown:
+ throw new NotImplementedException();
+ default:
+ matrix = PopulateDenseMatrix(type, reader, rows, columns);
+ break;
+ }
+
+ file.Matrices.Add(name, matrix);
+ if (file.FirstMatrixName == null)
+ {
+ file.FirstMatrixName = name;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Populates a sparse matrix.
+ ///
+ /// The reader.
+ /// The number of rows.
+ /// The number of columns.
+ /// The size of the block.
+ /// A populated sparse matrix.
+ private static Matrix PopulateSparseMatrix(BinaryReader reader, int rows, int columns, int size)
+ {
+ // populate the row data array
+ var ir = new int[size / 4];
+ for (var i = 0; i < ir.Length; i++)
+ {
+ ir[i] = reader.ReadInt32();
+ }
+
+ AlignData(reader.BaseStream, size, false);
+
+ // skip data type since it will always be int32
+ reader.BaseStream.Seek(4, SeekOrigin.Current);
+
+ // populate the column data array
+ var jcsize = reader.ReadInt32();
+ var jc = new int[jcsize / 4];
+ for (var j = 0; j < jc.Length; j++)
+ {
+ jc[j] = reader.ReadInt32();
+ }
+
+ AlignData(reader.BaseStream, jcsize, false);
+
+ var type = (DataType)reader.ReadInt32();
+
+ // skip length since we already no it for the number of rows
+ reader.BaseStream.Seek(4, SeekOrigin.Current);
+
+ Matrix matrix = new SparseMatrix(rows, columns);
+ var col = 0;
+ for (var i = 0; i < ir.Length; i++)
+ {
+ var row = ir[i];
+ if (jc[col + 1] == i)
+ {
+ col++;
+ }
+
+ switch (type)
+ {
+ case DataType.Int8:
+ matrix[row, col] = reader.ReadSByte();
+ break;
+ case DataType.UInt8:
+ matrix[row, col] = reader.ReadByte();
+ break;
+ case DataType.Int16:
+ matrix[row, col] = reader.ReadInt16();
+ break;
+
+ case DataType.UInt16:
+ matrix[row, col] = reader.ReadUInt16();
+ break;
+ case DataType.Int32:
+ matrix[row, col] = reader.ReadInt32();
+ break;
+
+ case DataType.UInt32:
+ matrix[row, col] = reader.ReadUInt32();
+ break;
+ case DataType.Single:
+ matrix[row, col] = reader.ReadSingle();
+ break;
+ case DataType.Int64:
+ matrix[row, col] = reader.ReadInt64();
+ break;
+ case DataType.UInt64:
+ matrix[row, col] = reader.ReadUInt64();
+ break;
+ case DataType.Double:
+ matrix[row, col] = (float)reader.ReadDouble();
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+ }
+
+ return matrix;
+ }
+
+ ///
+ /// Populates a dense matrix.
+ ///
+ /// The type of data.
+ /// The reader.
+ /// The number of rows.
+ /// The number of columns.
+ /// Returns a populated dense matrix.
+ private static Matrix PopulateDenseMatrix(DataType type, BinaryReader reader, int rows, int columns)
+ {
+ Matrix matrix = new DenseMatrix(rows, columns);
+ switch (type)
+ {
+ case DataType.Int8:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadSByte();
+ }
+ }
+
+ break;
+ case DataType.UInt8:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadByte();
+ }
+ }
+
+ break;
+ case DataType.Int16:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadInt16();
+ }
+ }
+
+ break;
+ case DataType.UInt16:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadUInt16();
+ }
+ }
+
+ break;
+ case DataType.Int32:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadInt32();
+ }
+ }
+
+ break;
+ case DataType.UInt32:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadUInt32();
+ }
+ }
+
+ break;
+ case DataType.Single:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadSingle();
+ }
+ }
+
+ break;
+ case DataType.Int64:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadInt64();
+ }
+ }
+
+ break;
+ case DataType.UInt64:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = reader.ReadUInt64();
+ }
+ }
+
+ break;
+ case DataType.Double:
+ for (var j = 0; j < columns; j++)
+ {
+ for (var i = 0; i < rows; i++)
+ {
+ matrix[i, j] = (float)reader.ReadDouble();
+ }
+ }
+
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+
+ return matrix;
+ }
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/MatlabReader.cs b/src/Numerics/LinearAlgebra/Single/IO/MatlabReader.cs
new file mode 100644
index 00000000..2c748eaa
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/MatlabReader.cs
@@ -0,0 +1,190 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using Generic;
+ using Matlab;
+ using Properties;
+
+ ///
+ /// Creates matrices from Matlab files.
+ ///
+ public class MatlabMatrixReader
+ {
+ ///
+ /// The name of the file to read from.
+ ///
+ private readonly string _filename;
+
+ ///
+ /// The stream to read from if we are not reading from a file directly.
+ ///
+ private readonly Stream _stream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the file to read matrices from.
+ public MatlabMatrixReader(string filename)
+ {
+ if (string.IsNullOrEmpty(filename))
+ {
+ throw new ArgumentException(Resources.StringNullOrEmpty, "filename");
+ }
+
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException(Resources.FileDoesNotExist, "filename");
+ }
+
+ _filename = filename;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream to reader matrices from.
+ public MatlabMatrixReader(Stream stream)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+
+ _stream = stream;
+ }
+
+ ///
+ /// Reads the first matrix from the file or stream.
+ ///
+ ///
+ /// If the matrix is stored as a sparse matrix, then a is returned. Otherwise, a
+ /// is returned.
+ ///
+ public Matrix ReadMatrix()
+ {
+ return ReadMatrix(null);
+ }
+
+ ///
+ /// Reads the named matrix from the file or stream.
+ ///
+ /// The name of the matrix to read.
+ ///
+ /// If the matrix is stored as a sparse matrix, then a is returned. Otherwise, a
+ /// is returned. is returned if a matrix with the requests name doesn't exist.
+ ///
+ public Matrix ReadMatrix(string matrixName)
+ {
+ Stream stream;
+ if (_filename == null)
+ {
+ stream = _stream;
+ _stream.Seek(0, SeekOrigin.Begin);
+ }
+ else
+ {
+ stream = new FileStream(_filename, FileMode.Open, FileAccess.Read);
+ }
+
+ var names = string.IsNullOrEmpty(matrixName) ? new string[] { } : new[] { matrixName };
+ var parser = new MatlabParser(stream, names);
+ var file = parser.Parse();
+
+ Matrix matrix = null;
+ if (string.IsNullOrEmpty(matrixName))
+ {
+ matrix = file.FirstMatrix;
+ }
+ else if (file.Matrices.ContainsKey(matrixName))
+ {
+ matrix = file.Matrices[matrixName];
+ }
+
+ if (_filename != null)
+ {
+ stream.Close();
+ stream.Dispose();
+ }
+
+ return matrix;
+ }
+
+ ///
+ /// Reads all matrices from the file or stream.
+ ///
+ /// All matrices from the file or stream.
+ public Matrix[] ReadMatrices()
+ {
+ return ReadMatrices(new string[] { });
+ }
+
+ ///
+ /// Reads the named matrices from the file or stream.
+ ///
+ /// The names of the matrices to retrieve.
+ ///
+ /// The named matrices from the file or stream.
+ ///
+ public Matrix[] ReadMatrices(IEnumerable names)
+ {
+ Stream stream;
+ if (_filename == null)
+ {
+ stream = _stream;
+ _stream.Seek(0, SeekOrigin.Begin);
+ }
+ else
+ {
+ stream = new BufferedStream(new FileStream(_filename, FileMode.Open, FileAccess.Read));
+ }
+
+ var parser = new MatlabParser(stream, names);
+ var file = parser.Parse();
+
+ var matrices = new Matrix[file.Matrices.Count];
+ var i = 0;
+ foreach (var matrix in file.Matrices.Values)
+ {
+ matrices[i++] = matrix;
+ }
+
+ if (_filename != null)
+ {
+ stream.Close();
+ stream.Dispose();
+ }
+
+ return matrices;
+ }
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/MatrixReader.cs b/src/Numerics/LinearAlgebra/Single/IO/MatrixReader.cs
new file mode 100644
index 00000000..8f6364d0
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/MatrixReader.cs
@@ -0,0 +1,84 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+// Copyright (c) 2009-2010 Math.NET
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO
+{
+ using System;
+ using System.IO;
+ using Generic;
+ using Properties;
+
+ ///
+ /// Base class to read a single from a file or stream.
+ ///
+ /// The type of Matrix to return.
+ public abstract class MatrixReader where TMatrix : Matrix
+ {
+ ///
+ /// Reads a from a file.
+ ///
+ /// The file to read the matrix from.
+ /// A containing the data from the file. is returned if the file is empty.
+ /// If is .
+ /// If the file doesn't exist.
+ /// If a value is not a number or not in a valid format.
+ /// If a value represents a number less than or greater than .
+ public Matrix ReadMatrix(string file)
+ {
+ if (file == null)
+ {
+ throw new ArgumentNullException("file", Resources.StringNullOrEmpty);
+ }
+
+ return ReadMatrix(File.OpenRead(file));
+ }
+
+ ///
+ /// Reads a from a .
+ ///
+ /// The to read the matrix from.
+ /// A matrix containing the data from the . is returned if the is empty.
+ /// If is .
+ /// If a value is not a number or not in a valid format.
+ /// If a value represents a number less than or greater than .
+ public TMatrix ReadMatrix(Stream stream)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+
+ return DoReadMatrix(stream);
+ }
+
+ ///
+ /// Subclasses override this method to do the actual reading.
+ ///
+ /// The to read the matrix from.
+ /// A matrix containing the data from the . is returned if the is empty.
+ protected abstract TMatrix DoReadMatrix(Stream stream);
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/IO/MatrixWriter.cs b/src/Numerics/LinearAlgebra/Single/IO/MatrixWriter.cs
new file mode 100644
index 00000000..d1d9a2d3
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/IO/MatrixWriter.cs
@@ -0,0 +1,197 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+
+namespace MathNet.Numerics.LinearAlgebra.Single.IO
+{
+ using Generic;
+
+ ///
+ /// Base class to write a single to a file or stream.
+ ///
+ public abstract class MatrixWriter
+ {
+ ///
+ /// Writes the given to the given file. If the file already exists,
+ /// the file will be overwritten.
+ ///
+ /// The matrix to write.
+ /// The file to write the matrix to.
+ /// If either or is null.
+ public void WriteMatrix(Matrix matrix, string file)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (file == null)
+ {
+ throw new ArgumentNullException("file");
+ }
+
+ using (var writer = new StreamWriter(file))
+ {
+ DoWriteMatrix(matrix, writer, null);
+ }
+ }
+
+ ///
+ /// Writes the given to the given file. If the file already exists,
+ /// the file will be overwritten.
+ ///
+ /// the matrix to write.
+ /// The file to write the matrix to.
+ /// The format to use on each element.
+ /// If either or is null.
+ public void WriteMatrix(Matrix matrix, string file, string format)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (file == null)
+ {
+ throw new ArgumentNullException("file");
+ }
+
+ if (File.Exists(file))
+ {
+ File.Delete(file);
+ }
+
+ using (var writer = new StreamWriter(file))
+ {
+ DoWriteMatrix(matrix, writer, format);
+ }
+ }
+
+ ///
+ /// Writes the given to the given stream.
+ ///
+ /// The matrix to write.
+ /// The to write the matrix to.
+ /// If either or is null.
+ public void WriteMatrix(Matrix matrix, Stream stream)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+
+ using (var writer = new StreamWriter(stream))
+ {
+ DoWriteMatrix(matrix, writer, null);
+ }
+ }
+
+ ///
+ /// Writes the given to the given stream.
+ ///
+ /// The to write.
+ /// The to write the matrix to.
+ /// The format to use on each element.
+ /// If either or is null.
+ public void WriteMatrix(Matrix matrix, Stream stream, string format)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+
+ using (var writer = new StreamWriter(stream))
+ {
+ DoWriteMatrix(matrix, writer, format);
+ }
+ }
+
+ ///
+ /// Writes the given to the given .
+ ///
+ /// The matrix to write.
+ /// The to write the matrix to.
+ /// If either or is null.
+ public void WriteMatrix(Matrix matrix, TextWriter writer)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ DoWriteMatrix(matrix, writer, null);
+ }
+
+ ///
+ /// Writes the given to the given .
+ ///
+ /// The matrix to write.
+ /// The to write the matrix to.
+ /// The format to use on each element.
+ /// If either or is null.
+ public void WriteMatrix(Matrix matrix, TextWriter writer, string format)
+ {
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (writer == null)
+ {
+ throw new ArgumentNullException("writer");
+ }
+
+ DoWriteMatrix(matrix, writer, format);
+ }
+
+ ///
+ /// Subclasses must implement this method to do the actually writing.
+ ///
+ /// The matrix to serialize.
+ /// The to write the matrix to.
+ /// The format for the new matrix.
+ protected abstract void DoWriteMatrix(Matrix matrix, TextWriter writer, string format);
+ }
+}
diff --git a/src/Numerics/LinearAlgebra/Single/Solvers/Iterative/BiCgStab.cs b/src/Numerics/LinearAlgebra/Single/Solvers/Iterative/BiCgStab.cs
new file mode 100644
index 00000000..b37a286a
--- /dev/null
+++ b/src/Numerics/LinearAlgebra/Single/Solvers/Iterative/BiCgStab.cs
@@ -0,0 +1,520 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2010 Math.NET
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Iterative
+{
+ using System;
+ using Generic;
+ using Generic.Solvers;
+ using Generic.Solvers.Preconditioners;
+ using Generic.Solvers.Status;
+ using Preconditioners;
+ using Properties;
+
+ ///
+ /// A Bi-Conjugate Gradient stabilized iterative matrix solver.
+ ///
+ ///
+ ///
+ /// The Bi-Conjugate Gradient Stabilized (BiCGStab) solver is an 'improvement'
+ /// of the standard Conjugate Gradient (CG) solver. Unlike the CG solver the
+ /// BiCGStab can be used on non-symmetric matrices.
+ /// Note that much of the success of the solver depends on the selection of the
+ /// proper preconditioner.
+ ///
+ ///
+ /// The Bi-CGSTAB algorithm was taken from:
+ /// Templates for the solution of linear systems: Building blocks
+ /// for iterative methods
+ ///
+ /// Richard Barrett, Michael Berry, Tony F. Chan, James Demmel,
+ /// June M. Donato, Jack Dongarra, Victor Eijkhout, Roldan Pozo,
+ /// Charles Romine and Henk van der Vorst
+ ///
+ /// Url: http://www.netlib.org/templates/Templates.html
+ ///
+ /// Algorithm is described in Chapter 2, section 2.3.8, page 27
+ ///
+ ///
+ /// The example code below provides an indication of the possible use of the
+ /// solver.
+ ///
+ ///
+ public sealed class BiCgStab : IIterativeSolver
+ {
+ ///
+ /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
+ /// iterator.
+ ///
+ private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
+
+ ///
+ /// The preconditioner that will be used. Can be set to , in which case the default
+ /// pre-conditioner will be used.
+ ///
+ private IPreConditioner _preconditioner;
+
+ ///
+ /// The iterative process controller.
+ ///
+ private IIterator _iterator;
+
+ ///
+ /// Indicates if the user has stopped the solver.
+ ///
+ private bool _hasBeenStopped;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// When using this constructor the solver will use the with
+ /// the standard settings and a default preconditioner.
+ ///
+ public BiCgStab() : this(null, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ /// When using this constructor the solver will use a default preconditioner.
+ ///
+ ///
+ /// The main advantages of using a user defined are:
+ ///
+ /// - It is possible to set the desired convergence limits.
+ /// -
+ /// It is possible to check the reason for which the solver finished
+ /// the iterative procedure by calling the property.
+ ///
+ ///
+ ///
+ ///
+ /// The that will be used to monitor the iterative process.
+ public BiCgStab(IIterator iterator) : this(null, iterator)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// When using this constructor the solver will use the with
+ /// the standard settings.
+ ///
+ /// The that will be used to precondition the matrix equation.
+ public BiCgStab(IPreConditioner preconditioner) : this(preconditioner, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ /// The main advantages of using a user defined are:
+ ///
+ /// - It is possible to set the desired convergence limits.
+ /// -
+ /// It is possible to check the reason for which the solver finished
+ /// the iterative procedure by calling the property.
+ ///
+ ///
+ ///
+ ///
+ /// The that will be used to precondition the matrix equation.
+ /// The that will be used to monitor the iterative process.
+ public BiCgStab(IPreConditioner preconditioner, IIterator iterator)
+ {
+ _iterator = iterator;
+ _preconditioner = preconditioner;
+ }
+
+ ///
+ /// Sets the that will be used to precondition the iterative process.
+ ///
+ /// The preconditioner.
+ public void SetPreconditioner(IPreConditioner preconditioner)
+ {
+ _preconditioner = preconditioner;
+ }
+
+ ///
+ /// Sets the that will be used to track the iterative process.
+ ///
+ /// The iterator.
+ public void SetIterator(IIterator iterator)
+ {
+ _iterator = iterator;
+ }
+
+ ///
+ /// Gets the status of the iteration once the calculation is finished.
+ ///
+ public ICalculationStatus IterationResult
+ {
+ get
+ {
+ return (_iterator != null) ? _iterator.Status : DefaultStatus;
+ }
+ }
+
+ ///
+ /// Stops the solve process.
+ ///
+ ///
+ /// Note that it may take an indetermined amount of time for the solver to actually stop the process.
+ ///
+ public void StopSolve()
+ {
+ _hasBeenStopped = true;
+ }
+
+ ///
+ /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
+ /// solution vector and x is the unknown vector.
+ ///
+ /// The coefficient , A.
+ /// The solution , b.
+ /// The result , x.
+ public Vector Solve(Matrix matrix, Vector vector)
+ {
+ if (vector == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ Vector result = new DenseVector(matrix.RowCount);
+ Solve(matrix, vector, result);
+ return result;
+ }
+
+ ///
+ /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
+ /// solution vector and x is the unknown vector.
+ ///
+ /// The coefficient , A.
+ /// The solution , b.
+ /// The result , x.
+ public void Solve(Matrix matrix, Vector input, Vector result)
+ {
+ // If we were stopped before, we are no longer
+ // We're doing this at the start of the method to ensure
+ // that we can use these fields immediately.
+ _hasBeenStopped = false;
+
+ // Parameters checks
+ if (matrix == null)
+ {
+ throw new ArgumentNullException("matrix");
+ }
+
+ if (matrix.RowCount != matrix.ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
+ }
+
+ if (input == null)
+ {
+ throw new ArgumentNullException("input");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.Count != input.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength);
+ }
+
+ // Initialize the solver fields
+ // Set the convergence monitor
+ if (_iterator == null)
+ {
+ _iterator = Iterator.CreateDefault();
+ }
+
+ if (_preconditioner == null)
+ {
+ _preconditioner = new UnitPreconditioner();
+ }
+
+ _preconditioner.Initialize(matrix);
+
+ // Compute r_0 = b - Ax_0 for some initial guess x_0
+ // In this case we take x_0 = vector
+ // This is basically a SAXPY so it could be made a lot faster
+ Vector residuals = new DenseVector(matrix.RowCount);
+ CalculateTrueResidual(matrix, residuals, result, input);
+
+ // Choose r~ (for example, r~ = r_0)
+ var tempResiduals = residuals.Clone();
+ var temp = result.Clone();
+
+ // create five temporary vectors needed to hold temporary
+ // coefficients. All vectors are mangled in each iteration.
+ // These are defined here to prevent stressing the garbage collector
+ Vector vecP = new DenseVector(residuals.Count);
+ Vector vecPdash = new DenseVector(residuals.Count);
+ Vector nu = new DenseVector(residuals.Count);
+ Vector vecS = new DenseVector(residuals.Count);
+ Vector vecSdash = new DenseVector(residuals.Count);
+ Vector t = new DenseVector(residuals.Count);
+
+ // create some temporary float variables that are needed
+ // to hold values in between iterations
+ float currentRho = 0;
+ float alpha = 0;
+ float omega = 0;
+
+ var iterationNumber = 0;
+ while (ShouldContinue(iterationNumber, result, input, residuals))
+ {
+ // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
+ var oldRho = currentRho;
+ currentRho = tempResiduals.DotProduct(residuals);
+
+ // if (rho_(i-1) == 0) // METHOD FAILS
+ // If rho is only 1 ULP from zero then we fail.
+ if (currentRho.AlmostEqual(0, 1))
+ {
+ // Rho-type breakdown
+ throw new Exception("Iterative solver experience a numerical break down");
+ }
+
+ if (iterationNumber != 0)
+ {
+ // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
+ var beta = (currentRho / oldRho) * (alpha / omega);
+
+ // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
+ vecP.Add(nu.Multiply(-omega), vecP);
+
+ vecP.Multiply(beta, vecP);
+ vecP.Add(residuals, vecP);
+ }
+ else
+ {
+ // p_i = r_(i-1)
+ residuals.CopyTo(vecP);
+ }
+
+ // SOLVE Mp~ = p_i // M = preconditioner
+ _preconditioner.Approximate(vecP, vecPdash);
+
+ // nu_i = Ap~
+ matrix.Multiply(vecPdash, nu);
+
+ // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
+ alpha = currentRho * 1 / tempResiduals.DotProduct(nu);
+
+ // s = r_(i-1) - alpha_i nu_i
+ residuals.Add(nu.Multiply(-alpha), vecS);
+
+ // Check if we're converged. If so then stop. Otherwise continue;
+ // Calculate the temporary result.
+ // Be careful not to change any of the temp vectors, except for
+ // temp. Others will be used in the calculation later on.
+ // x_i = x_(i-1) + alpha_i * p^_i + s^_i
+ vecPdash.Multiply(alpha, temp);
+ temp.Add(vecSdash, temp);
+ temp.Add(result, temp);
+
+ // Check convergence and stop if we are converged.
+ if (!ShouldContinue(iterationNumber, temp, input, vecS))
+ {
+ temp.CopyTo(result);
+
+ // Calculate the true residual
+ CalculateTrueResidual(matrix, residuals, result, input);
+
+ // Now recheck the convergence
+ if (!ShouldContinue(iterationNumber, result, input, residuals))
+ {
+ // We're all good now.
+ return;
+ }
+
+ // Continue the calculation
+ iterationNumber++;
+ continue;
+ }
+
+ // SOLVE Ms~ = s
+ _preconditioner.Approximate(vecS, vecSdash);
+
+ // temp = As~
+ matrix.Multiply(vecSdash, t);
+
+ // omega_i = temp^T s / temp^T temp
+ omega = t.DotProduct(vecS) / t.DotProduct(t);
+
+ // x_i = x_(i-1) + alpha_i p^ + omega_i s^
+ result.Add(vecSdash.Multiply(omega), result);
+ result.Add(vecPdash.Multiply(alpha), result);
+
+ t.Multiply(-omega, residuals);
+ residuals.Add(vecS, residuals);
+
+ // for continuation it is necessary that omega_i != 0.0
+ // If omega is only 1 ULP from zero then we fail.
+ if (omega.AlmostEqual(0, 1))
+ {
+ // Omega-type breakdown
+ throw new Exception("Iterative solver experience a numerical break down");
+ }
+
+ if (!ShouldContinue(iterationNumber, result, input, residuals))
+ {
+ // Recalculate the residuals and go round again. This is done to ensure that
+ // we have the proper residuals.
+ // The residual calculation based on omega_i * s can be off by a factor 10. So here
+ // we calculate the real residual (which can be expensive) but we only do it if we're
+ // sufficiently close to the finish.
+ CalculateTrueResidual(matrix, residuals, result, input);
+ }
+
+ iterationNumber++;
+ }
+ }
+
+ ///
+ /// Calculates the true residual of the matrix equation Ax = b according to: residual = b - Ax
+ ///
+ /// Instance of the A.
+ /// Residual values in .
+ /// Instance of the x.
+ /// Instance of the b.
+ private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
+ {
+ // -Ax = residual
+ matrix.Multiply(x, residual);
+
+ // Do not use residual = residual.Negate() because it creates another object
+ residual.Multiply(-1, residual);
+
+ // residual + b
+ residual.Add(b, residual);
+ }
+
+ ///