/// <summary>Computes the Cholesky decomposition of a Hermitian positive-definite matrix, i.e. A = conj(U') * U or A = L * conj(L'), where L is a lower triangular matrix and U is upper triangular. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="a">The matrix A supplied column-by-column of dimension (<paramref name="n"/>; <paramref name="n"/>); overwritten by the upper or lower triangular matrix U, L respectively.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> public void zpotrf(int n, Complex[] a, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { int info; var uplo = LAPACK.GetUplo(triangularMatrixType); _zpotrf(ref uplo, ref n, a, ref n, out info); CheckForError(info, "zpotrf"); }
/// <summary>Computes the Cholesky factorization of a symmetric positive-definite matrix using packed storage, i.e. /// A = U' * U or A = L * L', where L is a lower triangular matrix and U is upper triangular. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="aPacked">Either the upper or lower triangular part of matrix A in packed storage, i.e. at least <paramref name="n"/> * (<paramref name="n"/> + 1)/2 elements; overwritten by the upper or lower triangular matrix U, L respectively in packed storage.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> public void dpptrf(int n, double[] aPacked, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { int info; var uplo = LAPACK.GetUplo(triangularMatrixType); _dpptrf(ref uplo, ref n, aPacked, out info); CheckForError(info, "dpptrf"); }
/// <summary>Computes the Bunch-Kaufman factorization of a Hermitian matrix using packed storage, i.e. A = P * U * D * conj(U') * conj(P') or A = P * L * D * conj(L') * conj(P'), where P is a permutation matrix, U and L are upper and /// lower triangular matrices with unit diagonal and D is a symmetric block-diagonal matrix with 1-by-1 and 2-by-2 diagonal blocks. U and L have 2-by-2 unit diagonal blocks corresponding to the 2-by-2 blocks of D. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="aPacked">Either the upper or lower triangular part of matrix A in packed storage, i.e. at least <paramref name="n"/> * (<paramref name="n"/> + 1)/2 elements; overwritten by details of the block-diagonal matrix D and the multiplies used to obtain the factor U (or L).</param> /// <param name="iPivot">Contains details of the interchanges an the block structure of D, at least <paramref name="n"/> elements (output).</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> public void zhptrf(int n, Complex[] aPacked, int[] iPivot, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { int info; var uplo = LAPACK.GetUplo(triangularMatrixType); _zhptrf(ref uplo, ref n, aPacked, iPivot, out info); CheckForError(info, "zhptrf"); }
/// <summary>Computes the Cholesky factorization of a Hermitian positive-definite band matrix, i.e. i.e. A = conj(U') * U or A = L * conj(L'), where L is a lower triangular matrix and U is upper triangular. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="kd">The number of superdiagonals or subdiagonals in the input matrix.</param> /// <param name="a">Either the upper or lower triangular part of the input matrix in band storage of dimension (<paramref name="kd"/> + 1; <paramref name="n"/>); overwritten by the upper or lower triangular matrix U, L respectively.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> public void zpbtrf(int n, int kd, Complex[] a, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { int info; int lda = kd + 1; var uplo = LAPACK.GetUplo(triangularMatrixType); _zpbtrf(ref uplo, ref n, ref kd, a, ref lda, out info); CheckForError(info, "zpbtrf"); }
/// <summary>Computes the Cholesky factorization of a Hermitian positive-definite matrix using the Rectangular Full Packed (RFP) format, i.e. /// A = conj(U') * U or A = L * conj(L'), where L is a lower triangular matrix and U is upper triangular. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="a">The matrix A in the RFP format, i.e. an array with at least <paramref name="n"/> * (<paramref name="n"/> + 1) / 2 elements; overwritten by the upper or lower triangular matrix U, L respectively.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> /// <param name="transposeState">A value indicating whether <paramref name="a"/> represents matrix A or its transposed.</param> public void zpftrf(int n, Complex[] a, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix, BLAS.MatrixTransposeState transposeState = BLAS.MatrixTransposeState.NoTranspose) { int info; var trans = LAPACK.GetTrans(transposeState); var uplo = LAPACK.GetUplo(triangularMatrixType); _zpftrf(ref trans, ref uplo, ref n, a, out info); CheckForError(info, "zpftrf"); }
/// <summary>Computes the Bunch-Kaufman factorization of a complex Hermitian matrix, i.e. A = P * U * D * conj(U') * conj(P') or A = P * L * D * conj(L') * conj(P'), where P is a permutation matrix, U and L are upper and /// lower triangular matrices with unit diagonal and D is a symmetric block-diagonal matrix with 1-by-1 and 2-by-2 diagonal blocks. U and L have 2-by-2 unit diagonal blocks corresponding to the 2-by-2 blocks of D. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="a">The upper or the lower triangular part of the input matrix of dimension (<paramref name="n"/>; <paramref name="n"/>); overwritten by details of the block-diagonal matrix D and the multiplies used to obtain the factor U (or L).</param> /// <param name="iPivot">Contains details of the interchanges an the block structure of D, at least <paramref name="n"/> elements (output).</param> /// <param name="work">A workspace array of length at least <paramref name="n"/>.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> public void zhetrf(int n, Complex[] a, int[] iPivot, Complex[] work, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { int info; int lwork = work.Length; var uplo = LAPACK.GetUplo(triangularMatrixType); _zhetrf(ref uplo, ref n, a, ref n, iPivot, work, ref lwork, out info); CheckForError(info, "zhetrf"); }
/// <summary>Performs a rank-1 update of a Hermitian matrix, i.e. A := \alpha * x * conj(x^t) + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" />-1) * |<paramref name="incX" />| elements.</param> /// <param name="a">The Hermitian matrix A with dimension (<paramref name="lda" />, <paramref name="n" />).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void zher(int n, double alpha, Complex[] x, Complex[] a, int lda, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } else if (incX != 1) { kx = 1; } if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = alpha * Complex.Conjugate(x[jx - 1]); int ix = kx; for (int i = 1; i <= j - 1; i++) { a[i - 1 + (j - 1) * lda] += x[ix - 1] * temp; ix += incX; } a[j - 1 + (j - 1) * lda] = (a[j - 1 + (j - 1) * lda] + x[jx - 1] * temp).Real; jx += incX; } } else { int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = alpha * Complex.Conjugate(x[jx - 1]); a[j - 1 + (j - 1) * lda] = (a[j - 1 + (j - 1) * lda] + temp * x[jx - 1]).Real; int ix = jx; for (int i = j + 1; i <= n; i++) { ix += incX; a[i - 1 + (j - 1) * lda] += x[ix - 1] * temp; } jx += incX; } } }
/// <summary>Performs a rank-1 update of a Hermitian packed matrix, i.e. A := \alpha * x * conjg(x^t) + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" />-1) * |<paramref name="incX" />| elements.</param> /// <param name="aPacked">The Hermitian packed matrix A with dimension at least (<paramref name="n" /> * (<paramref name="n" /> + 1) ) / 2.</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void zhpr(int n, double alpha, Complex[] x, Complex[] aPacked, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } int kk = 1; if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = alpha * Complex.Conjugate(x[jx - 1]); int ix = kx; for (int k = kk; k <= kk + j - 2; k++) { aPacked[k - 1] += x[ix - 1] * temp; ix += incX; } aPacked[kk + j - 2] = (aPacked[kk + j - 2] + x[jx - 1] * temp).Real; jx += incX; kk += j; } } else { int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = alpha * Complex.Conjugate(x[jx - 1]); aPacked[kk - 1] = (aPacked[kk - 1] + temp * x[jx - 1]).Real; int ix = jx; for (int k = kk + 1; k <= kk + n - j; k++) { ix += incX; aPacked[k - 1] += x[ix - 1] * temp; } jx += incX; kk = kk + n - j + 1; } } }
/// <summary>Gets the <see cref="System.Char"/> representation of a value indicating whether the lower or upper triangular part of a matrix should take into account. /// </summary> /// <param name="triangularMatrixType">The type of the triangular matrix.</param> /// <returns>The <see cref="System.Char"/> representation of <paramref name="triangularMatrixType"/>.</returns> private static char GetUplo(BLAS.TriangularMatrixType triangularMatrixType) { switch (triangularMatrixType) { case BLAS.TriangularMatrixType.LowerTriangularMatrix: return('L'); case BLAS.TriangularMatrixType.UpperTriangularMatrix: return('U'); default: throw new NotImplementedException(); } }
/// <summary>Performs a rank-1 update of a symmetric matrix, i.e. A := \alpha * x * x^t + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incX" /> | elements.</param> /// <param name="a">The symmetric matrix A of dimension (<paramref name="lda" />, <paramref name="n" />) supplied column-by-column (input/output).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void dsyr(int n, double alpha, double[] x, double[] a, int lda, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } else if (incX != 1) { kx = 1; } if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { double temp = alpha * x[jx - 1]; int ix = kx; for (int i = 1; i <= j; i++) { a[i - 1 + (j - 1) * lda] += x[ix - 1] * temp; ix += incX; } jx += incX; } } else { int jx = kx; for (int j = 1; j <= n; j++) { double temp = alpha * x[jx - 1]; int ix = jx; for (int i = j; i <= n; i++) { a[i - 1 + (j - 1) * lda] += x[ix - 1] * temp; ix += incX; } jx += incX; } } }
/// <summary>Gets a optimal workspace array length for the <c>dsytrf</c> function. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> /// <returns>The optimal workspace array length.</returns> /// <remarks>The parameter <paramref name="triangularMatrixType"/> should not have an impact of the calculation of the optimal length of the workspace array.</remarks> public int dsytrfQuery(int n, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { var lwork = -1; var uplo = LAPACK.GetUplo(triangularMatrixType); unsafe { double *work = stackalloc double[1]; int info; _dsytrf(ref uplo, ref n, null, ref n, null, work, ref lwork, out info); CheckForError(info, "dsytrf"); return(((int)work[0]) + 1); } }
/// <summary>Gets a optimal workspace array length for the <c>zhetrf</c> function. /// </summary> /// <param name="n">The order of the matrix.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> /// <returns>The optimal workspace array length.</returns> /// <remarks>The parameter <paramref name="triangularMatrixType"/> should not have an impact of the calculation of the optimal length of the workspace array.</remarks> public int zhetrfQuery(int n, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { var lwork = -1; var uplo = LAPACK.GetUplo(triangularMatrixType); unsafe { Complex *work = stackalloc Complex[1]; int info; _zhetrf(ref uplo, ref n, null, ref n, null, work, ref lwork, out info); CheckForError(info, "zhetrf"); return(((int)work[0].Real) + 1); } }
/// <summary>Performs a rank-1 update of a symmetric packed matrix, i.e. A := \alpha * x * x^t + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incX" /> | elements.</param> /// <param name="aPacked">The symmetric packed matrix A with dimension at least (<paramref name="n" /> * (<paramref name="n" /> + 1) ) / 2.</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void dspr(int n, double alpha, double[] x, double[] aPacked, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; int kk = 1; if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { double temp = alpha * x[jx - 1]; int ix = kx; for (int k = kk; k <= kk + j - 1; k++) { aPacked[k - 1] += x[ix - 1] * temp; ix += incX; } jx += incX; kk += j; } } else { int jx = kx; for (int j = 1; j <= n; j++) { double temp = alpha * x[jx - 1]; int ix = jx; for (int k = kk; k <= kk + n - j; k++) { aPacked[k - 1] += x[ix - 1] * temp; ix += incX; } jx += incX; kk = kk + n - j + 1; } } }
/// <summary>Performs a rank-2 update of a Hermitian packed matrix, i.e. A := \alpha * x * conjg(y^t) + conjg(\alpha) * y * conjg(x^t) + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" />-1) * |<paramref name="incX" />| elements.</param> /// <param name="y">The vector y with at least 1 + (<paramref name="n" />-1) * |<paramref name="incY" />| elements.</param> /// <param name="aPacked">The Hermitian packed matrix A with dimension at least (<paramref name="n" /> * (<paramref name="n" /> + 1) ) / 2.</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> /// <param name="incY">The increment for the elements of <paramref name="y" />.</param> public void zhpr2(int n, Complex alpha, Complex[] x, Complex[] y, Complex[] aPacked, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1, int incY = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; int ky = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } if (incY <= 0) { ky = 1 - (n - 1) * incY; } int jx = kx; int jy = ky; int kk = 1; if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 1; j <= n; j++) { Complex temp1 = alpha * Complex.Conjugate(y[jy - 1]); Complex temp2 = Complex.Conjugate(alpha * x[jx - 1]); int ix = kx; int iy = ky; for (int k = kk; k <= kk + j - 2; k++) { aPacked[k - 1] = aPacked[k - 1] + x[ix - 1] * temp1 + y[iy - 1] * temp2; ix += incX; iy += incY; } aPacked[kk + j - 2] = (aPacked[kk + j - 2] + x[jx - 1] * temp1 + y[jy - 1] * temp2).Real; jx += incX; jy += incY; kk += j; } } else { for (int j = 1; j <= n; j++) { Complex temp1 = alpha * Complex.Conjugate(y[jy - 1]); Complex temp2 = Complex.Conjugate(alpha * x[jx - 1]); aPacked[kk - 1] = (aPacked[kk - 1] + x[jx - 1] * temp1 + y[jy - 1] * temp2).Real; int ix = jx; int iy = jy; for (int k = kk + 1; k <= kk + n - j; k++) { ix += incX; iy += incY; aPacked[k - 1] = aPacked[k - 1] + x[ix - 1] * temp1 + y[iy - 1] * temp2; } jx += incX; jy += incY; kk = kk + n - j + 1; } } }
/// <summary>Performs a rank-2 update of a Hermitian matrix, i.e. A := \alpha * x * conjg(y^t) + conjg(\alpha) * y * conjg(x^t) + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" />-1) * |<paramref name="incX" />| elements.</param> /// <param name="y">The vector y with at least 1 + (<paramref name="n" />-1) * |<paramref name="incY" />| elements.</param> /// <param name="a">The Hermitian matrix A with dimension (<paramref name="lda" />, <paramref name="n" />).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> /// <param name="incY">The increment for the elements of <paramref name="y" />.</param> public void zher2(int n, Complex alpha, Complex[] x, Complex[] y, Complex[] a, int lda, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1, int incY = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; int ky = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } if (incY <= 0) { ky = 1 - (n - 1) * incY; } int jx = kx; int jy = ky; if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 1; j <= n; j++) { Complex temp1 = alpha * Complex.Conjugate(y[jy - 1]); Complex temp2 = Complex.Conjugate(alpha * x[jx - 1]); int ix = kx; int iy = ky; for (int i = 1; i <= j; i++) { a[i - 1 + (j - 1) * lda] = a[i - 1 + (j - 1) * lda] + x[ix - 1] * temp1 + y[iy - 1] * temp2; ix += incX; iy += incY; } jx += incX; jy += incY; } } else { for (int j = 1; j <= n; j++) { Complex temp1 = alpha * Complex.Conjugate(y[jy - 1]); Complex temp2 = Complex.Conjugate(alpha * x[jx - 1]); a[j - 1 + (j - 1) * lda] = (a[j - 1 + (j - 1) * lda] + x[jx - 1] * temp1 + y[jy - 1] * temp2).Real; int ix = jx; int iy = jy; for (int i = j + 1; i <= n; i++) { ix += incX; iy += incY; a[i - 1 + (j - 1) * lda] = a[i - 1 + (j - 1) * lda] + x[ix - 1] * temp1 + y[iy - 1] * temp2; } jx += incX; jy += incY; } } }
/// <summary>Solves a system of linear equations whose coefficients are in a triangular matrix, i.e. op(A) * x = b, where op(A) = A or op(A) = A^t. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="a">The triangular matrix A with dimension (<paramref name="lda" />, <paramref name="n" />).</param> /// <param name="x">The vector b (input), x (output) with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incX" /> | elements (input/output).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="isUnitTriangular">A value indicating whether the matrix A is unit triangular.</param> /// <param name="transpose">A value indicating whether op(A) = A or op(A) = A^t.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void dtrsv(int n, double[] a, double[] x, int lda, BLAS.TriangularMatrixType triangularMatrixType, bool isUnitTriangular = true, BLAS.MatrixTransposeState transpose = BLAS.MatrixTransposeState.NoTranspose, int incX = 1) { if (n == 0) { return; } int kx = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } else if (incX != 1) { kx = 1; } if (transpose == BLAS.MatrixTransposeState.NoTranspose) // x := Inv( A ) *x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx + (n - 1) * incX; for (int j = n; j >= 1; j--) { if (isUnitTriangular == false) { x[jx - 1] /= a[j - 1 + (j - 1) * lda]; } double temp = x[jx - 1]; int ix = jx; for (int i = j - 1; i >= 1; i--) { ix -= incX; x[ix - 1] -= temp * a[i - 1 + (j - 1) * lda]; } jx -= incX; } } else { int jx = kx; for (int j = 1; j <= n; j++) { if (isUnitTriangular == false) { x[jx - 1] /= a[j - 1 + (j - 1) * lda]; } double temp = x[jx - 1]; int ix = jx; for (int i = j + 1; i <= n; i++) { ix += incX; x[ix - 1] -= temp * a[i - 1 + (j - 1) * lda]; } jx += incX; } } } else // x := Inv( A' ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { double temp = x[jx - 1]; int ix = kx; for (int i = 1; i <= j - 1; i++) { temp -= a[i - 1 + (j - 1) * lda] * x[ix - 1]; ix += incX; } if (isUnitTriangular == false) { temp /= a[j - 1 + (j - 1) * lda]; } x[jx - 1] = temp; jx += incX; } } else { kx += (n - 1) * incX; int jx = kx; for (int j = n; j >= 1; j--) { double temp = x[jx - 1]; int ix = kx; for (int i = n; i >= j + 1; i--) { temp -= a[i - 1 + (j - 1) * lda] * x[ix - 1]; ix -= incX; } if (isUnitTriangular == false) { temp /= a[j - 1 + (j - 1) * lda]; } x[jx - 1] = temp; jx -= incX; } } } }
/// <summary>Creates a n x r matrix B such that B * B^t is a correlation matrix and "near" to the specified symmetric, normalized matrix of dimension n. A rank reduction will apply if r is strict less than n. /// </summary> /// <param name="rawCorrelationMatrix">The symmetric, normalized matrix where to find the 'nearest' correlation matrix.</param> /// <param name="state">The state of the operation in its <see cref="PseudoSqrtMatrixDecomposer.State"/> representation (output).</param> /// <param name="outputEntries">This argument will be used to store the matrix entries of the resulting matrix B, i.e. the return value array points to this array if != <c>null</c>; otherwise a memory allocation will be done.</param> /// <param name="worksspaceContainer">A specific <see cref="PseudoSqrtMatrixDecomposer.WorkspaceContainer"/> object to reduce memory allocation; ignored if <c>null</c>.</param> /// <param name="triangularMatrixType">A value indicating which part of <paramref name="rawCorrelationMatrix"/> to take into account.</param> /// <returns>A <see cref="DenseMatrix"/> object that represents a matrix B such that B * B^t is the "nearest" correlation matrix with respect to <paramref name="rawCorrelationMatrix"/>.</returns> /// <remarks>In general the return object does <b>not</b> represents the pseudo-root of <paramref name="rawCorrelationMatrix"/>, i.e. output of the Cholesky decomposition. /// <para>The parameters <paramref name="outputEntries"/>, <paramref name="worksspaceContainer"/> allows to avoid memory allocation and to re-use arrays if the calculation of correlation matrices will be done often.</para></remarks> public abstract DenseMatrix Create(DenseMatrix rawCorrelationMatrix, out State state, double[] outputEntries = null, WorkspaceContainer worksspaceContainer = null, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix);
public double zlansp(MatrixNormType matrixNormType, int n, Complex[] ap, Complex[] work, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { throw new NotImplementedException(); }
/// <summary>Solves a system of linear equations whose coefficients are in a triangular band matrix, i.e. op(A) * x = b, where op(A) = A, op(A) = A ^t or op(A) = A^h. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="k">The number of super-diagonals of A if the matrix A is provided in its upper triangular representation; the number of sub-diagonals otherwise.</param> /// <param name="a">The triangular band matrix with dimension (<paramref name="lda" />, <paramref name="n" />).</param> /// <param name="x">The vector b (input), x (output) with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incX" /> | elements (input/output).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least (1 + <paramref name="k" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="isUnitTriangular">A value indicating whether the matrix A is unit triangular.</param> /// <param name="transpose">A value indicating whether 'op(A)=A', 'op(A)=A^t' or 'op(A)=A^h'.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void ztbsv(int n, int k, Complex[] a, Complex[] x, int lda, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, bool isUnitTriangular = true, BLAS.MatrixTransposeState transpose = BLAS.MatrixTransposeState.NoTranspose, int incX = 1) { if (n == 0) { return; } int kx = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } else if (incX != 1) { kx = 1; } if (transpose == BLAS.MatrixTransposeState.NoTranspose) // x := Inv( A ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { kx += (n - 1) * incX; int jx = kx; for (int j = n; j >= 1; j--) { kx -= incX; int ix = kx; int ell = k + 1 - j; if (isUnitTriangular == false) { x[jx - 1] /= a[k + (j - 1) * lda]; } Complex temp = x[jx - 1]; for (int i = j - 1; i >= Math.Max(1, j - k); i--) { x[ix - 1] -= temp * a[ell + i - 1 + (j - 1) * lda]; ix -= incX; } jx -= incX; } } else { int jx = kx; for (int j = 1; j <= n; j++) { kx += incX; int ix = kx; int ell = 1 - j; if (isUnitTriangular == false) { x[jx - 1] /= a[(j - 1) * lda]; } Complex temp = x[jx - 1]; for (int i = j + 1; i <= Math.Min(n, j + k); i++) { x[ix - 1] -= temp * a[ell + i - 1 + (j - 1) * lda]; ix += incX; } jx += incX; } } } else if (transpose == BLAS.MatrixTransposeState.Transpose) // x := Inv( A' ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = x[jx - 1]; int ix = kx; int ell = k + 1 - j; for (int i = Math.Max(1, j - k); i <= j - 1; i++) { temp -= a[ell + i - 1 + (j - 1) * lda] * x[ix - 1]; ix += incX; } if (isUnitTriangular == false) { temp /= a[k + (j - 1) * lda]; } x[jx - 1] = temp; jx += incX; if (j > k) { kx += incX; } } } else { kx += (n - 1) * incX; int jx = kx; for (int j = n; j >= 1; j--) { Complex temp = x[jx - 1]; int ix = kx; int ell = 1 - j; for (int i = Math.Min(n, j + k); i >= j + 1; i--) { temp -= a[ell + i - 1 + (j - 1) * lda] * x[ix - 1]; ix -= incX; } if (isUnitTriangular == false) { temp /= a[(j - 1) * lda]; } x[jx - 1] = temp; jx -= incX; if (n - j >= k) { kx -= incX; } } } } else // x := Inv( conj(A)' ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = x[jx - 1]; int ix = kx; int ell = k + 1 - j; for (int i = Math.Max(1, j - k); i <= j - 1; i++) { temp -= Complex.Conjugate(a[ell + i - 1 + (j - 1) * lda]) * x[ix - 1]; ix += incX; } if (isUnitTriangular == false) { temp /= Complex.Conjugate(a[k + (j - 1) * lda]); } x[jx - 1] = temp; jx += incX; if (j > k) { kx += incX; } } } else { kx += (n - 1) * incX; int jx = kx; for (int j = n; j >= 1; j--) { Complex temp = x[jx - 1]; int ix = kx; int ell = 1 - j; for (int i = Math.Min(n, j + k); i >= j + 1; i--) { temp -= Complex.Conjugate(a[ell + i - 1 + (j - 1) * lda]) * x[ix - 1]; ix -= incX; } if (isUnitTriangular == false) { temp /= Complex.Conjugate(a[(j - 1) * lda]); } x[jx - 1] = temp; jx -= incX; if (n - j >= k) { kx -= incX; } } } } }
/// <summary>Solves a system of linear equations whose coefficients are in a triangular packed matrix, i.e. op(A) * x = b, where op(A) = A, op(A) = A ^t or op(A) = A^h. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="aPacked">The triangular packed matrix A with dimension at least (<paramref name="n" /> * (<paramref name="n" /> + 1) ) / 2.</param> /// <param name="x">The vector b (input), x (output) with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incX" /> | elements (input/output).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="isUnitTriangular">A value indicating whether the matrix A is unit triangular.</param> /// <param name="transpose">A value indicating whether 'op(A)=A', 'op(A)=A^t' or 'op(A)=A^h'.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> public void ztpsv(int n, Complex[] aPacked, Complex[] x, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, bool isUnitTriangular = true, BLAS.MatrixTransposeState transpose = BLAS.MatrixTransposeState.NoTranspose, int incX = 1) { if (n == 0) { return; } int kx = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } else if (incX != 1) { kx = 1; } if (transpose == BLAS.MatrixTransposeState.NoTranspose) // x := Inv( A ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int kk = n * (n + 1) / 2; int jx = kx + (n - 1) * incX; for (int j = n; j >= 1; j--) { if (isUnitTriangular == false) { x[jx - 1] /= aPacked[kk - 1]; } Complex temp = x[jx - 1]; int ix = jx; for (int k = kk - 1; k >= kk - j + 1; k--) { ix -= incX; x[ix - 1] -= temp * aPacked[k - 1]; } jx -= incX; kk -= j; } } else { int kk = 1; int jx = kx; for (int j = 1; j <= n; j++) { if (isUnitTriangular == false) { x[jx - 1] /= aPacked[kk - 1]; } Complex temp = x[jx - 1]; int ix = jx; for (int k = kk + 1; k <= kk + n - j; k++) { ix += incX; x[ix - 1] -= temp * aPacked[k - 1]; } jx += incX; kk += n - j + 1; } } } else if (transpose == BLAS.MatrixTransposeState.Transpose) // x := Inv( A' ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int kk = 1; int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = x[jx - 1]; int ix = kx; for (int k = kk; k <= kk + j - 2; k++) { temp -= aPacked[k - 1] * x[ix - 1]; ix += incX; } if (isUnitTriangular == false) { temp /= aPacked[kk + j - 2]; } x[jx - 1] = temp; jx += incX; kk += j; } } else { int kk = n * (n + 1) / 2; kx += (n - 1) * incX; int jx = kx; for (int j = n; j >= 1; j--) { Complex temp = x[jx - 1]; int ix = kx; for (int k = kk; k >= kk - (n - (j + 1)); k--) { temp -= aPacked[k - 1] * x[ix - 1]; ix -= incX; } if (isUnitTriangular == false) { temp /= aPacked[kk - n + j - 1]; } x[jx - 1] = temp; jx -= incX; kk -= n - j + 1; } } } else // x := Inv( Conj(A)' ) * x { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int kk = 1; int jx = kx; for (int j = 1; j <= n; j++) { Complex temp = x[jx - 1]; int ix = kx; for (int k = kk; k <= kk + j - 2; k++) { temp -= Complex.Conjugate(aPacked[k - 1]) * x[ix - 1]; ix += incX; } if (isUnitTriangular == false) { temp /= Complex.Conjugate(aPacked[kk + j - 2]); } x[jx - 1] = temp; jx += incX; kk += j; } } else { int kk = n * (n + 1) / 2; kx += (n - 1) * incX; int jx = kx; for (int j = n; j >= 1; j--) { Complex temp = x[jx - 1]; int ix = kx; for (int k = kk; k >= kk - (n - (j + 1)); k--) { temp -= Complex.Conjugate(aPacked[k - 1]) * x[ix - 1]; ix -= incX; } if (isUnitTriangular == false) { temp /= Complex.Conjugate(aPacked[kk - n + j - 1]); } x[jx - 1] = temp; jx -= incX; kk -= n - j + 1; } } } }
/// <summary>Performs a symmetric rank-2k update, i.e. C := alpha*A*B^t + alpha*B*A^t + beta*C or C := alpha*A^t*B + alpha*B^t*A + beta*C with a symmetric matrix C. /// </summary> /// <param name="n">The order of matrix C.</param> /// <param name="k">The The number of columns of matrices A and B or the number .</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="a">The matrix A supplied column-by-column of dimension (<paramref name="lda" />, ka), where ka is <paramref name="k" /> if to calculate C := alpha*A*B^t + alpha*B*A^t + beta*C; otherwise <paramref name="n" />.</param> /// <param name="b">The matrix B supplied column-by-column of dimension (<paramref name="ldb" />, kb), where ka is at least max(1,<paramref name="n" />) if to calculate C := alpha*A*B^t + alpha*B*A^t + beta*C; otherwise at least max(1,<paramref name="k" />).</param> /// <param name="beta">The scalar \beta.</param> /// <param name="c">The symmetric matrix C supplied column-by-column of dimension (<paramref name="ldc" />, <paramref name="n" />).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1,<paramref name="n" />) if to calculate C:= alpha*A*B^t+alpha*B*A^t+beta*C; max(1,<paramref name="k" />) otherwise.</param> /// <param name="ldb">The leading dimension of <paramref name="b" />, must be at least max(1,<paramref name="n" />) if to calculate C:= alpha*A*B^t+alpha*B*A^t+beta*C; max(1,<paramref name="k" />) otherwise.</param> /// <param name="ldc">The leading dimension of <paramref name="c" />, must be at least max(1,<paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix C is in its upper or lower triangular representation.</param> /// <param name="operation">A value indicating whether to calculate C := alpha*A*B^t + alpha*B*A^t + beta*C or C := alpha*A^t*B + alpha*B^t*A + beta*C.</param> public void zsyr2k(int n, int k, Complex alpha, Complex[] a, Complex[] b, Complex beta, Complex[] c, int lda, int ldb, int ldc, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, BLAS.Xsyr2kOperation operation = BLAS.Xsyr2kOperation.ATimesBTransPlusBTimesATrans) { if (operation == BLAS.Xsyr2kOperation.ATimesBTransPlusBTimesATrans) // C := \alpha * A*B' + \alpha * B *A' +C { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int i = 0; i <= j; i++) { c[i + j * ldc] *= beta; } for (int ell = 0; ell < k; ell++) { Complex temp = alpha * b[j + ell * ldb]; Complex temp2 = alpha * a[j + ell * lda]; for (int i = 0; i <= j; i++) { c[i + j * ldc] += b[i + ell * ldb] * temp2 + a[i + ell * lda] * temp; } } } } else { for (int j = 0; j < n; j++) { for (int i = j; i < n; i++) { c[i + j * ldc] *= beta; } for (int ell = 0; ell < k; ell++) { Complex temp = alpha * b[j + ell * ldb]; Complex temp2 = alpha * a[j + ell * lda]; for (int i = j; i < n; i++) { c[i + j * ldc] += a[i + ell * lda] * temp + b[i + ell * ldb] * temp2; } } } } } else // C := \alpha * A' * B + \alpha * B' * A + C. { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int i = 0; i <= j; i++) { Complex temp = 0.0; Complex temp2 = 0.0; for (int ell = 0; ell < k; ell++) { temp += a[ell + i * lda] * b[ell + j * ldb]; temp2 += b[ell + i * ldb] * a[ell + j * lda]; } c[i + j * ldc] = alpha * temp2 + alpha * temp + beta * c[i + j * ldc]; } } } else { for (int j = 0; j < n; j++) { for (int i = j; i < n; i++) { Complex temp = 0.0; Complex temp2 = 0.0; for (int ell = 0; ell < k; ell++) { temp += a[ell + i * lda] * b[ell + j * ldb]; temp2 += b[ell + i * ldb] * a[ell + j * lda]; } c[i + j * ldc] = alpha * temp2 + alpha * temp + beta * c[i + j * ldc]; } } } } }
/// <summary>Computes a matrix-vector product using a Hermitian matrix, i.e. y := \alpha * A * x + \beta * y. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" />-1) * |<paramref name="incX" />| elements.</param> /// <param name="beta">The scalar \beta.</param> /// <param name="y">The vector y with at least 1 + (<paramref name="n" />-1) * |<paramref name="incY" />| elements (input/output).</param> /// <param name="a">The Hermitian matrix A with dimension (<paramref name="lda" />, <paramref name="n" />).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> /// <param name="incY">The increment for the elements of <paramref name="y" />.</param> public void zhemv(int n, Complex alpha, Complex[] x, Complex beta, Complex[] y, Complex[] a, int lda, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1, int incY = 1) { if (n == 0 || alpha == 0.0 && beta == 1.0) { return; } int kx = 1; int ky = 1; if (incX <= 0) { kx = 1 - (n - 1) * incX; } if (incY <= 0) { ky = 1 - (n - 1) * incY; } /* calculate y := \beta * y:*/ int iy = ky; for (int i = 1; i <= n; i++) { y[iy - 1] = beta * y[iy - 1]; iy += incY; } if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { int jx = kx; int jy = ky; for (int j = 1; j <= n; j++) { Complex temp1 = alpha * x[jx - 1]; Complex temp2 = 0.0; int ix = kx; iy = ky; for (int i = 1; i <= j - 1; i++) { y[iy - 1] += temp1 * a[i - 1 + (j - 1) * lda]; temp2 += Complex.Conjugate(a[i - 1 + (j - 1) * lda]) * x[ix - 1]; ix += incX; iy += incY; } y[jy - 1] = y[jy - 1] + temp1 * a[j - 1 + (j - 1) * lda] + alpha * temp2; jx += incX; jy += incY; } } else { int jx = kx; int jy = ky; for (int j = 1; j <= n; j++) { Complex temp1 = alpha * x[jx - 1]; Complex temp2 = 0.0; y[jy - 1] += temp1 * a[j - 1 + (j - 1) * lda]; int ix = jx; iy = jy; for (int i = j + 1; i <= n; i++) { ix += incX; iy += incY; y[iy - 1] += temp1 * a[i - 1 + (j - 1) * lda]; temp2 += Complex.Conjugate(a[i - 1 + (j - 1) * lda]) * x[ix - 1]; } y[jy - 1] += alpha * temp2; jx += incX; jy += incY; } } }
/// <summary>Creates a 'n x r' matrix B such that B * B' is a correlation matrix and 'near' to the specified symmetric, normalized matrix of dimension n. A rank reduction will apply if r is strict less than n. /// </summary> /// <param name="rawCorrelationMatrix">The symmetric, normalized matrix where to find the 'nearest' correlation matrix.</param> /// <param name="state">The state of the operation in its <see cref="PseudoSqrtMatrixDecomposer.State"/> representation (output).</param> /// <param name="triangularMatrixType">A value indicating which part of <paramref name="rawCorrelationMatrix"/> to take into account.</param> /// <param name="outputEntries">This argument will be used to store the matrix entries of the resulting matrix B, i.e. the return value array points to this array if != <c>null</c>; otherwise a memory allocation will be done.</param> /// <param name="worksspaceContainer">A specific <see cref="PseudoSqrtMatrixDecomposer.WorkspaceContainer"/> object to reduce memory allocation; ignored if <c>null</c>.</param> /// <returns>A <see cref="DenseMatrix"/> object that represents a matrix B such that B * B' is the 'nearest' correlation matrix with respect to <paramref name="rawCorrelationMatrix"/>.</returns> /// <remarks>In general the return object does <b>not</b> represents the pseudo-root of <paramref name="rawCorrelationMatrix"/>, i.e. output of the Cholesky decomposition. /// <para>The parameters <paramref name="outputEntries"/>, <paramref name="worksspaceContainer"/> allows to avoid memory allocation and to re-use arrays if the calculation of correlation matrices will be done often.</para></remarks> public override DenseMatrix Create(DenseMatrix rawCorrelationMatrix, out State state, double[] outputEntries = null, PseudoSqrtMatrixDecomposer.WorkspaceContainer worksspaceContainer = null, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { if (rawCorrelationMatrix.IsQuadratic == false) { throw new ArgumentException("rawCorrelationMatrix"); } int n = rawCorrelationMatrix.RowCount; if ((outputEntries == null) || (outputEntries.Length < n * n)) { outputEntries = new double[n * n]; } var ws = worksspaceContainer as Workspace; if ((ws == null) || (ws.Dimension < n)) { ws = new Workspace(n); } int m; BLAS.Level1.dcopy(n * n, rawCorrelationMatrix.Data, ws.data); LAPACK.EigenValues.Symmetric.driver_dsyevr(LapackEigenvalues.SymmetricGeneralJob.All, n, ws.data, out m, ws.eigenValues, outputEntries, ws.isuppz, ws.work, ws.iwork); var originalEigenValueDataTable = InfoOutputDetailLevel.IsAtLeastAsComprehensiveAs(InfoOutputDetailLevel.High) ? CreateDataTableWithEigenvalues("Eigenvalues.Original", m, ws.eigenValues) : null; int rank = n; int minNumberOfEigenvaluesToSetZero = n - Math.Min(MaximalRank ?? n, n); int i = 0; while ((i < minNumberOfEigenvaluesToSetZero) || (ws.eigenValues[i] < 0.0)) { ws.eigenValues[i] = 0.0; i++; rank--; } var adjustedEigenValueDataTable = InfoOutputDetailLevel.IsAtLeastAsComprehensiveAs(InfoOutputDetailLevel.High) ? CreateDataTableWithEigenvalues("Eigenvalues.Adjusted", m, ws.eigenValues) : null; VectorUnit.Basics.Sqrt(n, ws.eigenValues); // calculate sqrt of eigenvalues only once, i.e. the array 'eigenValues' contains the sqrt of the eigenvalues! for (i = 0; i < n; i++) { var t_i = 0.0; for (int j = n - 1; j >= n - rank; j--) { t_i += outputEntries[i + j * n] * outputEntries[i + j * n] * ws.eigenValues[j] * ws.eigenValues[j]; outputEntries[i + j * n] *= ws.eigenValues[j]; } BLAS.Level1.dscal(rank, 1.0 / Math.Sqrt(t_i), outputEntries, -n, i + (n - 1) * n); // [i+j*n] *= 1/Math.Sqrt(tempValue) for j = n-1, ..., n-rank } /* The eigenvalues are in ascending order. Thefore the first (and not last) 'rank' columns of the eigenvectors are not required. Therefore we swap the relevant part */ BLAS.Level1.dscal(n * (n - rank), 0.0, outputEntries); BLAS.Level1.dswap(n * rank, outputEntries, 1, outputEntries, 1, n * (n - rank), 0); state = State.Create(rank, detailProperties: new[] { InfoOutputProperty.Create("Eigenvalues set to 0.0", n - rank) }, detailDataTables: new[] { originalEigenValueDataTable, adjustedEigenValueDataTable }, iterationsNeeded: 1, infoOutputDetailLevel: InfoOutputDetailLevel); return(new DenseMatrix(n, rank, outputEntries)); }
/// <summary>Computes a matrix-matrix product where one input matrix is triangular, i.e. B := \alpha * op(A)*B or B:= \alpha *B * op(A), where A is a unit or non-unit upper or lower triangular matrix. /// </summary> /// <param name="m">The number of rows of matrix B.</param> /// <param name="n">The number of columns of matrix B.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="a">The triangular matrix A supplied column-by-column of dimension (<paramref name="lda"/>, k), where k is <paramref name="m"/> if to calculate B := \alpha * op(A)*B; <paramref name="n"/> otherwise.</param> /// <param name="b">The matrix B supplied column-by-column of dimension (<paramref name="ldb"/>, <paramref name="n"/>).</param> /// <param name="lda">The leading dimension of <paramref name="a"/>, must be at least max(1,<paramref name="m"/>) if to calculate B := \alpha * op(A)*B; max(1,<paramref name="n"/>) otherwise.</param> /// <param name="ldb">The leading dimension of <paramref name="b"/>, must be at least max(1,<paramref name="m"/>).</param> /// <param name="isUnitTriangular">A value indicating whether the matrix A is unit triangular.</param> /// <param name="side">A value indicating whether to calculate B := \alpha * op(A)*B or B:= \alpha *B * op(A).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="transpose">A value indicating whether 'op(A)=A' or 'op(A)=A^t'.</param> public void dtrmm(int m, int n, double alpha, double[] a, double[] b, int lda, int ldb, bool isUnitTriangular = true, BLAS.Side side = BLAS.Side.Left, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, BLAS.MatrixTransposeState transpose = BLAS.MatrixTransposeState.NoTranspose) { if (n == 0) { return; // nothing to do } if (side == BLAS.Side.Left) { if (transpose == BLAS.MatrixTransposeState.NoTranspose) // B = \alpha *A*B { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int k = 0; k < m; k++) { double temp = alpha * b[k + j * ldb]; for (int i = 0; i <= k - 1; i++) { b[i + j * ldb] += temp * a[i + k * lda]; } if (isUnitTriangular == false) { temp *= a[k + k * lda]; } b[k + j * ldb] = temp; } } } else // lower triangular matrix { for (int j = 0; j < n; j++) { for (int k = m - 1; k >= 0; k--) { double temp = alpha * b[k + j * ldb]; b[k + j * ldb] = temp; if (isUnitTriangular == false) { b[k + j * ldb] *= a[k + k * lda]; } for (int i = k + 1; i < m; i++) { b[i + j * ldb] += temp * a[i + k * lda]; } } } } } else // B = \alpha * A' *B { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int i = m - 1; i >= 0; i--) { double temp = b[i + j * ldb]; if (isUnitTriangular == false) { temp *= a[i + i * lda]; } for (int k = 0; k <= i - 1; k++) { temp += a[k + i * lda] * b[k + j * ldb]; } b[i + j * ldb] = alpha * temp; } } } else // lower triangular matrix { for (int j = 0; j < n; j++) { for (int i = 0; i < m; i++) { double temp = b[i + j * ldb]; if (isUnitTriangular == false) { temp *= a[i + i * lda]; } for (int k = i + 1; k < m; k++) { temp += a[k + i * lda] * b[k + j * ldb]; } b[i + j * ldb] = alpha * temp; } } } } } else // side == BLAS.Side.Right { if (transpose == BLAS.MatrixTransposeState.NoTranspose) // B = \alpha * B * A { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = n - 1; j >= 0; j--) { double temp = alpha; if (isUnitTriangular == false) { temp *= a[j + j * lda]; } for (int i = 0; i < m; i++) { b[i + j * ldb] = temp * b[i + j * ldb]; } for (int k = 0; k <= j - 1; k++) { temp = alpha * a[k + j * lda]; for (int i = 0; i < m; i++) { b[i + j * ldb] += temp * b[i + k * ldb]; } } } } else { for (int j = 0; j < n; j++) { double temp = alpha; if (isUnitTriangular == false) { temp *= a[j + j * lda]; } for (int i = 0; i < m; i++) { b[i + j * ldb] = temp * b[i + j * ldb]; } for (int k = j + 1; k < n; k++) { temp = alpha * a[k + j * lda]; for (int i = 0; i < m; i++) { b[i + j * ldb] += temp * b[i + k * ldb]; } } } } } else // B = \alpha * B * A' { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int k = 0; k < n; k++) { double temp; for (int j = 0; j < k; j++) { temp = alpha * a[j + k * lda]; for (int i = 0; i < m; i++) { b[i + j * ldb] += temp * b[i + k * ldb]; } } temp = alpha; if (isUnitTriangular == false) { temp *= a[k + k * lda]; } for (int i = 0; i < m; i++) { b[i + k * ldb] = temp * b[i + k * ldb]; } } } else // lower triangular matrix { for (int k = n - 1; k >= 0; k--) { double temp; for (int j = k + 1; j < n; j++) { temp = alpha * a[j + k * lda]; for (int i = 0; i < m; i++) { b[i + j * ldb] += temp * b[i + k * ldb]; } } temp = alpha; if (isUnitTriangular == false) { temp *= a[k + k * lda]; } for (int i = 0; i < m; i++) { b[i + k * ldb] = temp * b[i + k * ldb]; } } } } } }
/// <summary>Computes the Cholesky decomposition with complete pivoting of a complex Hermitian positive-definite matrix, i.e. P' * A * P = U' * U or P' * A * P = L * L', where L is a lower triangular matrix and U is upper triangular. /// </summary> /// <param name="matrixFactorization">The <see cref="LapackLinearEquations.IMatrixFactorization"/> object.</param> /// <param name="n">The order of the matrix.</param> /// <param name="a">The matrix A supplied column-by-column of dimension (<paramref name="n"/>; <paramref name="n"/>); overwritten by the upper or lower triangular matrix U, L respectively.</param> /// <param name="pivot">The nonzero entries of permutation matrix P, i.e. P( pivot(k) , k ) = 1 for k = 1,.., <paramref name="n"/> - 1 (output).</param> /// <param name="work">A workspace array of length at least 2 * <paramref name="n"/>.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of matrix A is stored and how matrix A is factored.</param> /// <param name="tolerance">The tolerance for the termination condition of the algorithm, i.e. if pivot elements < <paramref name="tolerance"/>.</param> /// <returns>The rank of <paramref name="a"/> given by the number of steps the algorithm completed.</returns> public static int zpstrf(this LapackLinearEquations.IMatrixFactorization matrixFactorization, int n, Complex[] a, int[] pivot, Complex[] work, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix, double tolerance = MachineConsts.Epsilon) { int info; int lda = Math.Max(1, n); var uplo = GetUplo(triangularMatrixType); int rank; _zpstrf(ref uplo, ref n, a, ref lda, pivot, out rank, ref tolerance, work, out info); CheckForError(info, "zpstrf"); return(rank); }
/// <summary>Computes a matrix-matrix product where one input matrix is symmetric, i.e. C := \alpha*A*B + \beta*C or C := \alpha*B*A +\beta*C. /// </summary> /// <param name="m">The number of rows of the matrix C.</param> /// <param name="n">The number of columns of the matrix C.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="a">The symmetric matrix A supplied column-by-column of dimension (<paramref name="lda" />, ka), where ka is <paramref name="m" /> if to calculate C := \alpha * A*B + \beta*C; otherwise <paramref name="n" />.</param> /// <param name="b">The matrix B supplied column-by-column of dimension (<paramref name="ldb" />,<paramref name="n" />).</param> /// <param name="beta">The scalar \beta.</param> /// <param name="c">The matrix C supplied column-by-column of dimension (<paramref name="ldc" />,<paramref name="n" />); input/output.</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1,<paramref name="m" />) if <paramref name="side" />=left; max(1,n) otherwise.</param> /// <param name="ldb">The leading dimension of <paramref name="b" />, must be at least max(1,<paramref name="m" />).</param> /// <param name="ldc">The leading dimension of <paramref name="c" />, must be at least max(1,<paramref name="m" />).</param> /// <param name="side">A value indicating whether to calculate C := \alpha * A*B + \beta*C or C := \alpha * B*A +\beta*C.</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> public void zsymm(int m, int n, Complex alpha, Complex[] a, Complex[] b, Complex beta, Complex[] c, int lda, int ldb, int ldc, BLAS.Side side = BLAS.Side.Left, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix) { if (side == BLAS.Side.Left) // C := \alpha *A*B + \beta * C { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int i = 0; i < m; i++) { Complex temp = alpha * b[i + j * ldb]; Complex temp2 = 0.0; for (int k = 0; k <= i - 1; k++) { c[k + j * ldc] += temp * a[k + i * lda]; temp2 += b[k + j * ldb] * a[k + i * lda]; } c[i + j * ldc] = alpha * temp2 + temp * a[i + i * lda] + beta * c[i + j * ldc]; } } } else { for (int j = 0; j < n; j++) { for (int i = m - 1; i >= 0; i--) { Complex temp = alpha * b[i + j * ldb]; Complex temp2 = 0.0; for (int k = i + 1; k < m; k++) { c[k + j * ldc] += temp * a[k + i * lda]; temp2 += b[k + j * ldb] * a[k + i * lda]; } c[i + j * ldc] = alpha * temp2 + temp * a[i + i * lda] + beta * c[i + j * ldc]; } } } } else // C := \alpha * B * A + \beta * C { for (int j = 0; j < n; j++) { Complex temp = alpha * a[j + j * lda]; for (int i = 0; i < m; i++) { c[i + j * ldc] = temp * b[i + j * ldb] + beta * c[i + j * ldc]; } for (int k = 0; k <= j - 1; k++) { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { temp = alpha * a[k + j * lda]; } else { temp = alpha * a[j + k * lda]; } for (int i = 0; i < m; i++) { c[i + j * ldc] = c[i + j * ldc] + temp * b[i + k * ldb]; } } for (int k = j + 1; k < n; k++) { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { temp = alpha * a[j + k * lda]; } else { temp = alpha * a[k + j * lda]; } for (int i = 0; i < m; i++) { c[i + j * ldc] = c[i + j * ldc] + temp * b[i + k * ldb]; } } } } }
/// <summary>Performs a Hermitian rank-2 update, i.e. C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C or C := \alpha*B^h*A + conjg(\alpha)*A^h*B + beta*C, where C is an Hermitian matrix. /// </summary> /// <param name="n">The order of matrix C.</param> /// <param name="k">The number of columns of matrix A if to calculate C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C; the number of rows of the matrix A otherwise.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="a">The matrix A supplied column-by-column of dimension (<paramref name="lda" />, ka), where ka equals to <paramref name="k" /> if to calculate C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C; <paramref name="n" /> otherwise.</param> /// <param name="b">The matrix B supplied column-by-column of dimension (<paramref name="ldb" />, kb), where kb equals to <paramref name="k" /> if to calculate C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C; <paramref name="n" /> otherwise.</param> /// <param name="beta">The scalar \beta.</param> /// <param name="c">The Hermitian matrix C supplied column-by-column of dimension (<paramref name="ldc" />, <paramref name="n" />).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1,<paramref name="n" />) if to calculate C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C; max(1, <paramref name="k" />) otherwise.</param> /// <param name="ldb">The leading dimension of <paramref name="b" />, must be at least max(1,<paramref name="n" />) if to calculate C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C; max(1, <paramref name="k" />) otherwise.</param> /// <param name="ldc">The leading dimension of <paramref name="c" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix C is in its upper or lower triangular representation.</param> /// <param name="operation">A value indicating whether to calculate C := \alpha*A*B^h + conjg(\alpha)*B*A^h + \beta * C or C := \alpha*B^h*A + conjg(\alpha)*A^h*B + beta*C.</param> public void zher2k(int n, int k, Complex alpha, Complex[] a, Complex[] b, double beta, Complex[] c, int lda, int ldb, int ldc, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, BLAS.Zher2kOperation operation = BLAS.Zher2kOperation.ATimesBHermitePlusBTimesAHermite) { if (n == 0 || ((alpha == 0.0 || k == 0) && (beta == 1.0))) { return; // nothing to do } if (operation == BLAS.Zher2kOperation.ATimesBHermitePlusBTimesAHermite) // C := \alpha * A*conjg(B') + conjg(\alpha) *B*conjg(A') + \beta * C { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int i = 0; i <= j - 1; i++) { c[i + j * ldc] *= beta; } c[j + j * ldc] = beta * c[j + j * ldc].Real; for (int ell = 0; ell < k; ell++) { Complex temp = alpha * Complex.Conjugate(b[j + ell * ldb]); Complex temp2 = Complex.Conjugate(alpha * a[j + ell * lda]); for (int i = 0; i <= j - 1; i++) { c[i + j * ldc] += a[i + ell * lda] * temp + b[i + ell * ldb] * temp2; } c[j + j * ldc] += a[j + ell * lda] * temp + b[j + ell * ldb] * temp2; } } } else { for (int j = 0; j < n; j++) { for (int i = j + 1; i < n; i++) { c[i + j * ldc] *= beta; } c[j + j * ldc] = beta * c[j + j * ldc].Real; for (int ell = 0; ell < k; ell++) { Complex temp = alpha * Complex.Conjugate(b[j + ell * ldb]); Complex temp2 = Complex.Conjugate(alpha * a[j + ell * lda]); for (int i = j + 1; i < n; i++) { c[i + j * ldc] += a[i + ell * lda] * temp + b[i + ell * ldb] * temp2; } c[j + j * ldc] += a[j + ell * lda] * temp + b[j + ell * ldb] * temp2; } } } } else // C := \alpha * conjg(A')*B + conjg(\alpha) * conjg(B')*A + C { if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 0; j < n; j++) { for (int i = 0; i <= j; i++) { Complex temp = 0.0; Complex temp2 = 0.0; for (int ell = 0; ell < k; ell++) { temp += Complex.Conjugate(a[ell + i * lda]) * b[ell + j * ldb]; temp2 += Complex.Conjugate(b[ell + i * ldb]) * a[ell + j * lda]; } if (i == j) { c[j + j * ldc] = (beta * c[j + j * ldc] + alpha * temp + Complex.Conjugate(alpha) * temp2).Real; } else { c[i + j * ldc] = beta * c[i + j * ldc] + alpha * temp + Complex.Conjugate(alpha) * temp2; } } } } else { for (int j = 0; j < n; j++) { for (int i = j; i < n; i++) { Complex temp = 0.0; Complex temp2 = 0.0; for (int ell = 0; ell < k; ell++) { temp += Complex.Conjugate(a[ell + i * lda]) * b[ell + j * ldb]; temp2 += Complex.Conjugate(b[ell + i * ldb]) * a[ell + j * lda]; } if (i == j) { c[j + j * ldc] = (beta * c[j + j * ldc] + alpha * temp + Complex.Conjugate(alpha) * temp2).Real; } else { c[i + j * ldc] = beta * c[i + j * ldc] + alpha * temp + Complex.Conjugate(alpha) * temp2; } } } } } }
/// <summary>Returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value of any element of symmetric matrix supplied in packed form. /// </summary> /// <param name="matrixNormType">The type of the matrix norm.</param> /// <param name="n">The order of the matrix.</param> /// <param name="ap">The specified symmetric matrix in packed form, i.e. either upper or lower triangle as specified in <paramref name="triangularMatrixType"/> with at least <paramref name="n"/> * (<paramref name="n"/> + 1) / 2 elements.</param> /// <param name="work">A workspace array which is referenced in the case of 1- or infinity-norm only. In this case the length must be at least <paramref name="n"/>.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of the symmetric input matrix is stored.</param> /// <returns>The value of the specific matrix norm.</returns> public double dlansp(MatrixNormType matrixNormType, int n, double[] ap, double[] work, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { var norm = LAPACK.GetMatrixNormType(matrixNormType); var uplo = LAPACK.GetUplo(triangularMatrixType); return(_dlansp(ref norm, ref uplo, ref n, ap, work)); }
/// <summary>Performs a rank-2 update of a symmetric matrix, i.e. A := \alpha * x * y^t + \alpha * y * x^t + A. /// </summary> /// <param name="n">The order of matrix A.</param> /// <param name="alpha">The scalar \alpha.</param> /// <param name="x">The vector x with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incX" /> | elements.</param> /// <param name="y">The vector y with at least 1 + (<paramref name="n" /> - 1) * | <paramref name="incY" /> | elements.</param> /// <param name="a">The symmetric matrix A of dimension (<paramref name="lda" />, <paramref name="n" />) supplied column-by-column (input/output).</param> /// <param name="lda">The leading dimension of <paramref name="a" />, must be at least max(1, <paramref name="n" />).</param> /// <param name="triangularMatrixType">A value whether matrix A is in its upper or lower triangular representation.</param> /// <param name="incX">The increment for the elements of <paramref name="x" />.</param> /// <param name="incY">The increment for the elements of <paramref name="y" />.</param> public void dsyr2(int n, double alpha, double[] x, double[] y, double[] a, int lda, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.UpperTriangularMatrix, int incX = 1, int incY = 1) { if (n == 0 || alpha == 0.0) { return; } int kx = 1; int ky = 1; int jx = 1; int jy = 1; if (incX != 1 || incY != 1) { if (incX <= 0) { kx = 1 - (n - 1) * incX; } if (incY <= 0) { ky = 1 - (n - 1) * incY; } jx = kx; jy = ky; } if (triangularMatrixType == BLAS.TriangularMatrixType.UpperTriangularMatrix) { for (int j = 1; j <= n; j++) { double temp1 = alpha * y[jy - 1]; double temp2 = alpha * x[jx - 1]; int ix = kx; int iy = ky; for (int i = 1; i <= j; i++) { a[i - 1 + (j - 1) * lda] = a[i - 1 + (j - 1) * lda] + x[ix - 1] * temp1 + y[iy - 1] * temp2; ix += incX; iy += incY; } jx += incX; jy += incY; } } else { for (int j = 1; j <= n; ++j) { double temp1 = alpha * y[jy - 1]; double temp2 = alpha * x[jx - 1]; int ix = jx; int iy = jy; for (int i = j; i <= n; i++) { a[i - 1 + (j - 1) * lda] = a[i - 1 + (j - 1) * lda] + x[ix - 1] * temp1 + y[iy - 1] * temp2; ix += incX; iy += incY; } jx += incX; jy += incY; } } }
/// <summary>Returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value of any element of symmetric matrix supplied in packed form. /// </summary> /// <param name="matrixNormType">The type of the matrix norm.</param> /// <param name="n">The order of the matrix.</param> /// <param name="ap">The specified symmetric matrix in packed form, i.e. either upper or lower triangle as specified in <paramref name="triangularMatrixType"/> with at least <paramref name="n"/> * (<paramref name="n"/> + 1) / 2 elements.</param> /// <param name="work">A workspace array which is referenced in the case of 1- or infinity-norm only. In this case the length must be at least <paramref name="n"/>.</param> /// <param name="triangularMatrixType">A value indicating whether the upper or lower triangular part of the symmetric input matrix is stored.</param> /// <returns>The value of the specific matrix norm.</returns> public double zlansp(MatrixNormType matrixNormType, int n, Complex[] ap, Complex[] work, BLAS.TriangularMatrixType triangularMatrixType = BLAS.TriangularMatrixType.LowerTriangularMatrix) { var norm = LapackNativeWrapper.GetMatrixNormType(matrixNormType); var uplo = LapackNativeWrapper.GetUplo(triangularMatrixType); return(_zlansp(ref norm, ref uplo, ref n, ap, work)); }