public virtual DoubleMatrix1D Assign(Cern.Jet.Math.Mult mult) { for (int i = Size; --i >= 0;) { this[i] = mult.Apply(this[i]); } return(this); }
public void Solve(DoubleMatrix2D B) { int CUT_OFF = 10; //algebra.property().checkRectangular(LU); int m = M; int n = N; if (B.Rows != m) { throw new ArgumentException("Matrix row dimensions must agree."); } if (!this.IsNonsingular) { throw new ArgumentException("Matrix is singular."); } // right hand side with pivoting // Matrix Xmat = B.getMatrix(piv,0,nx-1); if (this.work1 == null || this.work1.Length < m) { this.work1 = new int[m]; } //if (this.work2 == null || this.work2.Length < m) this.work2 = new int[m]; Algebra.PermuteRows(B, this.piv, this.work1); if (m * n == 0) { return; // nothing to do } int nx = B.Columns; //precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] Brows = new DoubleMatrix1D[n]; for (int k = 0; k < n; k++) { Brows[k] = B.ViewRow(k); } // transformations Cern.Jet.Math.Mult div = Cern.Jet.Math.Mult.Div(0); Cern.Jet.Math.PlusMult minusMult = Cern.Jet.Math.PlusMult.MinusMult(0); IntArrayList nonZeroIndexes = new IntArrayList(); // sparsity DoubleMatrix1D Browk = Cern.Colt.Matrix.DoubleFactory1D.Dense.Make(nx); // blocked row k // Solve L*Y = B(piv,:) for (int k = 0; k < n; k++) { // blocking (make copy of k-th row to localize references) Browk.Assign(Brows[k]); // sparsity detection int maxCardinality = nx / CUT_OFF; // == heuristic depending on speedup Browk.GetNonZeros(nonZeroIndexes, null, maxCardinality); int cardinality = nonZeroIndexes.Count; Boolean sparse = (cardinality < maxCardinality); for (int i = k + 1; i < n; i++) { //for (int j = 0; j < nx; j++) B[i][j] -= B[k][j]*LU[i][k]; //for (int j = 0; j < nx; j++) B.set(i,j, B.Get(i,j) - B.Get(k,j)*LU.Get(i,k)); minusMult.Multiplicator = -LU[i, k]; if (minusMult.Multiplicator != 0) { if (sparse) { Brows[i].Assign(Browk, minusMult, nonZeroIndexes); } else { Brows[i].Assign(Browk, minusMult); } } } } // Solve U*B = Y; for (int k = n - 1; k >= 0; k--) { // for (int j = 0; j < nx; j++) B[k][j] /= LU[k][k]; // for (int j = 0; j < nx; j++) B.set(k,j, B.Get(k,j) / LU.Get(k,k)); div.Multiplicator = 1 / LU[k, k]; Brows[k].Assign(div); // blocking if (Browk == null) { Browk = Cern.Colt.Matrix.DoubleFactory1D.Dense.Make(B.Columns); } Browk.Assign(Brows[k]); // sparsity detection int maxCardinality = nx / CUT_OFF; // == heuristic depending on speedup Browk.GetNonZeros(nonZeroIndexes, null, maxCardinality); int cardinality = nonZeroIndexes.Count; Boolean sparse = (cardinality < maxCardinality); //Browk.GetNonZeros(nonZeroIndexes,null); //Boolean sparse = nonZeroIndexes.Count < nx/10; for (int i = 0; i < k; i++) { // for (int j = 0; j < nx; j++) B[i][j] -= B[k][j]*LU[i][k]; // for (int j = 0; j < nx; j++) B.set(i,j, B.Get(i,j) - B.Get(k,j)*LU.Get(i,k)); minusMult.Multiplicator = -LU[i, k]; if (minusMult.Multiplicator != 0) { if (sparse) { Brows[i].Assign(Browk, minusMult, nonZeroIndexes); } else { Brows[i].Assign(Browk, minusMult); } } } } }
public void Decompose(DoubleMatrix2D A) { int CUT_OFF = 10; // setup LU = A; int m = A.Rows; int n = A.Columns; // setup pivot vector if (this.piv == null || this.piv.Length != m) { this.piv = new int[m]; } for (int i = m; --i >= 0;) { piv[i] = i; } pivsign = 1; if (m * n == 0) { LU = LU; return; // nothing to do } //precompute and cache some views to avoid regenerating them time and again DoubleMatrix1D[] LUrows = new DoubleMatrix1D[m]; for (int i = 0; i < m; i++) { LUrows[i] = LU.ViewRow(i); } IntArrayList nonZeroIndexes = new IntArrayList(); // sparsity DoubleMatrix1D LUcolj = LU.ViewColumn(0).Like(); // blocked column j Cern.Jet.Math.Mult multFunction = Cern.Jet.Math.Mult.CreateInstance(0); // Outer loop. for (int j = 0; j < n; j++) { // blocking (make copy of j-th column to localize references) LUcolj.Assign(LU.ViewColumn(j)); // sparsity detection int maxCardinality = m / CUT_OFF; // == heuristic depending on speedup LUcolj.GetNonZeros(nonZeroIndexes, null, maxCardinality); int cardinality = nonZeroIndexes.Count; Boolean sparse = (cardinality < maxCardinality); // Apply previous transformations. for (int i = 0; i < m; i++) { int kmax = System.Math.Min(i, j); double s; if (sparse) { s = LUrows[i].ZDotProduct(LUcolj, 0, kmax, nonZeroIndexes); } else { s = LUrows[i].ZDotProduct(LUcolj, 0, kmax); } double before = LUcolj[i]; double after = before - s; LUcolj[i] = after; // LUcolj is a copy LU[i, j] = after; // this is the original if (sparse) { if (before == 0 && after != 0) { // nasty bug fixed! int pos = nonZeroIndexes.BinarySearch(i); pos = -pos - 1; nonZeroIndexes.Insert(pos, i); } if (before != 0 && after == 0) { nonZeroIndexes.Remove(nonZeroIndexes.BinarySearch(i)); } } } // Find pivot and exchange if necessary. int p = j; if (p < m) { double max = System.Math.Abs(LUcolj[p]); for (int i = j + 1; i < m; i++) { double v = System.Math.Abs(LUcolj[i]); if (v > max) { p = i; max = v; } } } if (p != j) { LUrows[p].Swap(LUrows[j]); int k = piv[p]; piv[p] = piv[j]; piv[j] = k; pivsign = -pivsign; } // Compute multipliers. double jj; if (j < m && (jj = LU[j, j]) != 0.0) { multFunction.Multiplicator = 1 / jj; LU.ViewColumn(j).ViewPart(j + 1, m - (j + 1)).Assign(multFunction); } } LU = LU; }