public PositiveDefiniteMatrix SetToInverse(PositiveDefiniteMatrix A) { #if LAPACK this.SetTo(A); Lapack.SymmetricInverseInPlace(this); return(this); #else return(SetToInverse(A, new LowerTriangularMatrix(rows, cols))); #endif }
/// <summary> /// Gets the Cholesky decomposition of the matrix (L*L' = A), replacing its contents. /// </summary> /// <param name="isPosDef">True if <c>this</c> is positive definite, otherwise false.</param> /// <returns>The Cholesky decomposition L. If <c>this</c> is positive semidefinite, /// then L will satisfy L*L' = A. /// Otherwise, L will only approximately satisfy L*L' = A.</returns> /// <remarks> /// <c>this</c> must be symmetric, but need not be positive definite. /// </remarks> public LowerTriangularMatrix CholeskyInPlace(out bool isPosDef) { LowerTriangularMatrix L = new LowerTriangularMatrix(rows, cols, data); #if LAPACK isPosDef = Lapack.CholeskyInPlace(this); #else isPosDef = L.SetToCholesky(this); #endif return(L); }
public bool SetToCholesky(Matrix A) { A.CheckSymmetry("A"); #if LAPACK SetTo(A); bool isPosDef = Lapack.CholeskyInPlace(this); #else CheckCompatible(A, "A"); bool isPosDef = true; LowerTriangularMatrix L = this; // compute the Cholesky factor // Reference: Golub and van Loan (1996) for (int i = 0; i < A.Cols; i++) { // upper triangle for (int j = 0; j < i; j++) { L[j, i] = 0; } // lower triangle for (int j = i; j < A.Rows; j++) { double sum = A[i, j]; int index1 = i * cols; int index2 = j * cols; for (int k = 0; k < i; k++) { //sum -= L[i, k] * L[j, k]; sum -= data[index1++] * data[index2++]; } if (i == j) { // diagonal entry if (sum <= 0) { isPosDef = false; L[i, i] = 0; } else { L[i, i] = System.Math.Sqrt(sum); } } else { // off-diagonal entry if (L[i, i] > 0) { L[j, i] = sum / L[i, i]; } else { L[j, i] = 0; } } } } CheckLowerTriangular(); #endif return(isPosDef); }
/// <summary> /// Modifies <c>this</c> to be the inverse of A. /// </summary> /// <param name="A">Can be the same object as <c>this</c></param> public void SetToInverse(LowerTriangularMatrix A) { #if LAPACK if (object.ReferenceEquals(this, A)) { A = (LowerTriangularMatrix)A.Clone(); } this.SetToIdentity(); Lapack.PredivideBy(this, A); #else // Reference: Golub and van Loan (1996) Assert.IsTrue(A.Rows == A.Cols); Assert.IsTrue(A.Rows == this.Rows); for (int k = 0; k < rows; k++) { if (A[k, k] == 0) { throw new MatrixSingularException(A); } } for (int j = 0; j < cols; j++) { int index1 = j; // k < j case for (int k = 0; k < j; k++) { //B[k, j] = 0.0; data[index1] = 0.0; index1 += cols; } // k == j case int index2 = j + j * cols; double v = 1.0 / A.data[index2]; data[index1] = v; for (int i = j + 1; i < rows; i++) { // B[i, j] = -v * A[i, j]; index1 += cols; index2 += cols; data[index1] = -v * A.data[index2]; } // k > j case for (int k = j + 1; k < rows; k++) { index1 = j + k * cols; index2 = k + k * cols; if (data[index1] != 0) { //double u = B[k,j]/A[k,k]; //B[k, j] = u; // TM: this style of indexing may look ugly but it runs much faster double u = data[index1] / A.data[index2]; data[index1] = u; for (int i = k + 1; i < rows; i++) { // B[i, j] -= u * A[i, k]; index1 += cols; index2 += cols; data[index1] -= u * A.data[index2]; } } } } #endif }