예제 #1
0
        /// <summary>
        /// Sparse matrix multiplication, C = A*B
        /// </summary>
        /// <param name="A">column-compressed matrix</param>
        /// <param name="B">column-compressed matrix</param>
        /// <returns>C = A*B, null on error</returns>
        public static SparseMatrix Multiply(SparseMatrix A, SparseMatrix B)
        {
            int  p, j, nz = 0, anz, m, n, bnz;
            bool values;

            int[]    Cp, Ci, Bp, w, Bi;
            double[] x, Bx, Cx;

            // check inputs
            if (A == null || B == null)
            {
                return(null);
            }
            if (A.n != B.m)
            {
                return(null);
            }

            m   = A.m;
            anz = A.p[A.n];
            n   = B.n;
            Bp  = B.p;
            Bi  = B.i;
            Bx  = B.x;
            bnz = Bp[n];

            w      = new int[m];                                        // get workspace
            values = (A.x != null) && (Bx != null);
            x      = values ? new double[m] : null;                     // get workspace

            SparseMatrix C = new SparseMatrix(m, n, anz + bnz, values); // allocate result

            Cp = C.p;
            for (j = 0; j < n; j++)
            {
                if (nz + m > C.nzmax && !C.Resize(2 * (C.nzmax) + m))
                {
                    return(null);      // out of memory
                }
                Ci    = C.i; Cx = C.x; // C.i and C.x may be reallocated
                Cp[j] = nz;            // column j of C starts here
                for (p = Bp[j]; p < Bp[j + 1]; p++)
                {
                    nz = A.Scatter(Bi[p], Bx != null ? Bx[p] : 1, w, x, j + 1, C, nz);
                }
                if (values)
                {
                    for (p = Cp[j]; p < nz; p++)
                    {
                        Cx[p] = x[Ci[p]];
                    }
                }
            }
            Cp[n] = nz;  // finalize the last column of C
            C.Resize(0); // remove extra space from C

            return(C);   // success
        }
예제 #2
0
        /// <summary>
        /// C = alpha*A + beta*B
        /// </summary>
        /// <param name="A">column-compressed matrix</param>
        /// <param name="B">column-compressed matrix</param>
        /// <param name="alpha">scalar alpha</param>
        /// <param name="beta">scalar beta</param>
        /// <returns>C=alpha*A + beta*B, null on error</returns>
        public static SparseMatrix Add(SparseMatrix A, SparseMatrix B, double alpha = 1.0, double beta = 1.0)
        {
            int p, j, nz = 0, anz, m, n, bnz;

            int[] Cp, Ci, Bp, w;
            bool  values;

            double[] x, Bx, Cx;

            // check inputs
            if (A == null || B == null)
            {
                return(null);
            }
            if (A.m != B.m || A.n != B.n)
            {
                return(null);
            }

            m   = A.m;
            anz = A.p[A.n];
            n   = B.n;
            Bp  = B.p;
            Bx  = B.x;
            bnz = Bp[n];

            w      = new int[m];                                        // get workspace
            values = (A.x != null) && (Bx != null);
            x      = values ? new double[m] : null;                     // get workspace

            SparseMatrix C = new SparseMatrix(m, n, anz + bnz, values); // allocate result

            Cp = C.p; Ci = C.i; Cx = C.x;
            for (j = 0; j < n; j++)
            {
                Cp[j] = nz;                                      // column j of C starts here
                nz    = A.Scatter(j, alpha, w, x, j + 1, C, nz); // alpha*A(:,j)
                nz    = B.Scatter(j, beta, w, x, j + 1, C, nz);  // beta*B(:,j)
                if (values)
                {
                    for (p = Cp[j]; p < nz; p++)
                    {
                        Cx[p] = x[Ci[p]];
                    }
                }
            }
            Cp[n] = nz;  // finalize the last column of C
            C.Resize(0); // remove extra space from C

            return(C);   // success
        }
예제 #3
0
        /// <summary>
        /// Sparse QR factorization [V,beta,pinv,R] = qr (A)
        /// </summary>
        static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S)
        {
            double[] Beta;
            int      i, p, p1, top, len, col;

            int m = A.m;
            int n = A.n;

            int[]    Ap = A.p;
            int[]    Ai = A.i;
            double[] Ax = A.x;

            int[] q      = S.q;
            int[] parent = S.parent;
            int[] pinv   = S.pinv;
            int   m2     = S.m2;

            int vnz = S.lnz;
            int rnz = S.unz;

            int[] leftmost = S.leftmost;

            int[]    w = new int[m2 + n]; // get int workspace
            double[] x = new double[m2];  // get double workspace

            int s = m2;                   // offset into w

            SparseMatrix         R, V;
            NumericFactorization N = new NumericFactorization(); // allocate result

            N.L = V = new SparseMatrix(m2, n, vnz, true);        // allocate result V
            N.U = R = new SparseMatrix(m2, n, rnz, true);        // allocate result R
            N.B = Beta = new double[n];                          // allocate result Beta

            int[]    Rp = R.p;
            int[]    Ri = R.i;
            double[] Rx = R.x;

            int[]    Vp = V.p;
            int[]    Vi = V.i;
            double[] Vx = V.x;

            for (i = 0; i < m2; i++)
            {
                w[i] = -1; // clear w, to mark nodes
            }

            rnz = 0; vnz = 0;
            for (int k = 0; k < n; k++) // compute V and R
            {
                Rp[k]     = rnz;        // R(:,k) starts here
                Vp[k]     = p1 = vnz;   // V(:,k) starts here
                w[k]      = k;          // add V(k,k) to pattern of V
                Vi[vnz++] = k;
                top       = n;
                col       = q != null ? q[k] : k;
                for (p = Ap[col]; p < Ap[col + 1]; p++)     // find R(:,k) pattern
                {
                    i = leftmost[Ai[p]];                    // i = min(find(A(i,q)))
                    for (len = 0; w[i] != k; i = parent[i]) // traverse up to k
                    {
                        //len++;
                        w[s + len++] = i;
                        w[i]         = k;
                    }
                    while (len > 0)
                    {
                        --top;
                        --len;
                        w[s + top] = w[s + len]; // push path on stack
                    }
                    i    = pinv[Ai[p]];          // i = permuted row of A(:,col)
                    x[i] = Ax[p];                // x (i) = A(:,col)
                    if (i > k && w[i] < k)       // pattern of V(:,k) = x (k+1:m)
                    {
                        Vi[vnz++] = i;           // add i to pattern of V(:,k)
                        w[i]      = k;
                    }
                }
                for (p = top; p < n; p++)               // for each i in pattern of R(:,k)
                {
                    i = w[s + p];                       // R(i,k) is nonzero
                    ApplyHouseholder(V, i, Beta[i], x); // apply (V(i),Beta(i)) to x
                    Ri[rnz]   = i;                      // R(i,k) = x(i)
                    Rx[rnz++] = x[i];
                    x[i]      = 0;
                    if (parent[i] == k)
                    {
                        vnz = V.Scatter(i, 0, w, null, k, V, vnz);
                    }
                }
                for (p = p1; p < vnz; p++) // gather V(:,k) = x
                {
                    Vx[p]    = x[Vi[p]];
                    x[Vi[p]] = 0;
                }
                Ri[rnz]   = k;                                                // R(k,k) = norm (x)
                Rx[rnz++] = CreateHouseholder(Vx, p1, ref Beta[k], vnz - p1); // [v,beta]=house(x)
            }
            Rp[n] = rnz;                                                      // finalize R
            Vp[n] = vnz;                                                      // finalize V

            return(N);                                                        // success
        }