/// <summary> /// Performs the following operation for 0 <= i < <see cref="NumRows"/>, 0 <= j < <see cref="NumColumns"/>: /// result[i, j] = <paramref name="otherCoefficient"/> * <paramref name="otherMatrix"/>[i, j] + this[i, j]. /// The resulting matrix is written to a new <see cref="CsrMatrix"/> and then returned. /// </summary> /// <param name="otherMatrix">A matrix with the same <see cref="NumRows"/> and <see cref="NumColumns"/> as this /// <see cref="CsrMatrix"/> instance.</param> /// <param name="otherCoefficient">A scalar that multiplies each entry of <paramref name="otherMatrix"/>.</param> /// <exception cref="NonMatchingDimensionsException">Thrown if <paramref name="otherMatrix"/> has different /// <see cref="NumRows"/> or <see cref="NumColumns"/> than this instance.</exception> public CsrMatrix Axpy(CsrMatrix otherMatrix, double otherCoefficient) { // Conceptually it is not wrong to so this, even if the indexers are different, but how would I implement it. if (!HasSameIndexer(otherMatrix)) { throw new SparsityPatternModifiedException("Only allowed if the indexing arrays are the same"); } //TODO: Perhaps this should be done using mkl_malloc and BLAS copy. double[] resultValues = new double[values.Length]; Array.Copy(this.values, resultValues, values.Length); Blas.Daxpy(values.Length, otherCoefficient, otherMatrix.values, 0, 1, resultValues, 0, 1); // Do not copy the index arrays, since they are already spread around. TODO: is this a good idea? return(new CsrMatrix(NumRows, NumColumns, resultValues, this.colIndices, this.rowOffsets)); }
/// <summary> /// Performs the operation: result = transpose(<paramref name="csr"/>) * <paramref name="other"/> * <paramref name="csr"/> /// in an efficient way, by appropriately selecting which methods should be called for these matrices and in what order. /// </summary> /// <param name="csr">The matrix that will be multiplied "outside".</param> /// <param name="other">The matrix that will be multiplied "inside". It must be square.</param> public static Matrix ThisTimesOtherTimesThisTranspose(this CsrMatrix csr, Matrix other) { // As of 15 December 2018, right multiplying is more efficient than left multiplying, since the resulting matrix // of right multiplying is column major and we can leverage BLAS. Therefore we want the right multiplication to // happen for the larger matrix: csr * matrix. if (other.NumColumns < csr.NumRows) { Matrix temp = csr.MultiplyLeft(other, true, false); // temp is larger than other return(csr.MultiplyRight(temp, false, false)); } else { Matrix temp = csr.MultiplyRight(other, false, false); // other is larger than temp return(csr.MultiplyLeft(temp, true, false)); } }
/// <summary> /// Creates a new <see cref="CsrMatrix"/> instance, that is transpose to this: result[i, j] = this[j, i]. The /// internal arrays can be copied or shared with this <see cref="CscMatrix"/> instance. /// </summary> /// <param name="copyInternalArray">If true, the internal arrays that store the entries of this /// <see cref="CscMatrix"/> instance will be copied and the new <see cref="CsrMatrix"/> instance /// instance will have references to the copies, which is safer. If false, both the new matrix and this one will have /// references to the same internal arrays, which is faster.</param> public CsrMatrix TransposeToCSR(bool copyInternalArrays) { if (copyInternalArrays) { double[] valuesCopy = new double[values.Length]; Array.Copy(values, valuesCopy, values.Length); int[] rowIndicesCopy = new int[rowIndices.Length]; Array.Copy(rowIndices, rowIndicesCopy, rowIndices.Length); int[] colOffsetsCopy = new int[colOffsets.Length]; Array.Copy(colOffsets, colOffsetsCopy, colOffsets.Length); return(CsrMatrix.CreateFromArrays(NumColumns, NumRows, valuesCopy, rowIndicesCopy, colOffsetsCopy, false)); } else { return(CsrMatrix.CreateFromArrays(NumColumns, NumRows, values, rowIndices, colOffsets, false)); } }
/// <summary> /// Performs the operation: result = transpose(<paramref name="csr"/>) * <paramref name="other"/> * <paramref name="csr"/> /// in an efficient way, by appropriately selecting which methods should be called for these matrices and in what order. /// </summary> /// <param name="csr">The matrix that will be multiplied "outside".</param> /// <param name="other">The matrix that will be multiplied "inside". It must be square.</param> public static Matrix ThisTimesOtherTimesThisTranspose(this CsrMatrix csr, SymmetricMatrix other) => throw new NotImplementedException("Placeholder for when SymmetricMatrix is fully implemented");