Esempio n. 1
0
        /// <inheritdoc />
        public override void Add(double alpha, double beta, CompressedColumnStorage <double> other,
                                 CompressedColumnStorage <double> result)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            int p, j, nz = 0;

            int m = this.rows;
            int n = this.columns;

            // check inputs
            if (m != other.RowCount || n != other.ColumnCount)
            {
                throw new ArgumentException(Resources.MatrixDimensions, nameof(other));
            }

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

            // Allocate result: (anz + bnz) is an upper bound

            var ci = result.ColumnPointers;
            var cj = result.RowIndices;
            var cx = result.Values;

            for (j = 0; j < n; j++)
            {
                ci[j] = nz;                                              // column j of C starts here
                nz    = this.Scatter(j, alpha, w, x, j + 1, result, nz); // alpha*A(:,j)
                nz    = other.Scatter(j, beta, w, x, j + 1, result, nz); // beta*B(:,j)

                for (p = ci[j]; p < nz; p++)
                {
                    cx[p] = x[cj[p]];
                }
            }

            // Finalize the last column
            ci[n] = nz;

            if (AutoTrimStorage)
            {
                // Remove extra space.
                result.Resize(0);
            }

            Helper.SortIndices(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Adds two matrices, C = alpha*A + beta*B, where A is current instance.
        /// </summary>
        /// <param name="alpha">Scalar factor for A, current instance.</param>
        /// <param name="beta">Scalar factor for B, other instance.</param>
        /// <param name="other">The matrix added to this instance.</param>
        /// <param name="result">Contains the sum.</param>
        /// <remarks>
        /// The (result) matrix has to be fully initialized and provide enough space for
        /// the nonzero entries of the sum. An upper bound is the sum of the nonzeros count
        /// of (this) and (other).
        /// </remarks>
        public override void Add(Complex alpha, Complex beta, CompressedColumnStorage <Complex> other,
                                 CompressedColumnStorage <Complex> result)
        {
            int p, j, nz = 0;

            int m = this.rowCount;
            int n = this.columnCount;

            // check inputs
            if (m != other.RowCount || n != other.ColumnCount)
            {
                throw new ArgumentException(Resources.MatrixDimensions);
            }

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

            // Allocate result: (anz + bnz) is an upper bound

            var ci = result.ColumnPointers;
            var cj = result.RowIndices;
            var cx = result.Values;

            for (j = 0; j < n; j++)
            {
                ci[j] = nz;                                              // column j of C starts here
                nz    = this.Scatter(j, alpha, w, x, j + 1, result, nz); // alpha*A(:,j)
                nz    = other.Scatter(j, beta, w, x, j + 1, result, nz); // beta*B(:,j)

                for (p = ci[j]; p < nz; p++)
                {
                    cx[p] = x[cj[p]];
                }
            }

            // Finalize the last column
            ci[n] = nz;

            // Remove extra space
            result.Resize(0);
            result.SortIndices();
        }
Esempio n. 3
0
        /// <summary>
        /// [L,U,pinv] = lu(A, [q lnz unz]). lnz and unz can be guess.
        /// </summary>
        private void Factorize(CompressedColumnStorage <Complex> A, double tol, IProgress <double> progress)
        {
            int[] q = S.q;

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

            this.L = CompressedColumnStorage <Complex> .Create(n, n, lnz);

            this.U = CompressedColumnStorage <Complex> .Create(n, n, unz);

            this.pinv = new int[n];

            // Workspace
            var x  = this.temp;
            var xi = new int[2 * n];

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

            lnz = unz = 0;

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

            int[]     li, ui;
            int[]     lp = L.ColumnPointers;
            int[]     up = U.ColumnPointers;
            Complex[] lx, ux;

            double current = 0.0;
            double step    = n / 100.0;

            // Now compute L(:,k) and U(:,k)
            for (int k = 0; k < n; k++)
            {
                // Progress reporting.
                if (k >= current)
                {
                    current += step;

                    if (progress != null)
                    {
                        progress.Report(k / (double)n);
                    }
                }

                // Triangular solve
                lp[k] = lnz; // L(:,k) starts here
                up[k] = unz; // U(:,k) starts here

                if (lnz + n > L.Values.Length)
                {
                    L.Resize(2 * L.Values.Length + n);
                }
                if (unz + n > U.Values.Length)
                {
                    U.Resize(2 * U.Values.Length + n);
                }

                li  = L.RowIndices;
                ui  = U.RowIndices;
                lx  = L.Values;
                ux  = U.Values;
                col = q != null ? (q[k]) : k;
                top = 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 = Complex.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.0)
                {
                    throw new Exception("No pivot element found.");
                }

                if (pinv[col] < 0 && Complex.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.0;
                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.0;                   // x [0..n-1] = 0 for next k
                }
            }

            // Finalize L and U
            lp[n] = lnz;
            up[n] = unz;
            li    = L.RowIndices; // fix row indices of L for final pinv
            for (p = 0; p < lnz; p++)
            {
                li[p] = pinv[li[p]];
            }

            // Remove extra space from L and U
            L.Resize(0);
            U.Resize(0);
        }
Esempio n. 4
0
        /// <inheritdoc />
        public override void Multiply(CompressedColumnStorage <double> other, CompressedColumnStorage <double> result)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            int p, j, nz = 0;

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

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

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

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

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

            if (result.RowCount != m || result.ColumnCount != n)
            {
                throw new ArgumentException(Resources.InvalidDimensions, nameof(result));
            }

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

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

            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

            if (AutoTrimStorage)
            {
                // Remove extra space.
                result.Resize(0);
            }

            Helper.SortIndices(result);
        }
Esempio n. 5
0
 /// <summary>
 /// Trim row indices and values array of the storage to the exact size (non-zeros count).
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="storage">The sparse matrix.</param>
 public static void TrimStorage <T>(CompressedColumnStorage <T> storage)
     where T : struct, IEquatable <T>, IFormattable
 {
     storage.Resize(0);
 }