/// <summary> /// Linear algebraic matrix-matrix multiplication; <tt>C = alpha * A x B + beta*C</tt>. /// </summary> /// <param name="b"> /// The econd source matrix. /// </param> /// <param name="c"> /// The matrix where results are to be stored. Set this parameter to <tt>null</tt> to indicate that a new result matrix shall be constructed. /// </param> /// <param name="alpha"> /// The alpha. /// </param> /// <param name="beta"> /// The beta. /// </param> /// <param name="transposeA"> /// Whether A must be transposed. /// </param> /// <param name="transposeB"> /// Whether B must be transposed. /// </param> /// <returns> /// C (for convenience only). /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// If <tt>B.rows() != A.columns()</tt>. /// </exception> /// <exception cref="ArgumentException"> /// If <tt>C.rows() != A.rows() || C.columns() != B.columns()</tt>. /// </exception> /// <exception cref="ArithmeticException"> /// If <tt>A == C || B == C</tt>. /// </exception> public override DoubleMatrix2D ZMult(DoubleMatrix2D b, DoubleMatrix2D c, double alpha, double beta, bool transposeA, bool transposeB) { // overriden for performance only if (transposeA) { return(ViewDice().ZMult(b, c, alpha, beta, false, transposeB)); } if (b is SparseDoubleMatrix2D) { // exploit quick sparse mult // A*B = (B' * A')' if (c == null) { return(b.ZMult(this, null, alpha, beta, !transposeB, true).ViewDice()); } b.ZMult(this, c.ViewDice(), alpha, beta, !transposeB, true); return(c); } if (transposeB) { return(ZMult(b.ViewDice(), c, alpha, beta, false, false)); } int m = Rows; int n = Columns; int p = b.Columns; if (c == null) { c = new DenseDoubleMatrix2D(m, p); } if (!(c is DenseDoubleMatrix2D)) { return(base.ZMult(b, c, alpha, beta, false, false)); } if (b.Rows != n) { throw new ArgumentOutOfRangeException("b", "Matrix2D inner dimensions must agree:" + this + ", " + b); } if (c.Rows != m || c.Columns != p) { throw new ArgumentException("Incompatible result matrix: " + this + ", " + b + ", " + c); } if (this == c || b == c) { throw new ArgumentException("Matrices must not be identical"); } var bb = (DenseDoubleMatrix2D)b; var cc = (DenseDoubleMatrix2D)c; double[] aElems = Elements; double[] bElems = bb.Elements; double[] cElems = cc.Elements; if (aElems == null || bElems == null || cElems == null) { throw new ApplicationException(); } int cA = ColumnStride; int cB = bb.ColumnStride; int cC = cc.ColumnStride; int rA = RowStride; int rB = bb.RowStride; int rC = cc.RowStride; /* * A is blocked to hide memory latency * xxxxxxx B * xxxxxxx * xxxxxxx * A * xxx xxxxxxx C * xxx xxxxxxx * --- ------- * xxx xxxxxxx * xxx xxxxxxx * --- ------- * xxx xxxxxxx */ const int BLOCK_SIZE = 30000; int m_optimal = (BLOCK_SIZE - n) / (n + 1); if (m_optimal <= 0) { m_optimal = 1; } int blocks = m / m_optimal; int rr = 0; if (m % m_optimal != 0) { blocks++; } for (; --blocks >= 0;) { int jB = bb.Index(0, 0); int indexA = Index(rr, 0); int jC = cc.Index(rr, 0); rr += m_optimal; if (blocks == 0) { m_optimal += m - rr; } for (int j = p; --j >= 0;) { int iA = indexA; int iC = jC; for (int i = m_optimal; --i >= 0;) { int kA = iA; int kB = jB; double s = 0; /* * // not unrolled: * for (int k = n; --k >= 0;) { * //s += getQuick(i,k) * B.getQuick(k,j); * s += AElems[kA] * BElems[kB]; * kB += rB; * kA += cA; * } */ // loop unrolled kA -= cA; kB -= rB; for (int k = n % 4; --k >= 0;) { s += aElems[kA += cA] * bElems[kB += rB]; } for (int k = n / 4; --k >= 0;) { s += (aElems[kA += cA] * bElems[kB += rB]) + (aElems[kA += cA] * bElems[kB += rB]) + (aElems[kA += cA] * bElems[kB += rB]) + (aElems[kA += cA] * bElems[kB += rB]); } cElems[iC] = (alpha * s) + (beta * cElems[iC]); iA += rA; iC += rC; } jB += cB; jC += cC; } } return(c); }
/// <summary> /// A square matrix <i>A</i> is <i>orthogonal</i> if <i>A*transpose(A) = I</i>. /// <summary> /// <exception cref="ArgumentException">if <i>!isSquare(A)</i>. </exception> public Boolean IsOrthogonal(DoubleMatrix2D A) { CheckSquare(A); return(Equals(A.ZMult(A, null, 1, 0, false, true), Cern.Colt.Matrix.DoubleFactory2D.Dense.Identity(A.Rows))); }
/// <summary> /// Encode a vector in the space spanned by columns of U. /// </summary> /// <param name="d"> /// The vector d. /// </param> /// <returns> /// U'd /// </returns> public DoubleMatrix1D Encode(DoubleMatrix1D d) { return(_u.ZMult(d.Size < _m ? DoubleFactory1D.Sparse.AppendColumns(d, DoubleFactory1D.Sparse.Make(_m - d.Size)) : d, null, 1, 0, true)); }
public void Dgemv(Boolean transposeA, double alpha, DoubleMatrix2D A, DoubleMatrix1D x, double beta, DoubleMatrix1D y) { A.ZMult(x, y, alpha, beta, transposeA); }
public void Dgemm(Boolean transposeA, Boolean transposeB, double alpha, DoubleMatrix2D A, DoubleMatrix2D B, double beta, DoubleMatrix2D C) { A.ZMult(B, C, alpha, beta, transposeA, transposeB); }
/// <summary> /// Linear algebraic matrix-matrix multiplication; <i>C = A x B</i>. /// </summary> /// <param name="a"> /// The first source matrix. /// </param> /// <param name="b"> /// The second source matrix. /// </param> /// <returns> /// <i>C</i>; a new matrix holding the results, with <i>C.Rows=A.Rows, C.Columns==B.Columns</i>. /// </returns> /// <exception cref="ArgumentException"> /// If <i>B.Rows != A.Columns</i>. /// </exception> public static DoubleMatrix2D Mult(DoubleMatrix2D a, DoubleMatrix2D b) { return(a.ZMult(b, null)); }
/// <summary> /// Linear algebraic matrix-vector multiplication; <i>z = A * y</i>. /// </summary> /// <param name="a"> /// The matrix A. /// </param> /// <param name="y"> /// The vector y. /// </param> /// <returns> /// <i>z</i>; a new vector with <i>z.Size==A.Rows</i>. /// </returns> public static DoubleMatrix1D Mult(DoubleMatrix2D a, DoubleMatrix1D y) { return(a.ZMult(y, null)); }