示例#1
0
文件: SVD.cs 项目: kamilciesla/svd
        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;
        }
示例#2
0
文件: SVD.cs 项目: kamilciesla/svd
        private static double startv(SMat A, double[][] wptr, int step, int n)
        {
            double rnm2, t;
            double[] r;
            int irand = 0, id, i;

            rnm2 = svd_ddot(n, wptr[0], 1, wptr[0], 1);
            irand = 918273 + step;
            r = wptr[0];
            for (id = 0; id < 3; id++)
            {
                if (id > 0 || step > 0 || rnm2 == 0)
                {
                    for (i = 0; i < n; i++)
                    {
                        r[i] = svd_random2(ref irand);
                    }
                }
                svd_dcopy(n, wptr[0], 0, 1, wptr[3], 0, 1);
                svd_opb(A, wptr[3], wptr[0], OPBTemp);
                svd_dcopy(n, wptr[0], 0, 1, wptr[3], 0, 1);
                rnm2 = svd_ddot(n, wptr[0], 1, wptr[3], 1);
                if (rnm2 > 0.0) break;
            }

            // fatal error
            if (rnm2 <= 0.0)
            {
                ierr = 8192;
                return (-1);
            }

            if (step > 0)
            {
                for (i = 0; i < step; i++)
                {
                    store(n, (int)storeVals.RETRQ, i, wptr[5]);
                    t = -svd_ddot(n, wptr[3], 1, wptr[5], 1);
                    svd_daxpy(n, t, wptr[5], 1, wptr[0], 1);
                }

                t = svd_ddot(n, wptr[4], 1, wptr[0], 1);
                svd_daxpy(n, -t, wptr[2], 1, wptr[0], 1);
                svd_dcopy(n, wptr[0], 0, 1, wptr[3], 0, 1);
                t = svd_ddot(n, wptr[3], 1, wptr[0], 1);
                if (t <= eps * rnm2) t = 0.0;
                rnm2 = t;
            }
            return Math.Sqrt(rnm2);
        }
示例#3
0
文件: SVD.cs 项目: kamilciesla/svd
        private static void stpone(SMat A, double[][] wrkptr, ref double rnmp, ref double tolp, int n)
        {
            double t, rnm, anorm;
            double[] alf;
            alf = wrkptr[6];

            rnm = startv(A, wrkptr, 0, n);
            if (rnm == 0.0 || ierr != 0) return;

            t = 1.0 / rnm;
            svd_datx(n, t, wrkptr[0], 1, wrkptr[1], 1);
            svd_dscal(n, t, wrkptr[3], 1);

            svd_opb(A, wrkptr[3], wrkptr[0], OPBTemp);
            alf[0] = svd_ddot(n, wrkptr[0], 1, wrkptr[3], 1);
            svd_daxpy(n, -alf[0], wrkptr[1], 1, wrkptr[0], 1);
            t = svd_ddot(n, wrkptr[0], 1, wrkptr[3], 1);
            svd_daxpy(n, -t, wrkptr[1], 1, wrkptr[0], 1);
            alf[0] += t;
            svd_dcopy(n, wrkptr[0], 0, 1, wrkptr[4], 0, 1);
            rnm = Math.Sqrt(svd_ddot(n, wrkptr[0], 1, wrkptr[4], 1));
            anorm = rnm + Math.Abs(alf[0]);
            rnmp = rnm;
            tolp = reps * anorm;
        }
示例#4
0
文件: SVD.cs 项目: kamilciesla/svd
        private static int lanso(SMat A, int iterations, int dimensions, double endl, double endr,
            double[] ritz, double[] bnd, double[][] wptr, ref int neigp, int n)
        {
            double[] alf, eta, oldeta, bet, wrk;
            double rnm, tol;
            int ll, first, last, id2, id3, i, l, neig = 0, j = 0, intro = 0;

            alf = wptr[6];
            eta = wptr[7];
            oldeta = wptr[8];
            bet = wptr[9];
            wrk = wptr[5];

            rnm = 0.0;
            tol = 0.0;
            stpone(A, wptr, ref rnm, ref tol, n);

            if (rnm == 0.0 || ierr != 0) return 0;
            eta[0] = eps1;
            oldeta[0] = eps1;
            ll = 0;
            first = 1;
            last = svd_imin(dimensions + svd_imax(8, dimensions), iterations);
            int ENOUGH = 0;
            while (ENOUGH == 0)
            {
                if (rnm <= tol) rnm = 0.0;
                j = lanczos_step(A, first, last, wptr, alf, eta, oldeta, bet, ref ll, ref ENOUGH, ref rnm, ref tol, n);

                if (ENOUGH > 0) j = j - 1;
                else j = last - 1;
                first = j + 1;
                bet[j + 1] = rnm;

                l = 0;
                for (id2 = 0; id2 < j; id2++)
                {
                    if (l > j) break;
                    for (i = l; i <= j; i++) if (bet[i + 1] == 0.0) break;
                    if (i > j) i = j;

                    svd_dcopy(i - l + 1, alf, l, 1, ritz, l, -1);
                    svd_dcopy(i - l, bet, l + 1, 1, wrk, l + 1, -1);
                    imtqlb(i - l + 1, ritz, wrk, bnd);

                    if (ierr != 0)
                    {
                        Console.WriteLine("svdLAS2: imtqlb failed to converge {0}", ierr);
                    }
                    for (id3 = l; id3 <= i; id3++)
                    {
                        bnd[id3] = rnm * Math.Abs(bnd[id3]);
                    }
                    l = i + 1;
                }

                svd_dsort2((j + 1) / 2, j + 1, ritz, bnd);

                neig = error_bound(ref ENOUGH, endl, endr, ritz, bnd, j, tol);
                neigp = neig;

                if (neig < dimensions)
                {
                    if (neig == 0)
                    {
                        last = first + 9;
                        intro = first;
                    }
                    else
                    {
                        last = first + svd_imax(3, 1 + ((j - intro) * (dimensions - neig)) / neig);
                    }
                    last = svd_imin(last, iterations);
                }
                else
                {
                    ENOUGH = 1;
                }
                int RES = 0;
                if (first >= iterations) RES = 1;
                ENOUGH = ENOUGH | RES;
            }
            store(n, (int)(storeVals.STORQ), j, wptr[1]);
            return j;
        }
示例#5
0
文件: SVD.cs 项目: kamilciesla/svd
        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;
        }
示例#6
0
文件: SVD.cs 项目: kamilciesla/svd
        private static void svd_opb(SMat A, double[] x, double[] y, double[] temp)
        {
            int i, j, end;
            int[] pointr = A.pointr;
            int[] rowind = A.rowind;

            double[] value = A.value;
            int n = A.cols;

            SVDCount[(int)(svdCounters.SVD_MXV)] += 2;
            for (i = 0; i < n; ++i) y[i] = 0.0;
            for (i = 0; i < A.rows; i++) temp[i] = 0.0;

            for (i = 0; i < A.cols; i++)
            {
                end = pointr[i + 1];
                for (j = pointr[i]; j < end; j++)
                {
                    temp[rowind[j]] += value[j] * x[i];
                }
            }

            for (i = 0; i < A.cols; i++)
            {
                end = pointr[i + 1];
                for (j = pointr[i]; j < end; j++)
                {
                    y[i] += value[j] * temp[rowind[j]];
                }
            }
        }
示例#7
0
文件: SVD.cs 项目: kamilciesla/svd
        private static int lanczos_step(SMat A, int first, int last, double[][] wptr, double[] alf, double[] eta,
            double[] oldeta, double[] bet, ref int ll, ref int enough, ref double rnmp, ref double tolp, int n)
        {
            double t, anorm;
            double[] mid;
            double rnm = rnmp;
            double tol = tolp;
            int i, j;
            for (j = first; j < last; j++)
            {
                mid = wptr[2];
                wptr[2] = wptr[1];
                wptr[1] = mid;
                mid = wptr[3];
                wptr[3] = wptr[4];
                wptr[4] = mid;

                store(n, (int)(storeVals.STORQ), j - 1, wptr[2]);
                if (j - 1 < MAXLL) store(n, (int)(storeVals.STORP), j - 1, wptr[4]);
                bet[j] = rnm;

                if (bet[j] == 0.0)
                {
                    rnm = startv(A, wptr, j, n);
                    if (rnm < 0.0)
                    {
                        Console.WriteLine("Fatal error: {0}", ierr);
                        Environment.Exit(1);
                    }
                    if (ierr != 0) return j;
                    if (rnm == 0.0) enough = 1;
                }

                if (enough == 1)
                {
                    mid = wptr[2];
                    wptr[2] = wptr[1];
                    wptr[1] = mid;
                    break;
                }

                t = 1.0 / rnm;
                svd_datx(n, t, wptr[0], 1, wptr[1], 1);
                svd_dscal(n, t, wptr[3], 1);
                svd_opb(A, wptr[3], wptr[0], OPBTemp);
                svd_daxpy(n, -rnm, wptr[2], 1, wptr[0], 1);
                alf[j] = svd_ddot(n, wptr[0], 1, wptr[3], 1);
                svd_daxpy(n, -alf[j], wptr[1], 1, wptr[0], 1);

                if (j <= MAXLL && (Math.Abs(alf[j - 1]) > 4.0 * Math.Abs(alf[j])))
                {
                    ll = j;
                }
                for (i = 0; i < svd_imin(ll, j - 1); i++)
                {
                    store(n, (int)(storeVals.RETRP), i, wptr[5]);
                    t = svd_ddot(n, wptr[5], 1, wptr[0], 1);
                    store(n, (int)(storeVals.RETRQ), i, wptr[5]);
                    svd_daxpy(n, -t, wptr[5], 1, wptr[0], 1);
                    eta[i] = eps1;
                    oldeta[i] = eps1;
                }

                t = svd_ddot(n, wptr[0], 1, wptr[4], 1);
                svd_daxpy(n, -t, wptr[2], 1, wptr[0], 1);
                if (bet[j] > 0.0) bet[j] = bet[j] + t;
                t = svd_ddot(n, wptr[0], 1, wptr[3], 1);
                svd_daxpy(n, -t, wptr[1], 1, wptr[0], 1);
                alf[j] = alf[j] + t;
                svd_dcopy(n, wptr[0], 0, 1, wptr[4], 0, 1);
                rnm = Math.Sqrt(svd_ddot(n, wptr[0], 1, wptr[4], 1));
                anorm = bet[j] + Math.Abs(alf[j]) + rnm;
                tol = reps * anorm;

                ortbnd(alf, eta, oldeta, bet, j, rnm);

                purge(n, ll, wptr[0], wptr[1], wptr[4], wptr[3], wptr[5], eta, oldeta, j, rnmp, tol);
                if (rnm <= tol) rnm = 0.0;
            }
            rnmp = rnm;
            tolp = tol;
            return j;
        }
示例#8
0
文件: SVD.cs 项目: kamilciesla/svd
        private static void svd_opa(SMat A, double[] x, double[] y)
        {
            int end, i, j;
            int[] pointr = A.pointr;
            int[] rowind = A.rowind;
            double[] value = A.value;

            SVDCount[(int)(svdCounters.SVD_MXV)]++;
            for (int k = 0; k < A.rows; ++k)
            {
                y[k] = 0.0;
            }

            for (i = 0; i < A.cols; i++)
            {
                end = pointr[i + 1];
                for (j = pointr[i]; j < end; j++)
                {
                    y[rowind[j]] += value[j] * x[i];
                }
            }
        }
示例#9
0
文件: SVD.cs 项目: kamilciesla/svd
 private static int check_parameters(SMat A, int dimensions, int iterations, double endl, double endr)
 {
     int error_index;
     error_index = 0;
     if (endl > endr) error_index = 2;
     else if (dimensions > iterations) error_index = 3;
     else if (A.cols <= 0 || A.rows <= 0) error_index = 4;
     else if (iterations <= 0 || iterations > A.cols || iterations > A.rows) error_index = 5;
     else if (dimensions <= 0 || dimensions > iterations) error_index = 6;
     if (error_index > 0) Console.WriteLine("svdLAS2 parameter error: %s\n");
     return error_index;
 }
示例#10
0
文件: SVD.cs 项目: kamilciesla/svd
 private static SMat svdTransposeS(SMat S)
 {
     int r, c, i, j;
     SMat N = svdNewSMat(S.cols, S.rows, S.vals);
     for (i = 0; i < S.vals; i++) N.pointr[S.rowind[i]]++;
     N.pointr[S.rows] = S.vals - N.pointr[S.rows - 1];
     for (r = S.rows - 1; r > 0; r--) N.pointr[r] = N.pointr[r + 1] - N.pointr[r - 1];
     N.pointr[0] = 0;
     for (c = 0, i = 0; c < S.cols; c++)
     {
         for (; i < S.pointr[c + 1]; i++)
         {
             r = S.rowind[i];
             j = N.pointr[r + 1]++;
             N.rowind[j] = c;
             N.value[j] = S.value[i];
         }
     }
     return N;
 }
示例#11
0
文件: SVD.cs 项目: kamilciesla/svd
 private static SMat svdNewSMat(int rows, int cols, int vals)
 {
     SMat S = new SMat();
     S.rows = rows;
     S.cols = cols;
     S.vals = vals;
     S.pointr = new int[cols + 1];
     S.rowind = new int[vals];
     S.value = new double[vals];
     return S;
 }
示例#12
0
文件: SVD.cs 项目: kamilciesla/svd
 // Functions for reading-writing data
 private static SMat svdLoadSparseMatrix(string datafile)
 {
     try
     {
         SMat S = new SMat();
         using (FileStream stream = new FileStream(datafile, FileMode.Open))
         {
             using (BinaryReader reader = new BinaryReader(stream))
             {
                 S.rows = System.Net.IPAddress.NetworkToHostOrder(reader.ReadInt32());
                 S.cols = System.Net.IPAddress.NetworkToHostOrder(reader.ReadInt32());
                 S.vals = System.Net.IPAddress.NetworkToHostOrder(reader.ReadInt32());
                 S.pointr = new int[S.cols + 1];
                 for (int k = 0; k < S.cols + 1; ++k) S.pointr[k] = 0;
                 S.rowind = new int[S.vals];
                 S.value = new double[S.vals];
                 for (int c = 0, v = 0; c < S.cols; c++)
                 {
                     int n = System.Net.IPAddress.NetworkToHostOrder(reader.ReadInt32());
                     S.pointr[c] = v;
                     for (int i = 0; i < n; i++, v++)
                     {
                         int r = System.Net.IPAddress.NetworkToHostOrder(reader.ReadInt32());
                         int nBuf = System.Net.IPAddress.NetworkToHostOrder(reader.ReadInt32());
                         byte[] b = BitConverter.GetBytes(nBuf);
                         float f = BitConverter.ToSingle(b, 0);
                         S.rowind[v] = r;
                         S.value[v] = f;
                     }
                     S.pointr[S.cols] = S.vals;
                 }
                 reader.Close();
             }
             stream.Close();
         }
         return S;
     }
     catch (Exception e)
     {
         Console.WriteLine(e.Message);
         return null;
     }
 }