Пример #1
0
        /**
         * Performs matrix addition:<br>
         * C = &alpha;A + &beta;B
         *
         * @param alpha scalar value multiplied against A
         * @param A Matrix
         * @param beta scalar value multiplied against B
         * @param B Matrix
         * @param C Output matrix.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         * @param gx (Optional) Storage for internal workspace.  Can be null.
         */
        public static void add(double alpha, DMatrixSparseCSC A, double beta, DMatrixSparseCSC B, DMatrixSparseCSC C,
                               IGrowArray gw, DGrowArray gx)
        {
            double[] x = TriangularSolver_DSCC.adjust(gx, A.numRows);
            int[]    w = TriangularSolver_DSCC.adjust(gw, A.numRows, A.numRows);

            C.indicesSorted = false;
            C.nz_length     = 0;

            for (int col = 0; col < A.numCols; col++)
            {
                C.col_idx[col] = C.nz_length;

                ImplSparseSparseMult_DSCC.multAddColA(A, col, alpha, C, col + 1, x, w);
                ImplSparseSparseMult_DSCC.multAddColA(B, col, beta, C, col + 1, x, w);

                // take the values in the dense vector 'x' and put them into 'C'
                int idxC0 = C.col_idx[col];
                int idxC1 = C.col_idx[col + 1];

                for (int i = idxC0; i < idxC1; i++)
                {
                    C.nz_values[i] = x[C.nz_rows[i]];
                }
            }
        }
        /**
         * Performs matrix multiplication.  C = A*B<sup>T</sup></sup>
         *
         * @param A Matrix
         * @param B Matrix
         * @param C Storage for results.  Data length is increased if increased if insufficient.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         * @param gx (Optional) Storage for internal workspace.  Can be null.
         */
        public static void multTransB(DMatrixSparseCSC A, DMatrixSparseCSC B, DMatrixSparseCSC C,
                                      IGrowArray gw, DGrowArray gx)
        {
            if (!B.isIndicesSorted())
            {
                throw new ArgumentException("B must have its indices sorted.");
            }
            else if (!CommonOps_DSCC.checkIndicesSorted(B))
            {
                throw new ArgumentException("Crap. Not really sorted");
            }

            double[] x = TriangularSolver_DSCC.adjust(gx, A.numRows);
            int[]    w = TriangularSolver_DSCC.adjust(gw, A.numRows + B.numCols, A.numRows);

            C.growMaxLength(A.nz_length + B.nz_length, false);
            C.indicesSorted = false;
            C.nz_length     = 0;
            C.col_idx[0]    = 0;

            // initialize w is the first index in each column of B
            int locationB = A.numRows;

            Array.Copy(B.col_idx, 0, w, locationB, B.numCols);

            for (int colC = 0; colC < B.numRows; colC++)
            {
                C.col_idx[colC + 1] = C.nz_length; // needs a value of B has nothing in the row

                // find the column in the transposed B
                int mark = colC + 1;
                for (int colB = 0; colB < B.numCols; colB++)
                {
                    int bi = w[locationB + colB];
                    if (bi < B.col_idx[colB + 1])
                    {
                        int row = B.nz_rows[bi];
                        if (row == colC)
                        {
                            multAddColA(A, colB, B.nz_values[bi], C, mark, x, w);
                            w[locationB + colB]++;
                        }
                    }
                }

                // take the values in the dense vector 'x' and put them into 'C'
                int idxC0 = C.col_idx[colC];
                int idxC1 = C.col_idx[colC + 1];

                for (int i = idxC0; i < idxC1; i++)
                {
                    C.nz_values[i] = x[C.nz_rows[i]];
                }
            }
        }
Пример #3
0
        /**
         * Performs element-wise multiplication:<br>
         * C_ij = A_ij * B_ij
         *
         * @param A (Input) Matrix
         * @param B (Input) Matrix
         * @param C (Output) matrix.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         * @param gx (Optional) Storage for internal workspace.  Can be null.
         */
        public static void elementMult(DMatrixSparseCSC A, DMatrixSparseCSC B, DMatrixSparseCSC C,
                                       IGrowArray gw, DGrowArray gx)
        {
            double[] x = TriangularSolver_DSCC.adjust(gx, A.numRows);
            int[]    w = TriangularSolver_DSCC.adjust(gw, A.numRows);

            //Arrays.fill(w, 0, A.numRows, -1); // fill with -1. This will be a value less than column
            for (var i = 0; i < A.numRows; i++)
            {
                w[i] = -1;
            }

            C.indicesSorted = false; // Hmm I think if B is storted then C will be sorted...
            C.nz_length     = 0;

            for (int col = 0; col < A.numCols; col++)
            {
                int idxA0 = A.col_idx[col];
                int idxA1 = A.col_idx[col + 1];
                int idxB0 = B.col_idx[col];
                int idxB1 = B.col_idx[col + 1];

                // compute the maximum number of elements that there can be in this row
                int maxInRow = Math.Min(idxA1 - idxA0, idxB1 - idxB0);

                // make sure there are enough non-zero elements in C
                if (C.nz_length + maxInRow > C.nz_values.Length)
                {
                    C.growMaxLength(C.nz_values.Length + maxInRow, true);
                }

                // update the structure of C
                C.col_idx[col] = C.nz_length;

                // mark the rows that appear in A and save their value
                for (int i = idxA0; i < idxA1; i++)
                {
                    int row = A.nz_rows[i];
                    w[row] = col;
                    x[row] = A.nz_values[i];
                }

                // If a row appears in A and B, multiply and set as an element in C
                for (int i = idxB0; i < idxB1; i++)
                {
                    int row = B.nz_rows[i];
                    if (w[row] == col)
                    {
                        C.nz_values[C.nz_length] = x[row] * B.nz_values[i];
                        C.nz_rows[C.nz_length++] = row;
                    }
                }
            }
            C.col_idx[C.numCols] = C.nz_length;
        }
Пример #4
0
        /**
         * Adds the results of adding a column in A and B as a new column in C.<br>
         * C(:,end+1) = &alpha;*A(:,colA) + &beta;*B(:,colB)
         *
         * @param alpha scalar
         * @param A matrix
         * @param colA column in A
         * @param beta scalar
         * @param B matrix
         * @param colB column in B
         * @param C Column in C
         * @param gw workspace
         */
        public static void addColAppend(double alpha, DMatrixSparseCSC A, int colA, double beta, DMatrixSparseCSC B,
                                        int colB,
                                        DMatrixSparseCSC C, IGrowArray gw)
        {
            if (A.numRows != B.numRows || A.numRows != C.numRows)
            {
                throw new ArgumentException("Number of rows in A, B, and C do not match");
            }

            int idxA0 = A.col_idx[colA];
            int idxA1 = A.col_idx[colA + 1];
            int idxB0 = B.col_idx[colB];
            int idxB1 = B.col_idx[colB + 1];

            C.growMaxColumns(++C.numCols, true);
            C.growMaxLength(C.nz_length + idxA1 - idxA0 + idxB1 - idxB0, true);

            int[] w = TriangularSolver_DSCC.adjust(gw, A.numRows);
            //Arrays.fill(w, 0, A.numRows, -1);
            for (var i = 0; i < A.numRows; i++)
            {
                w[i] = -1;
            }

            for (int i = idxA0; i < idxA1; i++)
            {
                int row = A.nz_rows[i];
                C.nz_rows[C.nz_length]   = row;
                C.nz_values[C.nz_length] = alpha * A.nz_values[i];
                w[row] = C.nz_length++;
            }

            for (int i = idxB0; i < idxB1; i++)
            {
                int row = B.nz_rows[i];
                if (w[row] != -1)
                {
                    C.nz_values[w[row]] += beta * B.nz_values[i];
                }
                else
                {
                    C.nz_values[C.nz_length] = beta * B.nz_values[i];
                    C.nz_rows[C.nz_length++] = row;
                }
            }
            C.col_idx[C.numCols] = C.nz_length;
        }
        /**
         * Performs matrix multiplication.  C = A*B
         *
         * @param A Matrix
         * @param B Matrix
         * @param C Storage for results.  Data length is increased if increased if insufficient.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         * @param gx (Optional) Storage for internal workspace.  Can be null.
         */
        public static void mult(DMatrixSparseCSC A, DMatrixSparseCSC B, DMatrixSparseCSC C,
                                IGrowArray gw, DGrowArray gx)
        {
            double[] x = TriangularSolver_DSCC.adjust(gx, A.numRows);
            int[]    w = TriangularSolver_DSCC.adjust(gw, A.numRows, A.numRows);

            C.growMaxLength(A.nz_length + B.nz_length, false);
            C.indicesSorted = false;
            C.nz_length     = 0;

            // C(i,j) = sum_k A(i,k) * B(k,j)
            int idx0 = B.col_idx[0];

            for (int bj = 1; bj <= B.numCols; bj++)
            {
                int colB = bj - 1;
                int idx1 = B.col_idx[bj];
                C.col_idx[bj] = C.nz_length;

                if (idx0 == idx1)
                {
                    continue;
                }

                // C(:,j) = sum_k A(:,k)*B(k,j)
                for (int bi = idx0; bi < idx1; bi++)
                {
                    int    rowB = B.nz_rows[bi];
                    double valB = B.nz_values[bi]; // B(k,j)  k=rowB j=colB

                    multAddColA(A, rowB, valB, C, colB + 1, x, w);
                }

                // take the values in the dense vector 'x' and put them into 'C'
                int idxC0 = C.col_idx[colB];
                int idxC1 = C.col_idx[colB + 1];

                for (int i = idxC0; i < idxC1; i++)
                {
                    C.nz_values[i] = x[C.nz_rows[i]];
                }

                idx0 = idx1;
            }
        }
        /**
         * Computes the inner product of two column vectors taken from the input matrices.
         *
         * <p>dot = A(:,colA)'*B(:,colB)</p>
         *
         * @param A Matrix
         * @param colA Column in A
         * @param B Matrix
         * @param colB Column in B
         * @return Dot product
         */
        public static double dotInnerColumns(DMatrixSparseCSC A, int colA, DMatrixSparseCSC B, int colB,
                                             IGrowArray gw, DGrowArray gx)
        {
            if (A.numRows != B.numRows)
            {
                throw new ArgumentException("Number of rows must match.");
            }

            int[] w = TriangularSolver_DSCC.adjust(gw, A.numRows);
            //Arrays.fill(w,0,A.numRows,-1);
            for (var i = 0; i < A.numRows; i++)
            {
                w[i] = -1;
            }
            double[] x = TriangularSolver_DSCC.adjust(gx, A.numRows);

            int length = 0;

            int idx0 = A.col_idx[colA];
            int idx1 = A.col_idx[colA + 1];

            for (int i = idx0; i < idx1; i++)
            {
                int row = A.nz_rows[i];
                x[length] = A.nz_values[i];
                w[row]    = length++;
            }

            double dot = 0;

            idx0 = B.col_idx[colB];
            idx1 = B.col_idx[colB + 1];
            for (int i = idx0; i < idx1; i++)
            {
                int row = B.nz_rows[i];
                if (w[row] != -1)
                {
                    dot += x[w[row]] * B.nz_values[i];
                }
            }

            return(dot);
        }
Пример #7
0
        /**
         * Performs a matrix transpose.
         *
         * @param A Original matrix.  Not modified.
         * @param C Storage for transposed 'a'.  Reshaped.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         */
        public static void transpose(DMatrixSparseCSC A, DMatrixSparseCSC C, IGrowArray gw)
        {
            int[] work = TriangularSolver_DSCC.adjust(gw, A.numRows, A.numRows);
            C.reshape(A.numCols, A.numRows, A.nz_length);

            // compute the histogram for each row in 'a'
            int idx0 = A.col_idx[0];

            for (int j = 1; j <= A.numCols; j++)
            {
                int idx1 = A.col_idx[j];
                for (int i = idx0; i < idx1; i++)
                {
                    if (A.nz_rows.Length <= i)
                    {
                        throw new InvalidOperationException("Egads");
                    }
                    work[A.nz_rows[i]]++;
                }
                idx0 = idx1;
            }

            // construct col_idx in the transposed matrix
            C.colsum(work);

            // fill in the row indexes
            idx0 = A.col_idx[0];
            for (int j = 1; j <= A.numCols; j++)
            {
                int col  = j - 1;
                int idx1 = A.col_idx[j];
                for (int i = idx0; i < idx1; i++)
                {
                    int row   = A.nz_rows[i];
                    int index = work[row]++;
                    C.nz_rows[index]   = col;
                    C.nz_values[index] = A.nz_values[i];
                }
                idx0 = idx1;
            }
        }
        /**
         * Performs matrix multiplication.  C = A<sup>T</sup></sup>*B
         *
         * @param A Matrix
         * @param B Matrix
         * @param C Storage for results.  Data length is increased if increased if insufficient.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         * @param gx (Optional) Storage for internal workspace.  Can be null.
         */
        public static void multTransA(DMatrixSparseCSC A, DMatrixSparseCSC B, DMatrixSparseCSC C,
                                      IGrowArray gw, DGrowArray gx)
        {
            double[] x = TriangularSolver_DSCC.adjust(gx, A.numRows);
            int[]    w = TriangularSolver_DSCC.adjust(gw, A.numRows, A.numRows);

            C.growMaxLength(A.nz_length + B.nz_length, false);
            C.indicesSorted = true;
            C.nz_length     = 0;
            C.col_idx[0]    = 0;

            int idxB0 = B.col_idx[0];

            for (int bj = 1; bj <= B.numCols; bj++)
            {
                int idxB1 = B.col_idx[bj];
                C.col_idx[bj] = C.nz_length;

                if (idxB0 == idxB1)
                {
                    continue;
                }

                // convert the column of B into a dense format and mark which rows are used
                for (int bi = idxB0; bi < idxB1; bi++)
                {
                    int rowB = B.nz_rows[bi];
                    x[rowB] = B.nz_values[bi];
                    w[rowB] = bj;
                }

                // C(colA,colB) = A(:,colA)*B(:,colB)
                for (int colA = 0; colA < A.numCols; colA++)
                {
                    int idxA0 = A.col_idx[colA];
                    int idxA1 = A.col_idx[colA + 1];

                    double sum = 0;
                    for (int ai = idxA0; ai < idxA1; ai++)
                    {
                        int rowA = A.nz_rows[ai];
                        if (w[rowA] == bj)
                        {
                            sum += x[rowA] * A.nz_values[ai];
                        }
                    }

                    if (sum != 0)
                    {
                        if (C.nz_length == C.nz_values.Length)
                        {
                            C.growMaxLength(C.nz_length * 2 + 1, true);
                        }
                        C.nz_values[C.nz_length] = sum;
                        C.nz_rows[C.nz_length++] = colA;
                    }
                }
                C.col_idx[bj] = C.nz_length;
                idxB0         = idxB1;
            }
        }