/// <summary>LU Decomposition</summary> /// <param name="A"> Rectangular matrix /// </param> /// <returns> Structure to access L, U and piv. /// </returns> public LUDecomposition(GeneralMatrix A) { // Use a "left-looking", dot-product, Crout/Doolittle algorithm. LU = A.ArrayCopy; m = A.RowDimension; n = A.ColumnDimension; piv = new int[m]; for (int i = 0; i < m; i++) { piv[i] = i; } pivsign = 1; double[] LUrowi; double[] LUcolj = new double[m]; // Outer loop. for (int j = 0; j < n; j++) { // Make a copy of the j-th column to localize references. for (int i = 0; i < m; i++) { LUcolj[i] = LU[i][j]; } // Apply previous transformations. for (int i = 0; i < m; i++) { LUrowi = LU[i]; // Most of the time is spent in the following dot product. int kmax = System.Math.Min(i, j); double s = 0.0; for (int k = 0; k < kmax; k++) { s += LUrowi[k] * LUcolj[k]; } LUrowi[j] = LUcolj[i] -= s; } // Find pivot and exchange if necessary. int p = j; for (int i = j + 1; i < m; i++) { if (System.Math.Abs(LUcolj[i]) > System.Math.Abs(LUcolj[p])) { p = i; } } if (p != j) { for (int k = 0; k < n; k++) { double t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t; } int k2 = piv[p]; piv[p] = piv[j]; piv[j] = k2; pivsign = -pivsign; } // Compute multipliers. if (j < m & LU[j][j] != 0.0) { for (int i = j + 1; i < m; i++) { LU[i][j] /= LU[j][j]; } } } }
/// <summary>Solve X*A = B, which is also A'*X' = B'</summary> /// <param name="B"> right hand side /// </param> /// <returns> solution if A is square, least squares solution otherwise. /// </returns> public virtual GeneralMatrix SolveTranspose(GeneralMatrix B) { return(Transpose().Solve(B.Transpose())); }
/// <summary>Check for symmetry, then construct the eigenvalue decomposition</summary> /// <param name="Arg"> Square matrix /// </param> /// <returns> Structure to access D and V. /// </returns> public EigenvalueDecomposition(GeneralMatrix Arg) { double[][] A = Arg.Array; n = Arg.ColumnDimension; V = new double[n][]; for (int i = 0; i < n; i++) { V[i] = new double[n]; } d = new double[n]; e = new double[n]; issymmetric = true; for (int j = 0; (j < n) & issymmetric; j++) { for (int i = 0; (i < n) & issymmetric; i++) { issymmetric = (A[i][j] == A[j][i]); } } if (issymmetric) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { V[i][j] = A[i][j]; } } // Tridiagonalize. tred2(); // Diagonalize. tql2(); } else { H = new double[n][]; for (int i2 = 0; i2 < n; i2++) { H[i2] = new double[n]; } ort = new double[n]; for (int j = 0; j < n; j++) { for (int i = 0; i < n; i++) { H[i][j] = A[i][j]; } } // Reduce to Hessenberg form. orthes(); // Reduce Hessenberg to real Schur form. hqr2(); } }
/// <summary>Solve A*X = B</summary> /// <param name="B"> right hand side /// </param> /// <returns> solution if A is square, least squares solution otherwise /// </returns> public virtual GeneralMatrix Solve(GeneralMatrix B) { return(m == n ? (new LUDecomposition(this)).Solve(B):(new QRDecomposition(this)).Solve(B)); }