Exemplo n.º 1
0
        public static int BidiagDecomp(PZMath_matrix A, PZMath_vector tau_U, PZMath_vector tau_V)
        {
            if (A.RowCount < A.ColumnCount)
                PZMath_errno.ERROR ("PZMath_linalg::BidiagDecomp(), bidiagonal decomposition requires M>=N", PZMath_errno.PZMath_EBADLEN);
            else if (tau_U.Size != A.ColumnCount)
                PZMath_errno.ERROR ("PZMath_linalg::BidiagDecomp(),size of tau_U must be N", PZMath_errno.PZMath_EBADLEN);
            else if (tau_V.Size + 1 != A.ColumnCount)
                PZMath_errno.ERROR ("PZMath_linalg::BidiagDecomp(),size of tau_V must be (N - 1)", PZMath_errno.PZMath_EBADLEN);
            else
            {
                int M = A.RowCount;
                int N = A.ColumnCount;
                int i;

                for (i = 0 ; i < N; i++)
                {
                    /* Apply Householder transformation to current column */

                {
                    PZMath_vector c = A.Column(i);
                    PZMath_vector v = c.SubVector(i, M - i);
                    double tau_i = PZMath_linalg.HouseholderTransform(v);

                    /* Apply the transformation to the remaining columns */

                    if (i + 1 < N)
                    {
                        PZMath_matrix m = A.Submatrix(i, i + 1, M - i, N - (i + 1));
                        PZMath_linalg.HouseholderHM(tau_i, v, m);
                    }

                    tau_U[i] = tau_i;

                }

                    /* Apply Householder transformation to current row */

                    if (i + 1 < N)
                    {
                        PZMath_vector r = A.Row(i);
                        PZMath_vector v = r.SubVector(i + 1, N - (i + 1));
                        double tau_i = PZMath_linalg.HouseholderTransform (v);

                        /* Apply the transformation to the remaining rows */

                        if (i + 1 < M)
                        {
                            PZMath_matrix m = A.Submatrix(i+1, i+1, M - (i+1), N - (i+1));
                            PZMath_linalg.HouseholderMH(tau_i, v, m);
                        }

                        tau_V[i] = tau_i;
                    }
                }
            }

            return PZMath_errno.PZMath_SUCCESS;
        }
Exemplo n.º 2
0
        /* Modified algorithm which is better for M>>N */
        public static int SVDecompMod(PZMath_matrix A, PZMath_matrix X, PZMath_matrix V, PZMath_vector S, PZMath_vector work)
        {
            int i, j;

            int M = A.RowCount;
            int N = A.ColumnCount;

            if (M < N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::SVDDecompMod(), svd of MxN matrix, M<N, is not implemented", PZMath_errno.PZMath_EUNIMPL);
            }
            else if (V.RowCount != N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::SVDDecompMod(), 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::SVDDecompMod(), matrix V must be square", PZMath_errno.PZMath_ENOTSQR);
            }
            else if (X.RowCount != N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::SVDDecompMod(), square matrix X must match second dimension of matrix A",
                    PZMath_errno.PZMath_EBADLEN);
            }
            else if (X.RowCount != X.ColumnCount)
            {
                PZMath_errno.ERROR ("PZMath_linalg::SVDDecompMod(), matrix X must be square", PZMath_errno.PZMath_ENOTSQR);
            }
            else if (S.Size != N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::SVDDecompMod(), 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::SVDDecompMod(), length of workspace must match second dimension of matrix A",
                    PZMath_errno.PZMath_EBADLEN);
            }

            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;
            }

            /* Convert A into an upper triangular matrix R */

            for (i = 0; i < N; i++)
            {
                PZMath_vector c = A.Column(i);
                PZMath_vector v = c.SubVector(i, M - i);
                double tau_i = PZMath_linalg.HouseholderTransform(v);

                /* Apply the transformation to the remaining columns */

                if (i + 1 < N)
                {
                    PZMath_matrix m =A.Submatrix(i, i + 1, M - i, N - (i + 1));
                    PZMath_linalg.HouseholderHM(tau_i, v, m);
                }

                S[i] = tau_i;
            }

            /* Copy the upper triangular part of A into X */

            for (i = 0; i < N; i++)
            {
                for (j = 0; j < i; j++)
                {
                    X[i, j] = 0.0;
                }

            {
                double Aii = A[i, i];
                X[i, i] = Aii;
            }

                for (j = i + 1; j < N; j++)
                {
                    double Aij = A[i, j];
                    X[i, j] = Aij;
                }
            }

            /* Convert A into an orthogonal matrix L */

            for (j = N; j > 0 && (j -- > 0);)
            {
                /* Householder column transformation to accumulate L */
                double tj = S[j];
                PZMath_matrix m = A.Submatrix(j, j, M - j, N - j);
                PZMath_linalg.HouseholderHM1(tj, m);
            }

            /* unpack R into X V S */

            PZMath_linalg.SVDecomp(X, V, S, work);

            /* Multiply L by X, to obtain U = L X, stored in U */

            {
            PZMath_vector sum = work.SubVector(0, N);

            for (i = 0; i < M; i++)
            {
                PZMath_vector L_i = A.Row(i);
                sum.SetZero();

                for (j = 0; j < N; j++)
                {
                    double Lij = L_i[j];
                    PZMath_vector X_j = X.Row(j);
                    PZMath_blas.Daxpy(Lij, X_j, sum);

                }

                L_i.MemCopyFrom(sum);
            }
            }
            return PZMath_errno.PZMath_SUCCESS;
        }
Exemplo n.º 3
0
        public static int CholeskyDecomp(PZMath_matrix A)
        {
            int M = A.RowCount;
            int N = A.ColumnCount;

            if (M != N)
            {
                PZMath_errno.ERROR("PZMath_linalg::CholeskyDecomp()::cholesky decomposition requires square matrix", PZMath_errno.PZMath_ENOTSQR);
            }

            int i, j, k;
            int status = 0;

            /* Do the first 2 rows explicitly.  It is simple, and faster.  And
             * one can return if the matrix has only 1 or 2 rows.
             */

            double A_00 = A[0, 0];

            double L_00 = QuietSqrt(A_00);

            if (A_00 <= 0)
            {
                status = PZMath_errno.PZMath_EDOM;
            }

            A[0, 0] = L_00;

            if (M > 1)
            {
                double A_10 = A[1, 0];
                double A_11 = A[1, 1];

                double L_10 = A_10 / L_00;
                double diag = A_11 - L_10 * L_10;
                double L_11 = QuietSqrt(diag);

                if (diag <= 0)
                {
                    status = PZMath_errno.PZMath_EDOM;
                }

                A[1, 0] = L_10;
                A[1, 1] = L_11;
            }

            for (k = 2; k < M; k++)
            {
                double A_kk = A[k, k];

                for (i = 0; i < k; i++)
                {
                    double sum = 0;

                    double A_ki = A[k, i];
                    double A_ii = A[i, i];
                    PZMath_vector ci = A.Row(i);
                    PZMath_vector ck = A.Row(k);

                    if (i > 0)
                    {
                        PZMath_vector di = ci.SubVector(0, i);
                        PZMath_vector dk = ck.SubVector(0, i);
                        PZMath_blas.Ddot(di, dk, out sum);
                    }

                    A_ki = (A_ki - sum) / A_ii;
                    A[k, i] = A_ki;
                }

                {
                    PZMath_vector ck = A.Row(k);
                    PZMath_vector dk = ck.SubVector(0, k);
                    double sum = PZMath_blas.Dnrm2(dk);
                    double diag = A_kk - sum * sum;

                    double L_kk = QuietSqrt(diag);

                    if (diag <= 0)
                    {
                        status = PZMath_errno.PZMath_EDOM;
                    }
                    A[k, k] = L_kk;
                }
            }

            /* Now copy the transposed lower triangle to the upper triangle,
             * the diagonal is common.
             */

            for (i = 1; i < M; i++)
            {
                for (j = 0; j < i; j++)
                {
                    double A_ij = A[i, j];
                    A[j, i] = A_ij;
                }
            }

            if (status == PZMath_errno.PZMath_EDOM)
            {
                PZMath_errno.ERROR("PZMath_linalg::CholeskyDecomp()::matrix must be positive definite", PZMath_errno.PZMath_EDOM);
            }

            return PZMath_errno.PZMath_SUCCESS;
        }
Exemplo n.º 4
0
        public static int BidiagUnpack2(PZMath_matrix A, PZMath_vector tau_U, PZMath_vector tau_V, PZMath_matrix V)
        {
            int M = A.RowCount;
            int N = A.ColumnCount;

            int K = System.Math.Min(M, N);

            if (M < N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::BidiagUnpack2(),matrix A must have M >= N", PZMath_errno.PZMath_EBADLEN);
            }
            else if (tau_U.Size != K)
            {
                PZMath_errno.ERROR ("PZMath_linalg::BidiagUnpack2(),size of tau must be MIN(M,N)", PZMath_errno.PZMath_EBADLEN);
            }
            else if (tau_V.Size + 1 != K)
            {
                PZMath_errno.ERROR ("PZMath_linalg::BidiagUnpack2(),size of tau must be MIN(M,N) - 1", PZMath_errno.PZMath_EBADLEN);
            }
            else if (V.RowCount != N || V.ColumnCount != N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::BidiagUnpack2(),size of V must be N x N", PZMath_errno.PZMath_EBADLEN);
            }
            else
            {
                int i, j;

                /* Initialize V to the identity */
                V.SetIdentity();

                for (i = N - 1; i > 0 && (i -- > 0);)
                {
                    /* Householder row transformation to accumulate V */
                    PZMath_vector r = A.Row(i);
                    PZMath_vector h = r.SubVector(i + 1, N - (i+1));

                    double ti = tau_V[i];

                    PZMath_matrix m = V.Submatrix(i + 1, i + 1, N-(i+1), N-(i+1));
                    PZMath_linalg.HouseholderHM (ti, h, m);
                }

                /* Copy superdiagonal into tau_v */

                for (i = 0; i < N - 1; i++)
                {
                    double Aij = A[i, i+1];
                    tau_V[i] = Aij;
                }

                /* Allow U to be unpacked into the same memory as A, copy
                   diagonal into tau_U */

                for (j = N; j > 0 && (j -- > 0);)
                {
                    /* Householder column transformation to accumulate U */
                    double tj = tau_U[j];
                    double Ajj = A[j, j];
                    PZMath_matrix m = A.Submatrix (j, j, M-j, N-j);

                    tau_U[j] = Ajj;
                    PZMath_linalg.HouseholderHM1(tj, m);
                }
            }
            return PZMath_errno.PZMath_SUCCESS;;
        }