/* * * /// <summary> * /// Permutes the columns of a matrix in CSC format, B = A * P, where P represents * /// a permutation matrix. * /// </summary> * /// <param name="ax">Input matrix values.</param> * /// <param name="ai">Input matrix row pointers.</param> * /// <param name="aj">Input matrix column indices.</param> * /// <param name="bx">Output matrix values.</param> * /// <param name="bi">Output matrix row pointers.</param> * /// <param name="bj">Output matrix column indices.</param> * /// <param name="perm">Permutation array of length ColumnCount.</param> * /// <remarks> * /// The permutation P is defined through the array perm: for each j, * /// perm(j) represents the destination row number of row number j: * /// * /// a(i,j) in the original matrix becomes a(perm(i),j) in the output matrix. * /// </remarks> * protected void PermuteColumns(int[] ai, int[] aj, int[] bi, int[] bj, int[] perm) * { * int k; * * // Determine pointers for output matix. * for (int i = 0; i < columnCount; i++) * { * k = perm[i]; * bi[k + 1] = ai[i + 1] - ai[i]; * } * * // Get pointers from lengths * bi[0] = 0; * for (int i = 0; i < columnCount; i++) * { * bi[i + 1] = bi[i + 1] + bi[i]; * } * * // Copying * for (int i = 0; i < columnCount; i++) * { * // Old row = i, new row = perm(i), k = new pointer * k = bi[perm[i]]; * for (int j = ai[i]; j < ai[i + 1]; j++) * { * bj[k] = aj[j]; * k = k + 1; * } * } * } * * /// <summary> * /// Permute the rows of a matrix in CSC format, B = P * A, where P represents * /// a permutation matrix. * /// </summary> * /// <param name="ax">Input matrix values.</param> * /// <param name="ai">Input matrix row pointers.</param> * /// <param name="aj">Input matrix column indices.</param> * /// <param name="bx">Output matrix values.</param> * /// <param name="bi">Output matrix row pointers.</param> * /// <param name="bj">Output matrix column indices.</param> * /// <param name="perm">Permutation array of length RowCount.</param> * /// <param name="copy">Copy matrix values (not needed if used 'in place').</param> * /// <remarks> * /// The permutation matrix P maps column j into column perm(j), i.e., * /// on return a(i,j) in the original matrix becomes a(i,perm(j)) in the * /// output matrix. * /// * /// Notes: * /// * /// 1. This routine is in place: aj, bj can be the same. * /// 2. If the matrix is initially sorted (by increasing column number) * /// then bx, bi, bj may not be on return. * /// </remarks> * protected void PermuteRows(int[] ai, int[] aj, int[] bi, int[] bj, * int[] perm, bool copy = false) * { * int i, nnz = ai[columnCount]; * * for (i = 0; i < nnz; i++) * { * bj[i] = perm[aj[i]]; * } * * if (copy) * { * Array.Copy(ai, bi, columnCount); * } * } * */ internal static SymbolicColumnStorage Create <T>(CompressedColumnStorage <T> mat, bool clone = true) where T : struct, IEquatable <T>, IFormattable { int m = mat.RowCount; int n = mat.ColumnCount; int nnz = mat.NonZerosCount; var result = new SymbolicColumnStorage(m, n, clone ? nnz : 0); //edited by epsi1on to fix this: https://brieffiniteelementnet.codeplex.com/workitem/6 if (m == 0 || n == 0) { return(result); } // if (clone) { Buffer.BlockCopy(mat.ColumnPointers, 0, result.ColumnPointers, 0, (n + 1) * Constants.SizeOfInt); Buffer.BlockCopy(mat.RowIndices, 0, result.RowIndices, 0, nnz * Constants.SizeOfInt); } else { result.ColumnPointers = mat.ColumnPointers; result.RowIndices = mat.RowIndices; } return(result); }
//public abstract SparseColumnStorage<T> Permute(int[] perm, int[] qperm = null, bool symbolic = false); /// <summary> /// Permutes a sparse matrix, C = PAQ. /// </summary> /// <param name="pinv">Permutation vector of length m.</param> /// <param name="q">Permutation vector of length n.</param> /// <param name="result">Permuted matrix, C = PAQ.</param> public virtual void Permute(int[] pinv, int[] q, SymbolicColumnStorage result) { int i, j, k, nz = 0; int m = this.rowCount; int n = this.columnCount; int[] ap = this.ColumnPointers; int[] ai = this.RowIndices; // Allocate memory if needed. if (result.ColumnPointers == null) { result.ColumnPointers = new int[ap.Length]; result.RowIndices = new int[ai.Length]; } int[] cp = result.ColumnPointers; int[] ci = result.RowIndices; for (k = 0; k < n; k++) { cp[k] = nz; // column k of C is column q[k] of A j = q != null ? (q[k]) : k; for (i = ap[j]; i < ap[j + 1]; i++) { ci[nz++] = pinv != null ? (pinv[ai[i]]) : ai[i]; } } // Finalize the last column of result matrix. cp[n] = nz; }
public SymbolicColumnStorage Clone() { int m = this.RowCount; int n = this.ColumnCount; int nnz = this.NonZerosCount; var result = new SymbolicColumnStorage(m, n, nnz); Buffer.BlockCopy(this.ColumnPointers, 0, result.ColumnPointers, 0, (n + 1) * Constants.SizeOfInt); Buffer.BlockCopy(this.RowIndices, 0, result.RowIndices, 0, nnz * Constants.SizeOfInt); return(result); }
/// <summary> /// Sparse matrix multiplication, C = A*B /// </summary> /// <param name="other">column-compressed matrix</param> /// <returns>C = A*B</returns> public SymbolicColumnStorage Multiply(SymbolicColumnStorage other) { int p, j, nz = 0; if (this.columnCount != other.rowCount) { throw new ArgumentException(); } int m = this.rowCount; int n = other.columnCount; int anz = this.NonZerosCount; int bnz = other.NonZerosCount; var bp = other.ColumnPointers; var bi = other.RowIndices; var result = new SymbolicColumnStorage(m, n, 0); var cp = new int[n + 1]; var ci = new int[2 * Math.Max(anz, bnz)]; int[] work = new int[m]; for (j = 0; j < n; j++) { if (nz + m > ci.Length) { Array.Resize <int>(ref ci, 2 * ci.Length + m); } // Column j of C starts here cp[j] = nz; for (p = bp[j]; p < bp[j + 1]; p++) { nz = this.Scatter(bi[p], work, j + 1, ci, nz); } } cp[n] = nz; // Remove extra space from C Array.Resize <int>(ref ci, nz); result.ColumnPointers = cp; result.RowIndices = ci; return(result); }
/// <summary> /// Symbolic sum C = A + B /// </summary> /// <param name="other">column-compressed matrix</param> /// <returns>Sum C = A + B</returns> public SymbolicColumnStorage Add(SymbolicColumnStorage other) { int j, nz = 0; // check inputs if (rowCount != other.rowCount || columnCount != other.columnCount) { throw new ArgumentException(); } if (rowCount == 0 || columnCount == 0) { return(new SymbolicColumnStorage(0, 0, 0)); } int m = rowCount; int n = other.columnCount; var bi = other.ColumnPointers; int anz = ColumnPointers[columnCount]; int bnz = bi[n]; // Workspace var w = new int[m]; // Allocate result: (anz + bnz) is an upper bound var cp = new int[bi.Length]; var ci = new int[anz + bnz]; for (j = 0; j < n; j++) { // Column j of result starts here cp[j] = nz; nz = this.Scatter(j, w, j + 1, ci, nz); // A(:,j) nz = other.Scatter(j, w, j + 1, ci, nz); // B(:,j) } // Finalize the last column cp[n] = nz; // Remove extra space Array.Resize <int>(ref ci, nz); var result = new SymbolicColumnStorage(m, n, 0); result.ColumnPointers = cp; result.RowIndices = ci; return(result); }
/// <summary> /// Computes the transpose of a sparse matrix, C = A'; /// </summary> /// <returns>Transposed matrix, C = A'</returns> public virtual SymbolicColumnStorage Transpose() { int j, k, p; int m = this.RowCount; int n = this.ColumnCount; var result = new SymbolicColumnStorage(n, m, 0); //edited by epsi1on to fix this: https://brieffiniteelementnet.codeplex.com/workitem/6 if (m == 0 || n == 0) { return(result); } // var ci = new int[m + 1]; var cj = new int[RowIndices.Length]; int[] w = new int[rowCount]; for (p = 0; p < ColumnPointers[columnCount]; p++) { // Row counts. w[RowIndices[p]]++; } // Column pointers. Helper.CumulativeSum(ci, w, rowCount); for (j = 0; j < columnCount; j++) { for (p = ColumnPointers[j]; p < ColumnPointers[j + 1]; p++) { k = w[RowIndices[p]]++; // Place A(i,j) as entry C(j,i) cj[k] = j; } } result.ColumnPointers = ci; result.RowIndices = cj; return(result); }