static void SymmInv(MultidimensionalArray M, MultidimensionalArray L, MultidimensionalArray R) { L.Clear(); R.Clear(); L.AccEye(1.0); #if DEBUG var Mbefore = M.CloneAs(); #endif int n = M.NoOfRows; for (int i = 0; i < n; i++) { double M_ii = M[i, i]; if (M_ii == 0.0) { throw new ArithmeticException("Zero diagonal element at " + i + "-th row."); } double scl = 1.0 / Math.Sqrt(Math.Abs(M_ii)); M.RowScale(i, scl); L.RowScale(i, scl); M.ColScale(i, scl); double diagsign = Math.Sign(M[i, i]); if (diagsign == 0.0) { throw new ArithmeticException("Zero diagonal element at " + i + "-th row."); } if (Math.Abs(Math.Abs(M[i, i]) - 1.0) > 1.0e-8) { throw new ArithmeticException("Unable to create diagonal 1.0."); } for (int k = i + 1; k < n; k++) { double M_ki = M[k, i]; M.RowAdd(i, k, -M_ki * diagsign); L.RowAdd(i, k, -M_ki * diagsign); M.ColAdd(i, k, -M_ki * diagsign); Debug.Assert(Math.Abs(M[k, i]) < 1.0e-8); Debug.Assert(Math.Abs(M[i, k]) < 1.0e-8); } } L.TransposeTo(R); #if DEBUG var Test = MultidimensionalArray.Create(M.Lengths); //var Q = MultidimensionalArray.Create(M.Lengths); //Test.AccEye(1.0); Test.Multiply(-1.0, L, Mbefore, R, 1.0, "ij", "ik", "kl", "lj"); for (int i = 0; i < n; i++) { //Debug.Assert((Test[i, i].Abs() - 1.0).Abs() < 1.0e-8); //Test[i, i] -= Math.Sign(Test[i, i]); Test[i, i] = 0; } double TestNorm = Test.InfNorm(); double scale = Math.Max(Mbefore.InfNorm(), R.InfNorm()); Debug.Assert(TestNorm / scale < 1.0e-4); /* * if(TestNorm / scale >= 1.0e-8) { * var MM = Mbefore.CloneAs(); * MultidimensionalArray Lo = MultidimensionalArray.Create(n, n); * * for(int j = 0; j < n; j++) { * double Lo_jj = MM[j, j]; * for(int k = 0; k < j; k++) { * Lo_jj -= Lo[j, k].Pow2(); * } * * double sig = Math.Abs(Lo_jj); * Lo[j, j] = Math.Sqrt(Lo_jj * sig); * * * for(int i = j; i < n; i++) { * double acc = MM[i, j]; * for(int k = 0; k < j; k++) { * acc -= Lo[i, k] * Lo[j, k]; * } * * Lo[i, j] = (1 / (Lo[j, j] * sig)) * acc; * } * } * * int info = 0; * unsafe { * fixed(double* B_entries = Lo.Storage) { * * int UPLO = 'L', DIAG = 'N'; * LAPACK.F77_LAPACK.DTRTRI_(ref UPLO, ref DIAG, ref n, B_entries, ref n, out info); * } * } * * MultidimensionalArray Up = MultidimensionalArray.Create(n, n); * Lo.TransposeTo(Up); * Test.Clear(); * Test.Multiply(-1.0, Lo, Mbefore, R, 1.0, "ij", "ik", "kl", "lj"); * * * for(int i = 0; i < n; i++) { * //Debug.Assert((Test[i, i].Abs() - 1.0).Abs() < 1.0e-8); * Test[i, i] -= Math.Sign(Test[i, i]); * } * * double TestNorm1 = Test.InfNorm(); * //double scale = Math.Max(Mbefore.InfNorm(), R.InfNorm()); * Console.WriteLine(TestNorm1); * * } */ #endif }