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; }
public static int SVDecomp(PZMath_matrix A, PZMath_matrix V, PZMath_vector S, PZMath_vector work) { int a, b, i, j; int M = A.RowCount; int N = A.ColumnCount; int K = System.Math.Min(M, N); if (M < N) { PZMath_errno.ERROR ("PZMath_linalg::SVDDecomp(),svd of MxN matrix, M<N, is not implemented", PZMath_errno.PZMath_EUNIMPL); } else if (V.RowCount != N) { PZMath_errno.ERROR ("PZMath_linalg::SVDDecomp(), square matrix V must match second dimension of matrix A", PZMath_errno.PZMath_EBADLEN); } else if (V.RowCount != V.ColumnCount) { PZMath_errno.ERROR ("PZMath_linalg::SVDDecomp(),matrix V must be square", PZMath_errno.PZMath_ENOTSQR); } else if (S.Size != N) { PZMath_errno.ERROR ("PZMath_linalg::SVDDecomp(),length of vector S must match second dimension of matrix A", PZMath_errno.PZMath_EBADLEN); } else if (work.Size != N) { PZMath_errno.ERROR ("PZMath_linalg::SVDDecomp(),length of workspace must match second dimension of matrix A", PZMath_errno.PZMath_EBADLEN); } /* Handle the case of N = 1 (SVD of a column vector) */ if (N == 1) { PZMath_vector column = A.Column(0); double norm = PZMath_blas.Dnrm2(column); S[0] = norm; V[0, 0] = 1.0; if (norm != 0.0) { PZMath_blas.Dscal(1.0 / norm, column); } return PZMath_errno.PZMath_SUCCESS; } { PZMath_vector f = work.SubVector(0, K - 1); /* bidiagonalize matrix A, unpack A into U S V */ PZMath_linalg.BidiagDecomp (A, S, f); PZMath_linalg.BidiagUnpack2 (A, S, f, V); /* apply reduction steps to B=(S,Sd) */ ChopSmallElements (S, f); /* Progressively reduce the matrix until it is diagonal */ b = N - 1; while (b > 0) { double fbm1 = f[b - 1]; if (fbm1 == 0.0 || PZMath_sys.Isnan (fbm1)) { b--; continue; } /* Find the largest unreduced block (a,b) starting from b and working backwards */ a = b - 1; while (a > 0) { double fam1 = f[a - 1]; if (fam1 == 0.0 || PZMath_sys.Isnan (fam1)) { break; } a--; } { int n_block = b - a + 1; PZMath_vector S_block = S.SubVector(a, n_block); PZMath_vector f_block = f.SubVector (a, n_block - 1); PZMath_matrix U_block = A.Submatrix(0, a, A.RowCount, n_block); PZMath_matrix V_block = V.Submatrix(0, a, V.RowCount, n_block); QRStep (S_block, f_block, U_block, V_block); /* remove any small off-diagonal elements */ ChopSmallElements (S_block, f_block); } } } /* Make singular values positive by reflections if necessary */ for (j = 0; j < K; j++) { double Sj = S[j]; if (Sj < 0.0) { for (i = 0; i < N; i++) { double Vij = V[i, j]; V[i, j] = -Vij; } S[j] = -Sj; } } /* Sort singular values into decreasing order */ for (i = 0; i < K; i++) { double S_max = S[i]; int i_max = i; for (j = i + 1; j < K; j++) { double Sj = S[j]; if (Sj > S_max) { S_max = Sj; i_max = j; } } if (i_max != i) { /* swap eigenvalues */ S.Swap(i, i_max); /* swap eigenvectors */ A.SwapColumns(i, i_max); V.SwapColumns(i, i_max); } } return PZMath_errno.PZMath_SUCCESS; }