public void Dsymv(Boolean isUpperTriangular, double alpha, DoubleMatrix2D A, DoubleMatrix1D x, double beta, DoubleMatrix1D y) { if (isUpperTriangular) { A = A.ViewDice(); } Property.DEFAULT.CheckSquare(A); int size = A.Rows; if (size != x.Size || size != y.Size) { throw new ArgumentException(A.ToStringShort() + ", " + x.ToStringShort() + ", " + y.ToStringShort()); } DoubleMatrix1D tmp = x.Like(); for (int i = 0; i < size; i++) { double sum = 0; for (int j = 0; j <= i; j++) { sum += A[i, j] * x[j]; } for (int j = i + 1; j < size; j++) { sum += A[j, i] * x[j]; } tmp[i] = alpha * sum + beta * y[i]; } y.Assign(tmp); }
/// <summary> /// Update the SVD with the addition of a new column. /// </summary> /// <param name="c"> /// The new column. /// </param> /// <param name="wantV"> /// Whether the matrix V is needed. /// </param> public void Update(DoubleMatrix1D c, bool wantV) { int nRows = c.Size - _m; if (nRows > 0) { _u = DoubleFactory2D.Dense.AppendRows(_u, new SparseDoubleMatrix2D(nRows, _n)); _m = c.Size; } else if (nRows < 0) { c = DoubleFactory1D.Sparse.AppendColumns(c, DoubleFactory1D.Sparse.Make(-nRows)); } var d = DoubleFactory2D.Dense.Make(c.ToArray(), c.Size); // l = U'd is the eigencoding of d var l = _u.ViewDice().ZMult(d, null); ////var uu = _u.ZMult(_u.ViewDice(), null); // Ul = UU'd ////var ul = uu.ZMult(d, null); var ul = _u.ZMult(l, null); // h = d - UU'd = d - Ul is the component of d orthogonal to the subspace spanned by U ////var h = d.Copy().Assign(uu.ZMult(d, null), BinaryFunctions.Minus); ////var h = d.Copy().Assign(ul, BinaryFunctions.Minus); // k is the projection of d onto the subspace othogonal to U var k = Math.Sqrt(d.Aggregate(BinaryFunctions.Plus, a => a * a) - (2 * l.Aggregate(BinaryFunctions.Plus, a => a * a)) + ul.Aggregate(BinaryFunctions.Plus, a => a * a)); // truncation if (k == 0 || double.IsNaN(k)) { return; } _n++; // j = d - UU'd = d - Ul is an orthogonal basis for the component of d orthogonal to the subspace spanned by U ////var j = h.Assign(UnaryFunctions.Div(k)); var j = d.Assign(ul, BinaryFunctions.Minus).Assign(UnaryFunctions.Div(k)); // Q = [ S, l; 0, ||h||] var q = DoubleFactory2D.Sparse.Compose( new[] { new[] { S, l }, new[] { null, DoubleFactory2D.Dense.Make(1, 1, k) } }); var svdq = new SingularValueDecomposition(q, true, wantV, true); _u = DoubleFactory2D.Dense.AppendColumns(_u, j).ZMult(svdq.U, null); _s = svdq.SingularValues; if (wantV) { _v = DoubleFactory2D.Dense.ComposeDiagonal(_v, DoubleFactory2D.Dense.Identity(1)).ZMult( svdq.V, null); } }
public void Dtrmv(Boolean isUpperTriangular, Boolean transposeA, Boolean isUnitTriangular, DoubleMatrix2D A, DoubleMatrix1D x) { if (transposeA) { A = A.ViewDice(); isUpperTriangular = !isUpperTriangular; } Property.DEFAULT.CheckSquare(A); int size = A.Rows; if (size != x.Size) { throw new ArgumentException(A.ToStringShort() + ", " + x.ToStringShort()); } DoubleMatrix1D b = x.Like(); DoubleMatrix1D y = x.Like(); if (isUnitTriangular) { y.Assign(1); } else { for (int i = 0; i < size; i++) { y[i] = A[i, i]; } } for (int i = 0; i < size; i++) { double sum = 0; if (!isUpperTriangular) { for (int j = 0; j < i; j++) { sum += A[i, j] * x[j]; } sum += y[i] * x[i]; } else { sum += y[i] * x[i]; for (int j = i + 1; j < size; j++) { sum += A[i, j] * x[j]; } } b[i] = sum; } x.Assign(b); }
/// <summary> /// A matrix <i>A</i> is <i>symmetric</i> if <i>A = tranpose(A)</i>, that is <i>A[i,j] == A[j,i]</i>. /// <summary> /// <exception cref="ArgumentException">if <i>!isSquare(A)</i>. </exception> public Boolean IsSymmetric(DoubleMatrix2D A) { CheckSquare(A); return(Equals(A, A.ViewDice())); }
/// <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); }
public void Dgemv(bool transposeA, double alpha, DoubleMatrix2D A, DoubleMatrix1D x, double beta, DoubleMatrix1D y) { /* * split A, as follows: * * x x * x * x * A * xxx x y * xxx x * --- - * xxx x * xxx x * --- - * xxx x * */ if (transposeA) { Dgemv(false, alpha, A.ViewDice(), x, beta, y); return; } int m = A.Rows; int n = A.Columns; long flops = 2L * m * n; int noOfTasks = (int)System.Math.Min(flops / 30000, this.maxThreads); // each thread should process at least 30000 flops int width = A.Rows; noOfTasks = System.Math.Min(width, noOfTasks); if (noOfTasks < 2) { // parallelization doesn't pay off (too much start up overhead) seqBlas.Dgemv(transposeA, alpha, A, x, beta, y); return; } // set up concurrent tasks int span = width / noOfTasks; //FJTask[] subTasks = new FJTask[noOfTasks]; for (int i = 0; i < noOfTasks; i++) { int offset = i * span; if (i == noOfTasks - 1) { span = width - span * i; // last span may be a bit larger } // split A along rows into blocks DoubleMatrix2D AA = A.ViewPart(offset, 0, span, n); DoubleMatrix1D yy = y.ViewPart(offset, span); // subTasks[i] = new FJTask() // { // public void run() // { // seqBlas.Dgemv(transposeA, alpha, AA, x, beta, yy); // //Console.WriteLine("Hello "+offset); // } //}; Action task = (() => { seqBlas.Dgemv(transposeA, alpha, AA, x, beta, yy); }); // run tasks and wait for completion try { this.smp.TaskGroup.QueueTask(() => task()); } catch (TaskCanceledException exc) { } } }
public void Dgemm(bool transposeA, bool transposeB, double alpha, DoubleMatrix2D A, DoubleMatrix2D B, double beta, DoubleMatrix2D C) { /* * determine how to split and parallelize best into blocks * if more B.columns than tasks --> split B.columns, as follows: * * xx|xx|xxx B * xx|xx|xxx * xx|xx|xxx * A * xxx xx|xx|xxx C * xxx xx|xx|xxx * xxx xx|xx|xxx * xxx xx|xx|xxx * xxx xx|xx|xxx * * if less B.columns than tasks --> split A.rows, as follows: * * xxxxxxx B * xxxxxxx * xxxxxxx * A * xxx xxxxxxx C * xxx xxxxxxx * --- ------- * xxx xxxxxxx * xxx xxxxxxx * --- ------- * xxx xxxxxxx * */ if (transposeA) { Dgemm(false, transposeB, alpha, A.ViewDice(), B, beta, C); return; } if (transposeB) { Dgemm(transposeA, false, alpha, A, B.ViewDice(), beta, C); return; } int m = A.Rows; int n = A.Columns; int p = B.Columns; if (B.Rows != n) { throw new ArgumentException("Matrix2D inner dimensions must agree:" + A.ToStringShort() + ", " + B.ToStringShort()); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException("Incompatibel result matrix: " + A.ToStringShort() + ", " + B.ToStringShort() + ", " + C.ToStringShort()); } if (A == C || B == C) { throw new ArgumentException("Matrices must not be identical"); } long flops = 2L * m * n * p; int noOfTasks = (int)System.Math.Min(flops / 30000, this.maxThreads); // each thread should process at least 30000 flops Boolean splitB = (p >= noOfTasks); int width = splitB ? p : m; noOfTasks = System.Math.Min(width, noOfTasks); if (noOfTasks < 2) { // parallelization doesn't pay off (too much start up overhead) seqBlas.Dgemm(transposeA, transposeB, alpha, A, B, beta, C); return; } // set up concurrent tasks int span = width / noOfTasks; //FJTask[] subTasks = new FJTask[noOfTasks]; for (int i = 0; i < noOfTasks; i++) { int offset = i * span; if (i == noOfTasks - 1) { span = width - span * i; // last span may be a bit larger } DoubleMatrix2D AA, BB, CC; if (splitB) { // split B along columns into blocks AA = A; BB = B.ViewPart(0, offset, n, span); CC = C.ViewPart(0, offset, m, span); } else { // split A along rows into blocks AA = A.ViewPart(offset, 0, span, n); BB = B; CC = C.ViewPart(offset, 0, span, p); } Action task = (() => { seqBlas.Dgemm(transposeA, transposeB, alpha, AA, BB, beta, CC); }); // run tasks and wait for completion try { this.smp.TaskGroup.QueueTask(() => task()); } catch (TaskCanceledException exc) { } } }
public override DoubleMatrix2D ZMult(DoubleMatrix2D B, DoubleMatrix2D C, double alpha, double beta, Boolean transposeA, Boolean transposeB) { if (transposeB) { B = B.ViewDice(); } int m = Rows; int n = Columns; if (transposeA) { m = Columns; n = Rows; } int p = B.Columns; Boolean ignore = (C == null); if (C == null) { C = new DenseDoubleMatrix2D(m, p); } if (B.Rows != n) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_Matrix2DInnerDimensionMustAgree, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort())); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_IncompatibleResultMatrix, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort(), C.ToStringShort())); } if (this == C || B == C) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatricesMustNotBeIdentical); } if (!ignore) { C.Assign(F1.Mult(beta)); } // cache views DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int i = n; --i >= 0;) { Brows[i] = B.ViewRow(i); } DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; for (int i = m; --i >= 0;) { Crows[i] = C.ViewRow(i); } ForEachNonZero( new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) => { var fun = F2.PlusMult(value * alpha); //fun.multiplicator = value * alpha; if (!transposeA) { Crows[i].Assign(Brows[j], fun); } else { Crows[j].Assign(Brows[i], fun); } return(value); } )); return(C); }
///// <summary> ///// ///// </summary> ///// <param name="matrix"></param> ///// <param name="rowNames"></param> ///// <param name="columnNames"></param> ///// <param name="rowAxisName"></param> ///// <param name="columnAxisName"></param> ///// <param name="title"></param> ///// <returns></returns> //public String ToTitleString(ObjectMatrix2D matrix, String[] rowNames, String[] columnNames, String rowAxisName, String columnAxisName, String title) //{ // if (matrix.Size == 0) return "Empty matrix"; // String oldFormat = this.formatString; // this.formatString = LEFT; // int rows = matrix.Rows; // int columns = matrix.Columns; // // determine how many rows and columns are needed // int r = 0; // int c = 0; // r += (columnNames == null ? 0 : 1); // c += (rowNames == null ? 0 : 1); // c += (rowAxisName == null ? 0 : 1); // c += (rowNames != null || rowAxisName != null ? 1 : 0); // int height = r + System.Math.Max(rows, rowAxisName == null ? 0 : rowAxisName.Length); // int width = c + columns; // // make larger matrix holding original matrix and naming strings // Cern.Colt.Matrix.ObjectMatrix2D titleMatrix = matrix.Like(height, width); // // insert original matrix into larger matrix // titleMatrix.ViewPart(r, c, rows, columns).Assign(matrix); // // insert column axis name in leading row // if (r > 0) titleMatrix.ViewRow(0).ViewPart(c, columns).Assign(columnNames); // // insert row axis name in leading column // if (rowAxisName != null) // { // String[] rowAxisStrings = new String[rowAxisName.Length]; // for (int i = rowAxisName.Length; --i >= 0;) rowAxisStrings[i] = rowAxisName.Substring(i, i + 1); // titleMatrix.ViewColumn(0).ViewPart(r, rowAxisName.Length).Assign(rowAxisStrings); // } // // insert row names in next leading columns // if (rowNames != null) titleMatrix.ViewColumn(c - 2).ViewPart(r, rows).Assign(rowNames); // // insert vertical "---------" separator line in next leading column // if (c > 0) titleMatrix.ViewColumn(c - 2 + 1).ViewPart(0, rows + r).Assign("|"); // // convert the large matrix to a string // Boolean oldPrintShape = this.printShape; // this.printShape = false; // String str = ToString(titleMatrix); // this.printShape = oldPrintShape; // // insert horizontal "--------------" separator line // var total = new StringBuilder(str); // if (columnNames != null) // { // int i = str.IndexOf(rowSeparator); // total.Insert(i + 1, Repeat('-', i) + rowSeparator); // } // else if (columnAxisName != null) // { // int i = str.IndexOf(rowSeparator); // total.Insert(0, Repeat('-', i) + rowSeparator); // } // // insert line for column axis name // if (columnAxisName != null) // { // int j = 0; // if (c > 0) j = str.IndexOf('|'); // String s = Blanks(j); // if (c > 0) s = s + "| "; // s = s + columnAxisName + "\n"; // total.Insert(0, s); // } // // insert title // if (title != null) total.Insert(0, title + "\n"); // this.formatString = oldFormat; // return total.ToString(); //} /// <summary> /// Same as <i>toTitleString</i> except that additionally statistical aggregates (mean, median, sum, etcd) of rows and columns are printed. /// Pass <i>null</i> to one or more parameters to indicate that the corresponding decoration element shall not appear in the string converted matrix. /// </summary> /// <param name="matrix">The matrix to format.</param> /// <param name="rowNames">The headers of all rows (to be put to the left of the matrix).</param> /// <param name="columnNames">The headers of all columns (to be put to above the matrix).</param> /// <param name="rowAxisName">The label of the y-axis.</param> /// <param name="columnAxisName">The label of the x-axis.</param> /// <param name="title">The overall title of the matrix to be formatted.</param> /// <param name="aggr">the aggregation functions to be applied to columns and rows.</param> /// <returns>the matrix converted to a string.</returns> /// <see cref="Hep.Aida.Bin.BinFunction1D"/> /// <see cref="Hep.Aida.Bin.BinFunctions1D"/> public String ToTitleString(DoubleMatrix2D matrix, String[] rowNames, String[] columnNames, String rowAxisName, String columnAxisName, String title, Hep.Aida.Bin.BinFunction1D[] aggr) { if (matrix.Size == 0) { return("Empty matrix"); } if (aggr == null || aggr.Length == 0) { return(ToTitleString(matrix, rowNames, columnNames, rowAxisName, columnAxisName, title)); } DoubleMatrix2D rowStats = matrix.Like(matrix.Rows, aggr.Length); // hold row aggregations DoubleMatrix2D colStats = matrix.Like(aggr.Length, matrix.Columns); // hold column aggregations Cern.Colt.Matrix.DoubleAlgorithms.Statistics.Aggregate(matrix, aggr, colStats); // aggregate an entire column at a time Cern.Colt.Matrix.DoubleAlgorithms.Statistics.Aggregate(matrix.ViewDice(), aggr, rowStats.ViewDice()); // aggregate an entire row at a time // turn into strings // tmp holds "matrix" plus "colStats" below (needed so that numbers in a columns can be decimal point aligned) DoubleMatrix2D tmp = matrix.Like(matrix.Rows + aggr.Length, matrix.Columns); tmp.ViewPart(0, 0, matrix.Rows, matrix.Columns).Assign(matrix); tmp.ViewPart(matrix.Rows, 0, aggr.Length, matrix.Columns).Assign(colStats); String[][] s1 = Format(tmp); Align(s1); String[][] s2 = Format(rowStats); Align(s2); // copy strings into a large matrix holding the source matrix and all aggregations Cern.Colt.Matrix.ObjectMatrix2D allStats = Cern.Colt.Matrix.ObjectFactory2D.Dense.Make(matrix.Rows + aggr.Length, matrix.Columns + aggr.Length + 1); allStats.ViewPart(0, 0, matrix.Rows + aggr.Length, matrix.Columns).Assign(s1); allStats.ViewColumn(matrix.Columns).Assign("|"); allStats.ViewPart(0, matrix.Columns + 1, matrix.Rows, aggr.Length).Assign(s2); // append a vertical "|" separator plus names of aggregation functions to line holding columnNames if (columnNames != null) { var list = new List <Object>(columnNames); list.Add("|"); list.AddRange(aggr.Select(x => x.Method.Name).ToList()); columnNames = list.ToStringArray(); } // append names of aggregation functions to line holding rowNames if (rowNames != null) { var list = new List <Object>(rowNames); list.AddRange(aggr.Select(x => x.Method.Name).ToList()); rowNames = list.ToStringArray(); } // turn large matrix into string String s = new Cern.Colt.Matrix.ObjectAlgorithms.Formatter().ToTitleString(allStats, rowNames, columnNames, rowAxisName, columnAxisName, title); // insert a horizontal "----------------------" separation line above the column stats // determine insertion position and line width int last = s.Length + 1; int secondLast = last; int v = System.Math.Max(0, rowAxisName == null ? 0 : rowAxisName.Length - matrix.Rows - aggr.Length); for (int k = 0; k < aggr.Length + 1 + v; k++) { // scan "aggr.Length+1+v" lines backwards secondLast = last; last = s.LastIndexOf(rowSeparator, last - 1); } StringBuilder buf = new StringBuilder(s); buf.Insert(secondLast, rowSeparator + Repeat('-', secondLast - last - 1)); return(buf.ToString()); }
public override DoubleMatrix2D ZMult(DoubleMatrix2D B, DoubleMatrix2D C, double alpha, double beta, Boolean transposeA, Boolean transposeB) { if (transposeB) { B = B.ViewDice(); } int m = Rows; int n = Columns; if (transposeA) { m = Columns; n = Rows; } int p = B.Columns; Boolean ignore = (C == null); if (C == null) { C = new DenseDoubleMatrix2D(m, p); } if (B.Rows != n) { throw new ArgumentException("Matrix2D inner dimensions must agree:" + ToStringShort() + ", " + (transposeB ? B.ViewDice() : B).ToStringShort()); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException("Incompatibel result matrix: " + ToStringShort() + ", " + (transposeB ? B.ViewDice() : B).ToStringShort() + ", " + C.ToStringShort()); } if (this == C || B == C) { throw new ArgumentException("Matrices must not be identical"); } if (!ignore) { C.Assign(F1.Mult(beta)); } // cache views DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int i = n; --i >= 0;) { Brows[i] = B.ViewRow(i); } DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; for (int i = m; --i >= 0;) { Crows[i] = C.ViewRow(i); } ForEachNonZero( new Cern.Colt.Function.IntIntDoubleFunction((i, j, value) => { var fun = F2.PlusMult(value * alpha); //fun.multiplicator = value * alpha; if (!transposeA) { Crows[i].Assign(Brows[j], fun); } else { Crows[j].Assign(Brows[i], fun); } return(value); } )); return(C); }
/// <summary> /// Constructs and returns a new view which is the transposition of the given matrix <i>A</i>. /// </summary> /// <param name="a"> /// The matrix A. /// </param> /// <returns> /// The transpose of A. /// </returns> public static DoubleMatrix2D Transpose(DoubleMatrix2D a) { return(a.ViewDice()); }
public static DoubleMatrix2D PermuteColumns(DoubleMatrix2D A, int[] indexes, int[] work) { return(PermuteRows(A.ViewDice(), indexes, work)); }
public override DoubleMatrix2D ZMult(DoubleMatrix2D B, DoubleMatrix2D C, double alpha, double beta, Boolean transposeA, Boolean transposeB) { if (transposeB) { B = B.ViewDice(); } int m = Rows; int n = Columns; if (transposeA) { m = Columns; n = Rows; } int p = B.Columns; Boolean ignore = (C == null); if (C == null) { C = new DenseDoubleMatrix2D(m, p); } if (B.Rows != n) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_Matrix2DInnerDimensionMustAgree, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort())); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException(String.Format(Cern.LocalizedResources.Instance().Exception_IncompatibleResultMatrix, ToStringShort(), (transposeB ? B.ViewDice() : B).ToStringShort(), C.ToStringShort())); } if (this == C || B == C) { throw new ArgumentException(Cern.LocalizedResources.Instance().Exception_MatricesMustNotBeIdentical); } if (!ignore) { C.Assign(F1.Mult(beta)); } // cache views DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int i = n; --i >= 0;) { Brows[i] = B.ViewRow(i); } DoubleMatrix1D[] Crows = new DoubleMatrix1D[m]; for (int i = m; --i >= 0;) { Crows[i] = C.ViewRow(i); } int[] idx = Indexes.ToArray(); double[] vals = Values.ToArray(); for (int i = Starts.Length - 1; --i >= 0;) { int low = Starts[i]; for (int k = Starts[i + 1]; --k >= low;) { int j = idx[k]; var fun = F2.PlusMult(vals[k] * alpha); //fun.Multiplicator = vals[k] * alpha; if (!transposeA) { Crows[i].Assign(Brows[j], fun); } else { Crows[j].Assign(Brows[i], fun); } } } return(C); }