/// <summary> /// Initializes a new instance of the <see cref="DenseQR"/> class. This object will compute the /// QR factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The QR factorization method to use.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception> public DenseQR(DenseMatrix matrix, QRMethod method = QRMethod.Full) { if (matrix == null) { throw new ArgumentNullException("matrix"); } if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch<ArgumentException>(matrix); } Tau = new Complex32[Math.Min(matrix.RowCount, matrix.ColumnCount)]; if (method == QRMethod.Full) { MatrixR = matrix.Clone(); MatrixQ = new DenseMatrix(matrix.RowCount); Control.LinearAlgebraProvider.QRFactor(((DenseMatrix)MatrixR).Values, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix)MatrixQ).Values, Tau); } else { MatrixQ = matrix.Clone(); MatrixR = new DenseMatrix(matrix.ColumnCount); Control.LinearAlgebraProvider.ThinQRFactor(((DenseMatrix)MatrixQ).Values, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix)MatrixR).Values, Tau); } }
/// <summary> /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the /// QR factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The QR factorization method to use.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> public static UserQR Create(Matrix<double> matrix, QRMethod method = QRMethod.Full) { if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch<ArgumentException>(matrix); } Matrix<double> q; Matrix<double> r; var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount); var u = new double[minmn][]; if (method == QRMethod.Full) { r = matrix.Clone(); q = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount); for (var i = 0; i < matrix.RowCount; i++) { q.At(i, i, 1.0); } for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(r, i, i); ComputeQR(u[i], r, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], q, i, matrix.RowCount, i, matrix.RowCount, Control.NumberOfParallelWorkerThreads); } } else { q = matrix.Clone(); for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(q, i, i); ComputeQR(u[i], q, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } r = q.SubMatrix(0, matrix.ColumnCount, 0, matrix.ColumnCount); q.Clear(); for (var i = 0; i < matrix.ColumnCount; i++) { q.At(i, i, 1.0); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], q, i, matrix.RowCount, i, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } } return new UserQR(q, r, method); }
/// <summary> /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the /// QR factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The QR factorization method to use.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> public static UserQR Create(Matrix<Complex> matrix, QRMethod method = QRMethod.Full) { if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch<ArgumentException>(matrix); } Matrix<Complex> q; Matrix<Complex> r; var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount); var u = new Complex[minmn][]; if (method == QRMethod.Full) { r = matrix.Clone(); q = Matrix<Complex>.Build.SameAs(matrix, matrix.RowCount, matrix.RowCount); for (var i = 0; i < matrix.RowCount; i++) { q.At(i, i, 1.0f); } for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(r, i, i); ComputeQR(u[i], r, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.MaxDegreeOfParallelism); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], q, i, matrix.RowCount, i, matrix.RowCount, Control.MaxDegreeOfParallelism); } } else { q = matrix.Clone(); for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(q, i, i); ComputeQR(u[i], q, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.MaxDegreeOfParallelism); } r = q.SubMatrix(0, matrix.ColumnCount, 0, matrix.ColumnCount); q.Clear(); for (var i = 0; i < matrix.ColumnCount; i++) { q.At(i, i, 1.0f); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], q, i, matrix.RowCount, i, matrix.ColumnCount, Control.MaxDegreeOfParallelism); } } return new UserQR(q, r, method); }
/// <summary> /// Initializes a new instance of the <see cref="DenseQR"/> class. This object will compute the /// QR factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The QR factorization method to use.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="matrix"/> row count is less then column count</exception> public static DenseQR Create(DenseMatrix matrix, QRMethod method = QRMethod.Full) { if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch<ArgumentException>(matrix); } var tau = new float[Math.Min(matrix.RowCount, matrix.ColumnCount)]; Matrix<float> q; Matrix<float> r; if (method == QRMethod.Full) { r = matrix.Clone(); q = new DenseMatrix(matrix.RowCount); Control.LinearAlgebraProvider.QRFactor(((DenseMatrix) r).Values, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix) q).Values, tau); } else { q = matrix.Clone(); r = new DenseMatrix(matrix.ColumnCount); Control.LinearAlgebraProvider.ThinQRFactor(((DenseMatrix) q).Values, matrix.RowCount, matrix.ColumnCount, ((DenseMatrix) r).Values, tau); } return new DenseQR(q, r, method, tau); }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>. </param> /// <param name="rowsA">The number of rows in the A matrix.</param> /// <param name="columnsA">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (rowsA < columnsA) { throw new ArgumentException(Resources.RowsLessThanColumns); } int rowsQ, columnsQ, rowsR, columnsR; if (method == QRMethod.Full) { rowsQ = columnsQ = rowsR = rowsA; columnsR = columnsA; } else { rowsQ = rowsA; columnsQ = rowsR = columnsR = columnsA; } if (r.Length != rowsR * columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); } if (q.Length != rowsQ * columnsQ) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); } if (b.Length != rowsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); } if (x.Length != columnsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); } var sol = new Complex32[b.Length]; // Copy B matrix to "sol", so B data will not be changed Array.Copy(b, sol, b.Length); // Compute Y = transpose(Q)*B var column = new Complex32[rowsA]; for (var j = 0; j < columnsB; j++) { var jm = j * rowsA; CommonParallel.For(0, rowsA, k => column[k] = sol[jm + k]); CommonParallel.For( 0, columnsA, i => { var im = i * rowsA; var sum = Complex32.Zero; for (var k = 0; k < rowsA; k++) { sum += q[im + k].Conjugate() * column[k]; } sol[jm + i] = sum; }); } // Solve R*X = Y; for (var k = columnsA - 1; k >= 0; k--) { var km = k * rowsR; for (var j = 0; j < columnsB; j++) { sol[(j * rowsA) + k] /= r[km + k]; } for (var i = 0; i < k; i++) { for (var j = 0; j < columnsB; j++) { var jm = j * rowsA; sol[jm + i] -= sol[jm + k] * r[km + i]; } } } // Fill result matrix CommonParallel.For( 0, columnsR, row => { for (var col = 0; col < columnsB; col++) { x[(col * columnsA) + row] = sol[row + (col * rowsA)]; } }); }
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] tau, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException(nameof(r)); } if (q == null) { throw new ArgumentNullException(nameof(q)); } if (b == null) { throw new ArgumentNullException(nameof(q)); } if (x == null) { throw new ArgumentNullException(nameof(q)); } if (r.Length != rowsR * columnsR) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(r)); } if (q.Length != rowsR * rowsR) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(q)); } if (b.Length != rowsR * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(b)); } if (x.Length != columnsR * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(x)); } if (rowsR < columnsR) { throw new ArgumentException(Resources.RowsLessThanColumns); } var work = new Complex[columnsR * Control.BlockSize]; QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work); }
/// <summary> /// Computes the QR decomposition for a matrix. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The type of QR factorization to perform.</param> /// <returns>The QR decomposition object.</returns> public static QR QR(this Matrix <float> matrix, QRMethod method = QRMethod.Full) { return((QR)QR <float> .Create(matrix, method)); }
public override void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (work == null) { throw new ArgumentNullException("work"); } int rowsQ, columnsQ, rowsR, columnsR; if (method == QRMethod.Full) { rowsQ = columnsQ = rowsR = rowsA; columnsR = columnsA; } else { rowsQ = rowsA; columnsQ = rowsR = columnsR = columnsA; } if (r.Length != rowsR*columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r"); } if (q.Length != rowsQ*columnsQ) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q"); } if (b.Length != rowsA*columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b"); } if (x.Length != columnsA*columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x"); } if (work.Length < 1) { work[0] = rowsA*Control.BlockSize; throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); } if (method == QRMethod.Full) { SafeNativeMethods.d_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length); } else { // we don't have access to the raw Q matrix any more(it is stored in R in the full QR), need to think about this. // let just call the managed version in the meantime. The heavy lifting has already been done. -marcus base.QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, QRMethod.Thin); } }
/// <summary> /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the /// QR factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The QR factorization method to use.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> public UserQR(Matrix<double> matrix, QRMethod method = QRMethod.Full) { if (matrix == null) { throw new ArgumentNullException("matrix"); } if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch<ArgumentException>(matrix); } QrMethod = method; var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount); var u = new double[minmn][]; if (method == QRMethod.Full) { MatrixR = matrix.Clone(); MatrixQ = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount); for (var i = 0; i < matrix.RowCount; i++) { MatrixQ.At(i, i, 1.0); } for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(MatrixR, i, i); ComputeQR(u[i], MatrixR, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.RowCount, Control.NumberOfParallelWorkerThreads); } } else { MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); MatrixQ = matrix.Clone(); for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(MatrixQ, i, i); ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } MatrixR = MatrixQ.SubMatrix(0, matrix.ColumnCount, 0, matrix.ColumnCount); MatrixQ.Clear(); for (var i = 0; i < matrix.ColumnCount; i++) { MatrixQ.At(i, i, 1.0); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } } }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be /// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param> /// <param name="rowsR">The number of rows in the A matrix.</param> /// <param name="columnsR">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">On entry the B matrix; on exit the X matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">The work array - only used in the native provider. 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.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] tau, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full) { QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, method); }
/// <summary> /// Computes the QR decomposition for a matrix. /// </summary> /// <param name="method">The type of QR factorization to perform.</param> /// <returns>The QR decomposition object.</returns> public abstract QR <T> QR(QRMethod method = QRMethod.Thin);
public override QR <Complex32> QR(QRMethod method = QRMethod.Thin) { return(DenseQR.Create(this, method)); }
protected QR(Matrix <float> q, Matrix <float> rFull, QRMethod method) : base(q, rFull, method) { }
private DenseQR(Matrix <double> q, Matrix <double> rFull, QRMethod method, double[] tau) : base(q, rFull, method) { Tau = tau; }
public override QR <double> QR(QRMethod method = QRMethod.Thin) { return(DenseQR.Create(this, method)); }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param> /// <param name="rowsA">The number of rows in the A matrix.</param> /// <param name="columnsA">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { ManagedLinearAlgebraProvider.Instance.QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, method); }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { ManagedLinearAlgebraProvider.Instance.QRSolve(a, rows, columns, b, columnsB, x, method); }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <remarks>Rows must be greater or equal to columns.</remarks> public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (a.Length != rows*columns) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); } if (b.Length != rows*columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); } if (x.Length != columns*columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resources.RowsLessThanColumns); } var work = new double[columns*Control.BlockSize]; QRSolve(a, rows, columns, b, columnsB, x, work); }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be /// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param> /// <param name="rowsR">The number of rows in the A matrix.</param> /// <param name="columnsR">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">On entry the B matrix; on exit the X matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">The work array - only used in the native provider. 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.</param> /// <remarks>Rows must be greater or equal to columns.</remarks> public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (work == null) { throw new ArgumentNullException("work"); } 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"); } if (rowsR < columnsR) { throw new ArgumentException(Resources.RowsLessThanColumns); } if (work.Length < 1) { work[0] = rowsR*Control.BlockSize; throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); } SafeNativeMethods.d_qr_solve_factored(rowsR, columnsR, columnsB, r, b, tau, x, work, work.Length); }
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { var work = new Complex32[columns * Control.BlockSize]; QRSolve(a, rows, columns, b, columnsB, x, work, method); }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">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.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (work == null) { throw new ArgumentNullException("work"); } if (a.Length != rows * columns) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); } if (b.Length != rows * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); } if (x.Length != columns * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resources.RowsLessThanColumns); } if (work.Length < rows * columns) { work[0] = rows * columns; throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); } var clone = new double[a.Length]; a.Copy(clone); if (method == QRMethod.Full) { var q = new double[rows * rows]; QRFactor(clone, rows, columns, q, work); QRSolveFactored(q, clone, rows, columns, null, b, columnsB, x, method); } else { var r = new double[columns * columns]; ThinQRFactor(clone, rows, columns, r, work); QRSolveFactored(clone, r, rows, columns, null, b, columnsB, x, method); } work[0] = rows * columns; }
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { var work = new Complex32[columnsR * Control.BlockSize]; QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method); }
UserQR(Matrix<Complex> q, Matrix<Complex> rFull, QRMethod method) : base(q, rFull, method) { }
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (work == null) { throw new ArgumentNullException("work"); } int rowsQ, columnsQ, rowsR, columnsR; if (method == QRMethod.Full) { rowsQ = columnsQ = rowsR = rowsA; columnsR = columnsA; } else { rowsQ = rowsA; columnsQ = rowsR = columnsR = columnsA; } if (r.Length != rowsR * columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); } if (q.Length != rowsQ * columnsQ) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); } if (b.Length != rowsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); } if (x.Length != columnsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); } if (work.Length < 1) { work[0] = rowsA * Control.BlockSize; throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); } if (method == QRMethod.Full) { SafeNativeMethods.c_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length); } else { // we don't have access to the raw Q matrix any more(it is stored in R in the full QR), need to think about this. // let just call the managed version in the meantime. The heavy lifting has already been done. -marcus base.QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, QRMethod.Thin); } }
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (work == null) { throw new ArgumentNullException("work"); } if (a.Length != rows*columns) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); } if (b.Length != rows*columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); } if (x.Length != columns*columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resources.RowsLessThanColumns); } if (work.Length < 1) { work[0] = rows*Control.BlockSize; throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); } SafeNativeMethods.d_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length); }
DenseQR(Matrix <float> q, Matrix <float> rFull, QRMethod method, float[] tau) : base(q, rFull, method) { Tau = tau; }
public override void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } int rowsQ, columnsQ, rowsR, columnsR; if (method == QRMethod.Full) { rowsQ = columnsQ = rowsR = rowsA; columnsR = columnsA; } else { rowsQ = rowsA; columnsQ = rowsR = columnsR = columnsA; } if (r.Length != rowsR * columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r"); } if (q.Length != rowsQ * columnsQ) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q"); } if (b.Length != rowsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b"); } if (x.Length != columnsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x"); } if (method == QRMethod.Full) { var info = SafeNativeMethods.s_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x); if (info == (int)NativeError.MemoryAllocation) { throw new MemoryAllocationException(); } if (info < 0) { throw new InvalidParameterException(Math.Abs(info)); } } else { // we don't have access to the raw Q matrix any more(it is stored in R in the full QR), need to think about this. // let just call the managed version in the meantime. The heavy lifting has already been done. -marcus base.QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, QRMethod.Thin); } }
protected QR(Matrix <Complex> q, Matrix <Complex> rFull, QRMethod method) : base(q, rFull, method) { }
public void CanSolveForMatrixWithTallRandomMatrix(QRMethod method) { var matrixA = Matrix<Complex>.Build.Random(20, 10, 1); var matrixACopy = matrixA.Clone(); var factorQR = matrixA.QR(method); var matrixB = Matrix<Complex>.Build.Random(20, 5, 1); var matrixX = factorQR.Solve(matrixB); // The solution X row dimension is equal to the column dimension of A Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); // The solution X has the same number of columns as B Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); var test = (matrixA.ConjugateTranspose() * matrixA).Inverse() * matrixA.ConjugateTranspose() * matrixB; for (var i = 0; i < matrixX.RowCount; i++) { for (var j = 0; j < matrixX.ColumnCount; j++) { AssertHelpers.AlmostEqual(test[i, j], matrixX[i, j], 12); } } // Make sure A didn't change. for (var i = 0; i < matrixA.RowCount; i++) { for (var j = 0; j < matrixA.ColumnCount; j++) { Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]); } } }
UserQR(Matrix <Complex32> q, Matrix <Complex32> rFull, QRMethod method) : base(q, rFull, method) { }
DenseQR(Matrix<double> q, Matrix<double> rFull, QRMethod method, double[] tau) : base(q, rFull, method) { Tau = tau; }
public void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException(nameof(a)); } if (b == null) { throw new ArgumentNullException(nameof(b)); } if (x == null) { throw new ArgumentNullException(nameof(x)); } if (a.Length != rows * columns) { throw new ArgumentException("The array arguments must have the same length.", nameof(a)); } if (b.Length != rows * columnsB) { throw new ArgumentException("The array arguments must have the same length.", nameof(b)); } if (x.Length != columns * columnsB) { throw new ArgumentException("The array arguments must have the same length.", nameof(x)); } if (rows < columns) { throw new ArgumentException("The number of rows must greater than or equal to the number of columns."); } var info = SafeNativeMethods.c_qr_solve(rows, columns, columnsB, a, b, x); if (info == (int)MklError.MemoryAllocation) { throw new MemoryAllocationException(); } if (info < 0) { throw new InvalidParameterException(Math.Abs(info)); } if (info > 0) { throw new ArgumentException("Matrix must not be rank deficient.", nameof(a)); } }
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (r.Length != rowsR * columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r"); } if (tau.Length < Math.Min(rowsR, columnsR)) { throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); } if (q.Length != rowsR * rowsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q"); } var work = new float[columnsR * Control.BlockSize]; SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length); }
DenseQR(Matrix <Complex> q, Matrix <Complex> rFull, QRMethod method, Complex[] tau) : base(q, rFull, method) { Tau = tau; }
public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { 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"); } if (rowsR < columnsR) { throw new ArgumentException(Resources.RowsLessThanColumns); } var work = new double[columnsR*Control.BlockSize]; QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work); }
UserQR(Matrix <float> q, Matrix <float> rFull, QRMethod method) : base(q, rFull, method) { }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full) { var work = new Complex[rows*columns]; QRSolve(a, rows, columns, b, columnsB, x, work, method); }
protected QR(Matrix <double> q, Matrix <double> rFull, QRMethod method) : base(q, rFull, method) { }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { var work = new double[rows * columns]; QRSolve(a, rows, columns, b, columnsB, x, work, method); }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <remarks>Rows must be greater or equal to columns.</remarks> public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (a.Length != rows * columns) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "a"); } if (b.Length != rows * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "b"); } if (x.Length != columns * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resource.RowsLessThanColumns); } var work = new double[columns * Control.BlockSize]; QRSolve(a, rows, columns, b, columnsB, x, work); }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be /// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param> /// <param name="rowsA">The number of rows in the A matrix.</param> /// <param name="columnsA">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">On entry the B matrix; on exit the X matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">The work array - only used in the native provider. 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.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, method); }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">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.</param> /// <remarks>Rows must be greater or equal to columns.</remarks> public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (work == null) { throw new ArgumentNullException("work"); } if (a.Length != rows * columns) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "a"); } if (b.Length != rows * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "b"); } if (x.Length != columns * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resource.RowsLessThanColumns); } if (work.Length < 1) { work[0] = rows * Control.BlockSize; throw new ArgumentException(Resource.WorkArrayTooSmall, "work"); } SafeNativeMethods.d_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length); }
DenseQR(Matrix<float> q, Matrix<float> rFull, QRMethod method, float[] tau) : base(q, rFull, method) { Tau = tau; }
public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (r.Length != rowsR * columnsR) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "r"); } if (q.Length != rowsR * rowsR) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "q"); } if (b.Length != rowsR * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "b"); } if (x.Length != columnsR * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "x"); } if (rowsR < columnsR) { throw new ArgumentException(Resource.RowsLessThanColumns); } var work = new double[columnsR * Control.BlockSize]; QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work); }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be /// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[],QRMethod)"/>. </param> /// <param name="rowsR">The number of rows in the A matrix.</param> /// <param name="columnsR">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">On entry the B matrix; on exit the X matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">The work array - only used in the native provider. 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.</param> /// <remarks>Rows must be greater or equal to columns.</remarks> public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (work == null) { throw new ArgumentNullException("work"); } if (r.Length != rowsR * columnsR) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "r"); } if (q.Length != rowsR * rowsR) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "q"); } if (b.Length != rowsR * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "b"); } if (x.Length != columnsR * columnsB) { throw new ArgumentException(Resource.ArgumentArraysSameLength, "x"); } if (rowsR < columnsR) { throw new ArgumentException(Resource.RowsLessThanColumns); } if (work.Length < 1) { work[0] = rowsR * Control.BlockSize; throw new ArgumentException(Resource.WorkArrayTooSmall, "work"); } SafeNativeMethods.d_qr_solve_factored(rowsR, columnsR, columnsB, r, b, tau, x, work, work.Length); }
UserQR(Matrix <double> q, Matrix <double> rFull, QRMethod method) : base(q, rFull, method) { }
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { var work = new double[columns*Control.BlockSize]; QRSolve(a, rows, columns, b, columnsB, x, work, method); }
/// <summary> /// Initializes a new instance of the <see cref="UserQR"/> class. This object will compute the /// QR factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <param name="method">The QR factorization method to use.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> public UserQR(Matrix <Complex32> matrix, QRMethod method = QRMethod.Full) { if (matrix == null) { throw new ArgumentNullException("matrix"); } if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch <ArgumentException>(matrix); } QrMethod = method; var minmn = Math.Min(matrix.RowCount, matrix.ColumnCount); var u = new Complex32[minmn][]; if (method == QRMethod.Full) { MatrixR = matrix.Clone(); MatrixQ = matrix.CreateMatrix(matrix.RowCount, matrix.RowCount); for (var i = 0; i < matrix.RowCount; i++) { MatrixQ.At(i, i, 1.0f); } for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(MatrixR, i, i); ComputeQR(u[i], MatrixR, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.RowCount, Control.NumberOfParallelWorkerThreads); } } else { MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); MatrixQ = matrix.Clone(); for (var i = 0; i < minmn; i++) { u[i] = GenerateColumn(MatrixQ, i, i); ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i + 1, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } MatrixR = MatrixQ.SubMatrix(0, matrix.ColumnCount, 0, matrix.ColumnCount); MatrixQ.Clear(); for (var i = 0; i < matrix.ColumnCount; i++) { MatrixQ.At(i, i, 1.0f); } for (var i = minmn - 1; i >= 0; i--) { ComputeQR(u[i], MatrixQ, i, matrix.RowCount, i, matrix.ColumnCount, Control.NumberOfParallelWorkerThreads); } } }
public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) { var work = new double[columnsR*Control.BlockSize]; QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method); }
public override QR<Complex32> QR(QRMethod method = QRMethod.Thin) { return DenseQR.Create(this, method); }
public override void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (a.Length != rows * columns) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); } if (b.Length != rows * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); } if (x.Length != columns * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resources.RowsLessThanColumns); } var info = SafeNativeMethods.s_qr_solve(rows, columns, columnsB, a, b, x); if (info == (int)NativeError.MemoryAllocation) { throw new MemoryAllocationException(); } if (info < 0) { throw new InvalidParameterException(Math.Abs(info)); } if (info > 0) { throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a"); } }
/// <summary> /// Solves A*X=B for X using QR factorization of A. /// </summary> /// <param name="a">The A matrix.</param> /// <param name="rows">The number of rows in the A matrix.</param> /// <param name="columns">The number of columns in the A matrix.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (x == null) { throw new ArgumentNullException("x"); } if (a.Length != rows*columns) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); } if (b.Length != rows*columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); } if (x.Length != columns*columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); } if (rows < columns) { throw new ArgumentException(Resources.RowsLessThanColumns); } var work = new float[rows * columns]; var clone = new float[a.Length]; a.Copy(clone); if (method == QRMethod.Full) { var q = new float[rows*rows]; QRFactor(clone, rows, columns, q, work); QRSolveFactored(q, clone, rows, columns, null, b, columnsB, x, method); } else { var r = new float[columns*columns]; ThinQRFactor(clone, rows, columns, r, work); QRSolveFactored(clone, r, rows, columns, null, b, columnsB, x, method); } }
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { if (a == null) { throw new ArgumentNullException(nameof(a)); } if (b == null) { throw new ArgumentNullException(nameof(b)); } if (x == null) { throw new ArgumentNullException(nameof(x)); } if (a.Length != rows * columns) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(a)); } if (b.Length != rows * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(b)); } if (x.Length != columns * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(x)); } if (rows < columns) { throw new ArgumentException(Resources.RowsLessThanColumns); } var info = SafeNativeMethods.c_qr_solve(rows, columns, columnsB, a, b, x); if (info == (int)MklError.MemoryAllocation) { throw new MemoryAllocationException(); } if (info < 0) { throw new InvalidParameterException(Math.Abs(info)); } if (info > 0) { throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, nameof(a)); } }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be /// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param> /// <param name="rowsR">The number of rows in the A matrix.</param> /// <param name="columnsR">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">On entry the B matrix; on exit the X matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="work">The work array - only used in the native provider. 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.</param> /// <remarks>Rows must be greater or equal to columns.</remarks> public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] tau, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException(nameof(r)); } if (q == null) { throw new ArgumentNullException(nameof(q)); } if (b == null) { throw new ArgumentNullException(nameof(q)); } if (x == null) { throw new ArgumentNullException(nameof(q)); } if (work == null) { throw new ArgumentNullException(nameof(work)); } if (r.Length != rowsR * columnsR) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(r)); } if (q.Length != rowsR * rowsR) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(q)); } if (b.Length != rowsR * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(b)); } if (x.Length != columnsR * columnsB) { throw new ArgumentException(Resources.ArgumentArraysSameLength, nameof(x)); } if (rowsR < columnsR) { throw new ArgumentException(Resources.RowsLessThanColumns); } if (work.Length < 1) { work[0] = rowsR * Control.BlockSize; throw new ArgumentException(Resources.WorkArrayTooSmall, nameof(work)); } SafeNativeMethods.z_qr_solve_factored(rowsR, columnsR, columnsB, r, b, tau, x, work, work.Length); }
public override QR<double> QR(QRMethod method = QRMethod.Thin) { return DenseQR.Create(this, method); }
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException(nameof(r)); } if (q == null) { throw new ArgumentNullException(nameof(q)); } if (b == null) { throw new ArgumentNullException(nameof(q)); } if (x == null) { throw new ArgumentNullException(nameof(q)); } int rowsQ, columnsQ, rowsR, columnsR; if (method == QRMethod.Full) { rowsQ = columnsQ = rowsR = rowsA; columnsR = columnsA; } else { rowsQ = rowsA; columnsQ = rowsR = columnsR = columnsA; } if (r.Length != rowsR * columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), nameof(r)); } if (q.Length != rowsQ * columnsQ) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), nameof(q)); } if (b.Length != rowsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), nameof(b)); } if (x.Length != columnsA * columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), nameof(x)); } if (method == QRMethod.Full) { var info = SafeNativeMethods.c_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x); if (info == (int)MklError.MemoryAllocation) { throw new MemoryAllocationException(); } if (info < 0) { throw new InvalidParameterException(Math.Abs(info)); } } else { // we don't have access to the raw Q matrix any more(it is stored in R in the full QR), need to think about this. // let just call the managed version in the meantime. The heavy lifting has already been done. -marcus base.QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, QRMethod.Thin); } }
/// <summary> /// Solves A*X=B for X using a previously QR factored matrix. /// </summary> /// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>.</param> /// <param name="r">The R matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>. </param> /// <param name="rowsA">The number of rows in the A matrix.</param> /// <param name="columnsA">The number of columns in the A matrix.</param> /// <param name="tau">Contains additional information on Q. Only used for the native solver /// and can be <c>null</c> for the managed provider.</param> /// <param name="b">The B matrix.</param> /// <param name="columnsB">The number of columns of B.</param> /// <param name="x">On exit, the solution matrix.</param> /// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param> /// <remarks>Rows must be greater or equal to columns.</remarks> public virtual void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (b == null) { throw new ArgumentNullException("q"); } if (x == null) { throw new ArgumentNullException("q"); } if (rowsA < columnsA) { throw new ArgumentException(Resources.RowsLessThanColumns); } int rowsQ, columnsQ, rowsR, columnsR; if (method == QRMethod.Full) { rowsQ = columnsQ = rowsR = rowsA; columnsR = columnsA; } else { rowsQ = rowsA; columnsQ = rowsR = columnsR = columnsA; } if (r.Length != rowsR*columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r"); } if (q.Length != rowsQ*columnsQ) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q"); } if (b.Length != rowsA*columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b"); } if (x.Length != columnsA*columnsB) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "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[rowsA]; for (var j = 0; j < columnsB; j++) { var jm = j*rowsA; Array.Copy(sol, jm, column, 0, rowsA); CommonParallel.For(0, columnsA, (u, v) => { for (int i = u; i < v; i++) { var im = i*rowsA; var sum = 0.0f; for (var k = 0; k < rowsA; k++) { sum += q[im + k]*column[k]; } sol[jm + i] = sum; } }); } // Solve R*X = Y; for (var k = columnsA - 1; k >= 0; k--) { var km = k*rowsR; for (var j = 0; j < columnsB; j++) { sol[(j*rowsA) + k] /= r[km + k]; } for (var i = 0; i < k; i++) { for (var j = 0; j < columnsB; j++) { var jm = j*rowsA; sol[jm + i] -= sol[jm + k]*r[km + i]; } } } // Fill result matrix for (var col = 0; col < columnsB; col++) { Array.Copy(sol, col*rowsA, x, col*columnsA, columnsR); } }
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau, QRMethod method = QRMethod.Full) { if (r == null) { throw new ArgumentNullException("r"); } if (q == null) { throw new ArgumentNullException("q"); } if (r.Length != rowsR * columnsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r"); } if (tau.Length < Math.Min(rowsR, columnsR)) { throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); } if (q.Length != rowsR * rowsR) { throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q"); } var work = new Complex32[columnsR * Control.BlockSize]; SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length); }
public void CanSolveForVectorWithTallRandomMatrix(QRMethod method) { var matrixA = Matrix<Complex>.Build.Random(20, 10, 1); var matrixACopy = matrixA.Clone(); var factorQR = matrixA.QR(method); var vectorB = Vector<Complex>.Build.Random(20, 1); var vectorX = factorQR.Solve(vectorB); // The solution x dimension is equal to the column dimension of A Assert.AreEqual(matrixA.ColumnCount, vectorX.Count); var test = (matrixA.ConjugateTranspose() * matrixA).Inverse() * matrixA.ConjugateTranspose()* vectorB; for (var i = 0; i < vectorX.Count; i++) { AssertHelpers.AlmostEqual(test[i], vectorX[i], 9); } // Make sure A didn't change. for (var i = 0; i < matrixA.RowCount; i++) { for (var j = 0; j < matrixA.ColumnCount; j++) { Assert.AreEqual(matrixACopy[i, j], matrixA[i, j]); } } }
public override QR <float> QR(QRMethod method = QRMethod.Thin) { return(UserQR.Create(this, method)); }