Ejemplo n.º 1
0
        private static void rotateArray(SVDRec R, int x)
        {
            if (x == 0) return;
            x *= R.Vt.cols;

            int i, j, n, start, nRow, nCol;
            double t1, t2;
            int size = R.Vt.rows * R.Vt.cols;
            j = start = 0;
            t1 = R.Vt.value[0][0];
            for (i = 0; i < size; i++)
            {
                if (j >= x) n = j - x;
                else n = j - x + size;
                nRow = n / R.Vt.cols;
                nCol = n - nRow * R.Vt.cols;
                t2 = R.Vt.value[nRow][nCol];
                R.Vt.value[nRow][nCol] = t1;
                t1 = t2;
                j = n;
                if (j == start)
                {
                    start = ++j;
                    nRow = j / R.Vt.cols;
                    nCol = j - nRow * R.Vt.cols;
                    t1 = R.Vt.value[nRow][nCol];
                }
            }
        }
Ejemplo n.º 2
0
        private static SVDRec svdLAS2(SMat A)
        {
            int ibeta, it, irnd, machep, negep, n, steps, nsig, neig;
            double kappa = 1e-6;

            double[] las2end = new double[2] { -1.0e-30, 1.0e-30 };
            double[] ritz, bnd;

            double[][] wptr = new double[10][];

            svdResetCounters();

            int dimensions = A.rows;
            if (A.cols < dimensions) dimensions = A.cols;
            int iterations = dimensions;

            // Check parameters
            if (check_parameters(A, dimensions, iterations, las2end[0], las2end[1]) > 0) return null;

            // If A is wide, the SVD is computed on its transpose for speed.
            bool transpose = false;
            if (A.cols >= A.rows * 1.2)
            {
                //Console.WriteLine("TRANSPOSING THE MATRIX FOR SPEED\n");
                transpose = true;
                A = svdTransposeS(A);
            }

            n = A.cols;
            // Compute machine precision
            ibeta = it = irnd = machep = negep = 0;
            machar(ref ibeta, ref it, ref irnd, ref machep, ref negep);
            eps1 = eps * Math.Sqrt((double)n);
            reps = Math.Sqrt(eps);
            eps34 = reps * Math.Sqrt(reps);
            //Console.WriteLine("Machine precision {0} {1} {2} {3} {4}", ibeta, it, irnd, machep, negep);

            // Allocate temporary space.
            wptr[0] = new double[n];
            for (int i = 0; i < n; ++i) wptr[0][i] = 0.0;
            wptr[1] = new double[n];
            wptr[2] = new double[n];
            wptr[3] = new double[n];
            wptr[4] = new double[n];
            wptr[5] = new double[n];
            wptr[6] = new double[iterations];
            wptr[7] = new double[iterations];
            wptr[8] = new double[iterations];
            wptr[9] = new double[iterations + 1];
            ritz = new double[iterations + 1];
            for (int i = 0; i < iterations + 1; ++i) ritz[0] = 0.0;
            bnd = new double[iterations + 1];
            for (int i = 0; i < iterations + 1; ++i) bnd[0] = 0.0;

            LanStore = new double[iterations + MAXLL][];
            for (int i = 0; i < iterations + MAXLL; ++i)
            {
                LanStore[i] = null;
            }
            OPBTemp = new double[A.rows];

            // Actually run the lanczos thing:
            neig = 0;
            steps = lanso(A, iterations, dimensions, las2end[0], las2end[1], ritz, bnd, wptr, ref neig, n);

            //Console.WriteLine("NUMBER OF LANCZOS STEPS {0}", steps + 1);
            //Console.WriteLine("RITZ VALUES STABILIZED = RANK {0}", neig);

            kappa = svd_dmax(Math.Abs(kappa), eps34);

            SVDRec R = new SVDRec();
            R.d = dimensions;
            DMat Tmp1 = new DMat();
            Tmp1.rows = R.d;
            Tmp1.cols = A.rows;
            Tmp1.value = new double[Tmp1.rows][];
            for (int mm = 0; mm < Tmp1.rows; ++mm)
            {
                Tmp1.value[mm] = new double[Tmp1.cols];
                for (int j = 0; j < Tmp1.cols; ++j)
                {
                    Tmp1.value[mm][j] = 0.0;
                }
            }
            R.Ut = Tmp1;
            R.S = new double[R.d];
            for (int k = 0; k < R.d; ++k)
            {
                R.S[k] = 0.0;
            }
            DMat Tmp2 = new DMat();
            Tmp2.rows = R.d;
            Tmp2.cols = A.cols;
            Tmp2.value = new double[Tmp2.rows][];
            for (int mm = 0; mm < Tmp2.rows; ++mm)
            {
                Tmp2.value[mm] = new double[Tmp2.cols];
                for (int j = 0; j < Tmp2.cols; ++j)
                {
                    Tmp2.value[mm][j] = 0.0;
                }
            }
            R.Vt = Tmp2;

            nsig = ritvec(n, A, R, kappa, ritz, bnd, wptr[6], wptr[9], wptr[5], steps, neig);

            // This swaps and transposes the singular matrices if A was transposed.
            if (transpose)
            {
                DMat T;
                T = R.Ut;
                R.Ut = R.Vt;
                R.Vt = T;
            }
            return R;
        }
Ejemplo n.º 3
0
        private static int ritvec(int n, SMat A, SVDRec R, double kappa, double[] ritz, double[] bnd,
            double[] alf, double[] bet, double[] w2, int steps, int neig)
        {
            int js, jsq, i, k, id2, tmp, nsig = 0, x;
            double tmp0, tmp1, xnorm;
            double[] s;
            double[] xv2;
            double[] w1 = R.Vt.value[0];

            js = steps + 1;
            jsq = js * js;

            s = new double[jsq];
            for (k = 0; k < jsq; ++k) s[k] = 0.0;
            xv2 = new double[n];

            for (i = 0; i < jsq; i += (js + 1)) s[i] = 1.0;
            svd_dcopy(js, alf, 0, 1, w1, 0, -1);
            svd_dcopy(steps, bet, 1, 1, w2, 1, -1);

            imtql2(js, js, w1, w2, s);
            if (ierr != 0) return 0;

            nsig = 0;
            x = 0;
            id2 = jsq - js;
            for (k = 0; k < js; k++)
            {
                tmp = id2;
                if (bnd[k] <= kappa * Math.Abs(ritz[k]) && k > js - neig - 1)
                {
                    if (--x < 0) x = R.d - 1;
                    w1 = R.Vt.value[x];
                    for (i = 0; i < n; i++) w1[i] = 0.0;
                    for (i = 0; i < js; i++)
                    {
                        store(n, (int)(storeVals.RETRQ), i, w2);
                        svd_daxpy(n, s[tmp], w2, 1, w1, 1);
                        tmp -= js;
                    }
                    nsig++;
                }
                id2++;
            }

            // x is now the location of the highest singular value.
            rotateArray(R, x);
            R.d = svd_imin(R.d, nsig);
            for (x = 0; x < R.d; x++)
            {
                svd_opb(A, R.Vt.value[x], xv2, OPBTemp);
                tmp0 = svd_ddot(n, R.Vt.value[x], 1, xv2, 1);
                svd_daxpy(n, -tmp0, R.Vt.value[x], 1, xv2, 1);
                tmp0 = Math.Sqrt(tmp0);
                xnorm = Math.Sqrt(svd_ddot(n, xv2, 1, xv2, 1));

                svd_opa(A, R.Vt.value[x], R.Ut.value[x]);
                tmp1 = 1.0 / tmp0;
                svd_dscal(A.rows, tmp1, R.Ut.value[x], 1);
                xnorm *= tmp1;
                bnd[i] = xnorm;
                R.S[x] = tmp0;
            }
            return nsig;
        }