/// <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 }