/// <summary> /// Solve least squares problem M x = b. /// The right-hand-side std::vector x may be b, /// which will give a fractional increase in speed. /// </summary> /// <param name="b"></param> /// <param name="x"></param> public unsafe void Solve(Vector b, Vector x) { //assert(b.size() == A_.Columns()); x = b; int n = A_.Columns; fixed(float *data = A_.Datablock()) { fixed(float *data2 = x.Datablock()) { Netlib.dposl_(data, &n, &n, data2); } } }
/// <summary> /// Cholesky decomposition. /// Make cholesky decomposition of M optionally computing /// the reciprocal condition number. If mode is estimate_condition, the /// condition number and an approximate nullspace are estimated, at a cost /// of a factor of (1 + 18/n). Here's a table of 1 + 18/n: ///<pre> /// n: 3 5 10 50 100 500 1000 /// slowdown: 7.0f 4.6 2.8 1.4 1.18 1.04 1.02 /// </summary> /// <param name="M"></param> /// <param name="mode"></param> public unsafe void init(MatrixFixed M, Operation mode) { A_ = new MatrixFixed(M); int n = M.Columns; //assert(n == (int)(M.Rows())); num_dims_rank_def_ = -1; int num_dims_rank_def_temp = num_dims_rank_def_; // BJT: This warning is pointless - it often doesn't detect non symmetry and // if you know what you're doing you don't want to be slowed down // by a cerr /* * if (Math.Abs(M[0,n-1] - M[n-1,0]) > 1e-8) * { * Debug.WriteLine("cholesky: WARNING: unsymmetric: " + M); * } */ if (mode != Operation.estimate_condition) { // Quick factorization fixed(float *data = A_.Datablock()) { Netlib.dpofa_(data, &n, &n, &num_dims_rank_def_temp); } //if ((mode == Operation.verbose) && (num_dims_rank_def_temp != 0)) // Debug.WriteLine("cholesky:: " + Convert.ToString(num_dims_rank_def_temp) + " dimensions of non-posdeffness"); } else { Vector nullvector = new Vector(n); float rcond_temp = rcond_; fixed(float *data = A_.Datablock()) { fixed(float *data2 = nullvector.Datablock()) { Netlib.dpoco_(data, &n, &n, &rcond_temp, data2, &num_dims_rank_def_temp); } } rcond_ = rcond_temp; } num_dims_rank_def_ = num_dims_rank_def_temp; }
/// <summary> /// Compute inverse.\ Not efficient. /// </summary> /// <returns></returns> public unsafe MatrixFixed Inverse() { int n = A_.Columns; MatrixFixed I = new MatrixFixed(A_); float[] det = new float[2]; int job = 01; fixed(float *data = I.Datablock()) { fixed(float *data2 = det) { Netlib.dpodi_(data, &n, &n, data2, &job); } } // Copy lower triangle into upper for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { I[i, j] = I[j, i]; } } return(I); }
/// <summary> /// JOB: ABCDE decimal /// A B C D E /// --- --- --- --- --- /// Qb Q'b x norm(A*x - b) A*x /// /// Solve equation M x = b for x using the computed decomposition. /// </summary> /// <param name="b"></param> /// <returns></returns> public unsafe Vector Solve(Vector b) { int n = qrdc_out_.Columns; int p = qrdc_out_.Rows; float[] b_data = b.Datablock(); Vector QtB = new Vector(n); Vector x = new Vector(p); // see comment above int JOB = 100; int info = 0; fixed(float *data = qrdc_out_.Datablock()) { fixed(float *data2 = qraux_.Datablock()) { fixed(float *data3 = b_data) { fixed(float *data4 = QtB.Datablock()) { fixed(float *data5 = x.Datablock()) { Netlib.dqrsl_(data, &n, &n, &p, data2, data3, (float *)0, data4, data5, (float *)0, // residual* (float *)0, // Ax* &JOB, &info); } } } } } if (info > 0) { Debug.WriteLine("__FILE__ : VNL::QR<T>::Solve() : matrix is rank-deficient by " + Convert.ToString(info)); } return(x); }
public unsafe QR(MatrixFixed M) { qrdc_out_ = new MatrixFixed(M.Columns, M.Rows); qraux_ = new Vector(M.Columns); jpvt_ = new int[M.Rows]; Q_ = null; R_ = null; // Fill transposed O/P matrix int c = M.Columns; int r = M.Rows; for (int i = 0; i < r; ++i) { for (int j = 0; j < c; ++j) { qrdc_out_[j, i] = M[i, j]; } } int do_pivot = 0; // Enable[!=0]/disable[==0] pivoting. for (int i = 0; i < jpvt_.Length; i++) { jpvt_[i] = 0; } Vector work = new Vector(M.Rows); fixed(float *data = qrdc_out_.Datablock()) { fixed(float *data2 = qraux_.Datablock()) { fixed(int *data3 = jpvt_) { fixed(float *data4 = work.Datablock()) { Netlib.dqrdc_(data, // On output, UT is R, below diag is mangled Q &r, &r, &c, data2, // Further information required to demangle Q data3, data4, &do_pivot); } } } } }
/// <summary> /// Compute determinant. /// </summary> /// <returns></returns> public unsafe float Determinant() { int n = A_.Columns; MatrixFixed I = new MatrixFixed(A_); float[] det = new float[2]; int job = 10; fixed(float *data = I.Datablock()) { fixed(float *data2 = det) { Netlib.dpodi_(data, &n, &n, data2, &job); } } return(det[0] * (float)Math.Pow(10.0, det[1])); }
/// <summary> /// Returns new vector which is the multiplication of row vector v with matrix m.\ O(m*n). /// </summary> /// <param name="m"></param> /// <param name="v"></param> /// <returns></returns> public static Vector operator *(Vector v, MatrixFixed m) { Vector result = new Vector(m.Columns); // Temporary MatrixFixed mm = m; // Drop const for get() float[] result_data = result.Datablock(); float[] v_data = v.Datablock(); float[,] mm_data = mm.Datablock(); for (int i = 0; i < m.Columns; i++) { // For each index result_data[i] = 0; // Initialize element value for (int k = 0; k < result_data.Length; k++) // Loop over column values { result_data[i] += (v_data[k] * mm_data[k, i]); // Multiply } } return(result); }
public static Vector operator*(MatrixFixed m, Vector v) { Vector result = new Vector(m.Rows); // Temporary MatrixFixed mm = m; // Drop const for get() float[] result_data = result.Datablock(); float[] v_data = v.Datablock(); float[,] mm_data = mm.Datablock(); int vsize = v.size(); for (int i = 0; i < m.Rows; i++) { // For each index result_data[i] = 0; // Initialize element value for (int k = 0; k < vsize; k++) // Loop over column values { result_data[i] += (mm_data[i, k] * v_data[k]); // Multiply } } return(result); }