Exemplo n.º 1
0
        public static int BalanceColumns(PZMath_matrix A, PZMath_vector D)
        {
            int N = A.ColumnCount;
            int j;

            if (D.Size != N)
            {
                PZMath_errno.ERROR ("PZMath_linalg::BalanceColumns(), length of D must match second dimension of A", PZMath_errno.PZMath_EINVAL);
            }

            D.SetAll(1.0);

            for (j = 0; j < N; j++)
            {
                PZMath_vector A_j = A.Column(j);

                double s = PZMath_blas.Dasum (A_j);

                double f = 1.0;

                if (s == 0.0 || !PZMath_sys.Finite(s))
                {
                    D[j] = f;
                    continue;
                }

                while (s > 1.0)
                {
                    s /= 2.0;
                    f *= 2.0;
                }

                while (s < 0.5)
                {
                    s *= 2.0;
                    f /= 2.0;
                }

                D[j] = f;

                if (f != 1.0)
                    PZMath_blas.Dscal(1.0/f, A_j);
            }

            return PZMath_errno.PZMath_SUCCESS;
        }
Exemplo n.º 2
0
        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;
        }
Exemplo n.º 3
0
        // These functions compute the inverse of a matrix A from its LU decomposition (LU,p),
        // storing the result in the matrix inverse.
        // The inverse is computed by solving the system A x = b for each column of the identity matrix.
        // It is preferable to avoid direct use of the inverse whenever possible,
        // as the linear solver functions can obtain the same result more efficiently and reliably
        // (consult any introductory textbook on numerical linear algebra for details).
        public static int LUInvert(PZMath_matrix LU, PZMath_permutation p, PZMath_matrix inverse)
        {
            int i;
            int n = LU.RowCount;
            int status = PZMath_errno.PZMath_SUCCESS;

            inverse.SetIdentity();

            for (i = 0; i < n; i++)
            {
                PZMath_vector c = inverse.Column(i);
                int status_i = LUSVX(LU, p, c);

                if (status_i == PZMath_errno.PZMath_SUCCESS)
                    status = status_i;
            }
            return status;
        }
Exemplo n.º 4
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.º 5
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.º 6
0
        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;
        }
Exemplo n.º 7
0
        public static int QR_QTvec(PZMath_matrix QR, PZMath_vector tau, PZMath_vector v)
        {
            int M = QR.RowCount;
            int N = QR.ColumnCount;

            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 (v.Size != M)
            {
                PZMath_errno.ERROR("vector size must be N", PZMath_errno.PZMath_EBADLEN);
            }
            else
            {
                int i;

                /* compute Q^T v */
                for (i = 0; i < System.Math.Min(M, N); i++)
                {
                    PZMath_vector c = QR.Column(i);
                    PZMath_vector h = c.SubVector(i, M - i);
                    PZMath_vector w = v.SubVector(i, M - i);
                    double ti = tau[i];

                    HouseholderHV(ti, h, w);
                }
                return PZMath_errno.PZMath_SUCCESS;
            }
            return 0;
        }