public static void gaussj(MatDoub a) { // Overloaded version with no right-hand sides. Replaces a by its // inverse. MatDoub b = new MatDoub(a.nrows(), 0); // Dummy vector with zero columns. gaussj(a, b); }
public static void printmatrix(MatDoub a) { for (int i = 0; i < a.nrows(); i++) { for (int j = 0; j < a.ncols(); j++) { System.Console.Write(a[i][j] + ","); } System.Console.WriteLine(); } System.Console.WriteLine(); }
public static void fillMat(MatDoub a, Double[,] b) { int rows = a.nrows(); for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { a[i][j] = b[i, j]; } } }
/// <summary> /// Constructor. The single argument is A. The SVD computation is done by /// decompose(), and the results are sorted by reorder(). /// </summary> /// <param name="a">The matrix to decompose.</param> public SVD(MatDoub a) { m = (a.nrows()); n = (a.ncols()); u = new MatDoub(a); v = new MatDoub(n, n); w = new VecDoub(n); eps = double.Epsilon; decompose(); reorder(); tsh = 0.5 * Math.Sqrt(m + n + 1.0) * w[0] * eps; // Default threshold for nonzero singular values; }
public Sprsin(MatDoub a)//TODO: make a VecULong type to further save on space. { /************************************ * Converts a square matrix a[1..n][1..n] into row-indexed sparse storage mode. * Only elements of a with magnitude ≥thresh are retained. Output is in two linear arrays * with dimension nmax (an input parameter): sa[1..] contains array values, indexed by ija[1..]. * The number of elements filled of sa and ija on output are both ija[ija[1]-1]-1 ************************************/ sa = new VecDoub(new double[nmax]); ija = new VecLong(18, new long[nmax], 0); n = a.nrows(); int i, j, k; for (j = 0; j < n; j++) { sa[j] = a[j][j]; //Store the diagonal elements. } ija[0] = n + 1; //Index to the first off diagonal element if any. k = n; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (Math.Abs(a[i][j]) >= thresh && i != j) { if (++k > (int)nmax) { throw new Exception("sprsin: nmax too small"); } sa[k] = a[i][j]; //Store off diagonal elements. ija[k] = j; //And their column indices. } } ija[i + 1] = k + 1; //As each row is completed, store index to next } this.numelements = k + 1; }
/// <summary> /// Solve m sets of n equations AX=B using the pseudoinverse of A. /// The right-hand sides are input as b[0..n-1][0..m-1], while /// x[0..n-1][0..m-1] return the solutions. /// If positive, thresh is the threshold value below which singular values /// as considered to be zero. If thresh is negative, a default based on rounodd error is used. /// </summary> /// <param name="b"></param> /// <param name="x"></param> /// <param name="thresh"></param> //void solve(MatDoub_I &b, MatDoub_O &x, double thresh); public void solve(MatDoub b, MatDoub x, double thresh) { int i, j, m = b.ncols(); if (b.nrows() != n || x.nrows() != n || b.ncols() != x.ncols()) { throw new Exception("SVD::solve bad sizes"); } VecDoub xx = new VecDoub(n); for (j = 0; j < m; j++) { for (i = 0; i < n; i++) { xx[i] = b[i][j]; } solve(xx, xx, thresh); for (i = 0; i < n; i++) { x[i][j] = xx[i]; } } }
private bool sing; // Indicates whether A is singular. public QRdcmp(MatDoub a) { n = a.nrows(); MatDoub qt = new MatDoub(n, n); MatDoub r = new MatDoub(a); sing = (false); int i, j, k; VecDoub c = new VecDoub(n); VecDoub d = new VecDoub(n); double scale, sigma, sum, tau; for (k = 0; k < n - 1; k++) { scale = 0.0; for (i = k; i < n; i++) { scale = Math.Max(scale, Math.Abs(r[i][k])); } if (scale == 0.0) { // Singular case. sing = true; c[k] = d[k] = 0.0; } else { // Form Qk and Qk A. for (i = k; i < n; i++) { r[i][k] /= scale; } for (sum = 0.0, i = k; i < n; i++) { sum += r[i][k] * r[i][k]; } sigma = NR.SIGN(Math.Sqrt(sum), r[k][k]); r[k][k] += sigma; c[k] = sigma * r[k][k]; d[k] = -scale * sigma; for (j = k + 1; j < n; j++) { for (sum = 0.0, i = k; i < n; i++) { sum += r[i][k] * r[i][j]; } tau = sum / c[k]; for (i = k; i < n; i++) { r[i][j] -= tau * r[i][k]; } } } } d[n - 1] = r[n - 1][n - 1]; if (d[n - 1] == 0.0) { sing = true; } /////////////////////////// for (i = 0; i < n; i++) { // Form QT explicitly. for (j = 0; j < n; j++) { qt[i][j] = 0.0; } qt[i][i] = 1.0; } for (k = 0; k < n - 1; k++) { if (c[k] != 0.0) { for (j = 0; j < n; j++) { sum = 0.0; for (i = k; i < n; i++) { sum += r[i][k] * qt[i][j]; } sum /= c[k]; for (i = k; i < n; i++) { qt[i][j] -= sum * r[i][k]; } } } } for (i = 0; i < n; i++) { // Form R explicitly. r[i][i] = d[i]; for (j = 0; j < i; j++) { r[i][j] = 0.0; } } }
public static void gaussj(MatDoub a, MatDoub b) { // Linear equation solution by Gauss-Jordan elimination, // equation (2.1.1) above. The input matrix is a[0..n-1][0..n-1]. // b[0..n-1][0..m-1] is input containing the m right-hand side vectors. // On output, a is replaced by its matrix inverse, and b is replaced by // the corresponding set of solution vectors. int i, icol = 0, irow = 0, j, k, l, ll, n = a.nrows(), m = a.ncols(); double big, dum, pivinv; VecInt indxc = new VecInt(n); VecInt indxr = new VecInt(n); VecInt ipiv = new VecInt(n); // These integer arrays are used // for bookkeeping on the pivoting. for (j = 0; j < n; j++) { ipiv[j] = 0; } for (i = 0; i < n; i++) // This is the main loop over the columns to // be { big = 0.0; // reduced. for (j = 0; j < n; j++) { // This is the outer loop of the search for a pivot over the entire matrix! if (ipiv[j] != 1) // element. { for (k = 0; k < n; k++) { if (ipiv[k] == 0) { if (Math.Abs(a[j][k]) >= big) { big = Math.Abs(a[j][k]); irow = j; icol = k; } } } } } ++(ipiv[icol]); // We now have the pivot element, so we interchange rows, if needed, // to put the pivot element on the diagonal. The columns are not // physically interchanged, only relabeled: indxc[i], the column of the .iC1/th // pivot element, is the .iC1/th column that is reduced, while indxr[i] is // the row in which that pivot element was originally located. // If indxr[i] indxc[i], there is an implied column interchange. // With this form of bookkeeping, the solution bs will end up in the // correct order, and the inverse matrix will be scrambled by columns. if (irow != icol) { for (l = 0; l < n; l++) { NR.SWAP(a, irow, l, icol, l); } for (l = 0; l < m; l++) { NR.SWAP(b, irow, l, icol, l); } } indxr[i] = irow; // We are now ready to divide the pivot row by the // pivot element, located at irow and icol. indxc[i] = icol; if (a[icol][icol] == 0.0) { throw new Exception("gaussj: Singular Matrix"); } pivinv = 1.0 / a[icol][icol]; a[icol][icol] = 1.0; for (l = 0; l < n; l++) { a[icol][l] *= pivinv; } for (l = 0; l < m; l++) { b[icol][l] *= pivinv; } for (ll = 0; ll < n; ll++) { // Next, we reduce the rows... if (ll != icol) { // ...except for the pivot one, of course. dum = a[ll][icol]; a[ll][icol] = 0.0; for (l = 0; l < n; l++) { a[ll][l] -= a[icol][l] * dum; } for (l = 0; l < m; l++) { b[ll][l] -= b[icol][l] * dum; } } } } // This is the end of the main loop over columns of the reduction. It // only remains to unscramble the solution in view of the column // interchanges. We do this by interchanging pairs of columns in the // reverse order that the permutation was built up. for (l = n - 1; l >= 0; l--) { if (indxr[l] != indxc[l]) { for (k = 0; k < n; k++) { NR.SWAP(a, k, indxr[l], k, indxc[l]); } } } }