public static int QRPTDecomp(PZMath_matrix A, PZMath_vector tau, PZMath_permutation p, out int signum, PZMath_vector norm) { int M = A.RowCount; int N = A.ColumnCount; signum = 0; if (tau.Size != System.Math.Min(M, N)) { PZMath_errno.ERROR("size of tau must be MIN(M,N)", PZMath_errno.PZMath_EBADLEN); } else if (p.Size != N) { PZMath_errno.ERROR("permutation size must be N", PZMath_errno.PZMath_EBADLEN); } else if (norm.Size != N) { PZMath_errno.ERROR("norm size must be N", PZMath_errno.PZMath_EBADLEN); } else { int i; signum = 1; p.Init(); /* set to identity */ /* Compute column norms and store in workspace */ for (i = 0; i < N; i++) { PZMath_vector c = A.Column(i); double x = PZMath_blas.Dnrm2(c); norm[i] = x; } for (i = 0; i < System.Math.Min(M, N); i++) { /* Bring the column of largest norm into the pivot position */ double max_norm = norm[i]; int j; int kmax = i; for (j = i + 1; j < N; j++) { double x = norm[j]; if (x > max_norm) { max_norm = x; kmax = j; } } if (kmax != i) { A.SwapColumns(i, kmax); p.Swap(i, kmax); norm.Swap(i, kmax); signum = - signum; } /* Compute the Householder transformation to reduce the j-th column of the matrix to a multiple of the j-th unit vector */ { PZMath_vector c_full = A.Column(i); PZMath_vector c = c_full.SubVector(i, M - i); double tau_i = HouseholderTransform(c); tau[i] = tau_i; /* Apply the transformation to the remaining columns */ if (i + 1 < N) { PZMath_matrix m = A.Submatrix(i, i + 1, M - i, N - (i + 1)); HouseholderHM (tau_i, c, m); } } /* Update the norms of the remaining columns too */ if (i + 1 < M) { for (j = i + 1; j < N; j++) { double x = norm[j]; if (x > 0.0) { double y = 0; double temp= A[i, j] / x; if (System.Math.Abs(temp) >= 1) y = 0.0; else y = x * System.Math.Sqrt(1 - temp * temp); /* recompute norm to prevent loss of accuracy */ if (System.Math.Abs(y / x) < System.Math.Sqrt(20.0) * PZMath_machine.PZMath_SQRT_DBL_EPSILON) { PZMath_vector c_full = A.Column(j); PZMath_vector c = c_full.SubVector(i + 1, M - (i + 1)); y = PZMath_blas.Dnrm2(c); } norm[j] = y; } } } } } return PZMath_errno.PZMath_SUCCESS; }
// These functions factorize the square matrix A into the LU decomposition PA = LU. // On output the diagonal and upper triangular part of the input matrix A contain the matrix U. // The lower triangular part of the input matrix (excluding the diagonal) contains L. // The diagonal elements of L are unity, and are not stored. // The permutation matrix P is encoded in the permutation p. // The j-th column of the matrix P is given by the k-th column of the identity matrix, // where k = p_j the j-th element of the permutation vector. // The sign of the permutation is given by signum. // It has the value (-1)^n, where n is the number of interchanges in the permutation. // The algorithm used in the decomposition is Gaussian Elimination with partial pivoting // (Golub & Van Loan, Matrix Computations, Algorithm 3.4.1). public static int LUDecomp(PZMath_matrix A, PZMath_permutation p, out int signum) { if (A.ColumnCount != A.RowCount) { PZMath_errno.ERROR("PZMath_linalg::LUDecomp(), LU decomposition requires square matrix", PZMath_errno.PZMath_ENOTSQR); signum = 1; return PZMath_errno.PZMath_ENOTSQR; } else if (p.Size != A.ColumnCount) { PZMath_errno.ERROR("PZMath_linalg::LUDecomp(), permutation length must match matrix size", PZMath_errno.PZMath_EBADLEN); signum = 1; return PZMath_errno.PZMath_EBADLEN; } else { int N = A.ColumnCount; int i, j, k; signum = 1; p.Init(); for (j = 0; j < N - 1; j++) { /* Find maximum in the j-th column */ double ajj; double max = System.Math.Abs(A[j, j]); int i_pivot = j; for (i = j + 1; i < N; i++) { double aij = System.Math.Abs(A[i, j]); if (aij > max) { max = aij; i_pivot = i; } } if (i_pivot != j) { A.SwapRows(j, i_pivot); p.Swap(j, i_pivot); signum = -(signum); } ajj = A[j, j]; if (ajj != 0.0) { for (i = j + 1; i < N; i++) { double aij = A[i, j] / ajj; A[i, j] = aij; for (k = j + 1; k < N; k++) { double aik = A[i, k]; double ajk = A[j, k]; A[i, k] = aik - aij * ajk; } } } } return PZMath_errno.PZMath_SUCCESS; } }