/// <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 }