Пример #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
        // [L,U,pinv]=lu(A, [q lnz unz]). lnz and unz can be guess
        static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S, double tol)
        {
            int i, n = A.n;

            int[] q = S.q;

            int lnz = S.lnz;
            int unz = S.unz;

            int[] pinv;

            NumericFactorization N = new NumericFactorization(); // allocate result

            SparseMatrix L, U;

            N.L    = L = new SparseMatrix(n, n, lnz, true); // allocate result L
            N.U    = U = new SparseMatrix(n, n, unz, true); // allocate result U
            N.pinv = pinv = new int[n];                     // allocate result pinv

            double[] x  = new double[n];                    // get double workspace
            int[]    xi = new int[2 * n];                   // get int workspace

            for (i = 0; i < n; i++)
            {
                pinv[i] = -1; // no rows pivotal yet
            }

            lnz = unz = 0;

            int    ipiv, top, p, col;
            double pivot, a, t;

            int[]    Li, Ui, Lp = L.p, Up = U.p;
            double[] Lx, Ux;

            for (int k = 0; k < n; k++) // compute L(:,k) and U(:,k)
            {
                // Triangular solve
                Lp[k] = lnz; // L(:,k) starts here
                Up[k] = unz; // U(:,k) starts here
                if ((lnz + n > L.nzmax && !L.Resize(2 * L.nzmax + n)) ||
                    (unz + n > U.nzmax && !U.Resize(2 * U.nzmax + n)))
                {
                    return(null);
                }
                Li  = L.i;
                Lx  = L.x;
                Ui  = U.i;
                Ux  = U.x;
                col = q != null ? (q[k]) : k;
                top = Triangular.SolveSp(L, A, col, xi, x, pinv, true);  // x = L\A(:,col)

                // Find pivot
                ipiv = -1;
                a    = -1;
                for (p = top; p < n; p++)
                {
                    i = xi[p];       // x(i) is nonzero
                    if (pinv[i] < 0) // row i is not yet pivotal
                    {
                        if ((t = Math.Abs(x[i])) > a)
                        {
                            a    = t; // largest pivot candidate so far
                            ipiv = i;
                        }
                    }
                    else // x(i) is the entry U(pinv[i],k)
                    {
                        Ui[unz]   = pinv[i];
                        Ux[unz++] = x[i];
                    }
                }
                if (ipiv == -1 || a <= 0)
                {
                    return(null);
                }

                if (pinv[col] < 0 && Math.Abs(x[col]) >= a * tol)
                {
                    ipiv = col;
                }

                // Divide by pivot
                pivot      = x[ipiv];     // the chosen pivot
                Ui[unz]    = k;           // last entry in U(:,k) is U(k,k)
                Ux[unz++]  = pivot;
                pinv[ipiv] = k;           // ipiv is the kth pivot row
                Li[lnz]    = ipiv;        // first entry in L(:,k) is L(k,k) = 1
                Lx[lnz++]  = 1;
                for (p = top; p < n; p++) // L(k+1:n,k) = x / pivot
                {
                    i = xi[p];
                    if (pinv[i] < 0)              // x(i) is an entry in L(:,k)
                    {
                        Li[lnz]   = i;            // save unpermuted row in L
                        Lx[lnz++] = x[i] / pivot; // scale pivot column
                    }
                    x[i] = 0;                     // x [0..n-1] = 0 for next k
                }
            }

            // Finalize L and U
            Lp[n] = lnz;
            Up[n] = unz;
            Li    = L.i; // fix row indices of L for final pinv
            for (p = 0; p < lnz; p++)
            {
                Li[p] = pinv[Li[p]];
            }
            L.Resize(0); // remove extra space from L and U
            U.Resize(0);

            return(N); // success
        }
Пример #4
0
        /// <summary>
        /// Sparse matrix multiplication, C = A*B
        /// </summary>
        /// <param name="other">column-compressed matrix</param>
        /// <returns>C = A*B, null on error</returns>
        public override CompressedColumnStorage <double> Multiply(CompressedColumnStorage <double> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            int p, j, nz = 0;

            int[]    cp, ci;
            double[] cx;

            int m = this.rowCount;
            int n = other.ColumnCount;

            int anz = this.NonZerosCount;
            int bnz = other.NonZerosCount;

            if (this.ColumnCount != other.RowCount)
            {
                throw new ArgumentException(Resources.MatrixDimensions);
            }

            if ((m > 0 && this.ColumnCount == 0) || (other.RowCount == 0 && n > 0))
            {
                throw new Exception(Resources.InvalidDimensions);
            }

            var bp = other.ColumnPointers;
            var bi = other.RowIndices;
            var bx = other.Values;

            // Workspace
            var w = new int[m];
            var x = new double[m];

            var result = new SparseMatrix(m, n, anz + bnz);

            cp = result.ColumnPointers;
            for (j = 0; j < n; j++)
            {
                if (nz + m > result.Values.Length)
                {
                    // Might throw out of memory exception.
                    result.Resize(2 * (result.Values.Length) + m);
                }
                ci    = result.RowIndices;
                cx    = result.Values; // 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 = this.Scatter(bi[p], bx[p], w, x, j + 1, result, nz);
                }

                for (p = cp[j]; p < nz; p++)
                {
                    cx[p] = x[ci[p]];
                }
            }
            cp[n] = nz;       // finalize the last column of C
            result.Resize(0); // remove extra space from C
            result.SortIndices();

            return(result); // success
        }