// SymPy's cholesky decomposition void cholesky(const DenseMatrix &A, DenseMatrix &L) { CSYMPY_ASSERT(A.row_ == A.col_); CSYMPY_ASSERT(L.row_ == A.row_ && L.col_ == A.row_); unsigned col = A.col_; unsigned i, j, k; RCP<const Basic> sum; RCP<const Basic> i2 = integer(2); RCP<const Basic> half = div(one, i2); // Initialize L for (i = 0; i < col; i++) for(j = 0; j < col; j++) L.m_[i*col + j] = zero; for (i = 0; i < col; i++) { for (j = 0; j < i; j++) { sum = zero; for(k = 0; k < j; k++) sum = add(sum, mul(L.m_[i*col + k], L.m_[j*col + k])); L.m_[i*col + j] = mul(div(one, L.m_[j*col + j]), sub(A.m_[i*col + j], sum)); } sum = zero; for (k = 0; k < i; k++) sum = add(sum, pow(L.m_[i*col + k], i2)); L.m_[i*col + i] = pow(sub(A.m_[i*col + i], sum), half); } }
// --------------------------- Solve Ax = b ---------------------------------// // Assuming A is a diagonal square matrix void diagonal_solve(const DenseMatrix &A, const DenseMatrix &b, DenseMatrix &x) { CSYMPY_ASSERT(A.row_ == A.col_); CSYMPY_ASSERT(b.row_ == A.row_ && b.col_ == 1); CSYMPY_ASSERT(x.row_ == A.col_ && x.col_ == 1); // No checks are done to see if the diagonal entries are zero for (unsigned i = 0; i < A.col_; i++) x.m_[i] = div(b.m_[i], A.m_[i*A.col_ + i]); }
void char_poly(const DenseMatrix &A, DenseMatrix &B) { CSYMPY_ASSERT(B.ncols() == 1 && B.nrows() == A.nrows() + 1); CSYMPY_ASSERT(A.nrows() == A.ncols()); std::vector<DenseMatrix> polys; berkowitz(A, polys); B = polys[polys.size() - 1]; }
// ------------------------------- Submatrix ---------------------------------// void submatrix_dense(const DenseMatrix &A, unsigned row_start, unsigned row_end, unsigned col_start, unsigned col_end, DenseMatrix &B) { CSYMPY_ASSERT(row_end > row_start && col_end > col_start); CSYMPY_ASSERT(B.row_ == row_end - row_start + 1 && B.col_ == col_end - col_start + 1); unsigned row = B.row_, col = B.col_; for (unsigned i = 0; i < row; i++) for (unsigned j = 0; j < col; j++) B.m_[i*col + j] = A.m_[(row_start + i - 1)*A.col_ + col_start - 1 + j]; }
void pivoted_fraction_free_gauss_jordan_elimination(const DenseMatrix &A, DenseMatrix &B, std::vector<unsigned> &pivotlist) { CSYMPY_ASSERT(A.row_ == B.row_ && A.col_ == B.col_); CSYMPY_ASSERT(pivotlist.size() == A.row_); unsigned row = A.row_, col = A.col_; unsigned index = 0, i, k, j; RCP<const Basic> d; B.m_ = A.m_; for (i = 0; i < row; i++) pivotlist[i] = i; for (i = 0; i < col; i++) { if (index == row) break; k = pivot(B, index, i); if (k == row) continue; if (k != index) { row_exchange_dense(B, k, index); std::swap(pivotlist[k], pivotlist[index]); } if (i > 0) d = B.m_[i*col - col + i - 1]; for (j = 0; j < row; j++) { if (j != i) for (k = 0; k < col; k++) { if (k != i) { B.m_[j*col + k] = sub(mul(B.m_[i*col + i], B.m_[j*col + k]), mul(B.m_[j*col + i], B.m_[i*col + k])); if (i > 0) B.m_[j*col + k] = div(B.m_[j*col + k], d); } } } for (j = 0; j < row; j++) if (j != i) B.m_[j*col + i] = zero; index++; } }
// Algorithm 2, page 13, Nakos, G. C., Turner, P. R., Williams, R. M. (1997). // Fraction-free algorithms for linear and polynomial equations. // ACM SIGSAM Bulletin, 31(3), 11–19. doi:10.1145/271130.271133. void fraction_free_gauss_jordan_elimination(const DenseMatrix &A, DenseMatrix &B) { CSYMPY_ASSERT(A.row_ == B.row_ && A.col_ == B.col_); unsigned row = A.row_, col = A.col_; unsigned i, j, k; RCP<const Basic> d; B.m_ = A.m_; for (i = 0; i < col; i++) { if (i > 0) d = B.m_[i*col - col + i - 1]; for (j = 0; j < row; j++) if (j != i) for (k = 0; k < col; k++) { if (k != i) { B.m_[j*col + k] = sub(mul(B.m_[i*col + i], B.m_[j*col + k]), mul(B.m_[j*col + i], B.m_[i*col + k])); if (i > 0) B.m_[j*col + k] = div(B.m_[j*col + k], d); } } for (j = 0; j < row; j++) if (j != i) B.m_[j*col + i] = zero; } }
void back_substitution(const DenseMatrix &U, const DenseMatrix &b, DenseMatrix &x) { CSYMPY_ASSERT(U.row_ == U.col_); CSYMPY_ASSERT(b.row_ == U.row_ && b.col_ == 1); CSYMPY_ASSERT(x.row_ == U.col_ && x.col_ == 1); unsigned col = U.col_; x.m_ = b.m_; for (int i = col - 1; i >= 0; i--) { for (unsigned j = i + 1; j < col; j++) x.m_[i] = sub(x.m_[i], mul(U.m_[i*col + j], x.m_[j])); x.m_[i] = div(x.m_[i], U.m_[i*col + i]); } }
void fraction_free_gauss_jordan_solve(const DenseMatrix &A, const DenseMatrix &b, DenseMatrix &x) { CSYMPY_ASSERT(A.row_ == A.col_); CSYMPY_ASSERT(b.row_ == A.row_ && x.row_ == A.row_); CSYMPY_ASSERT(x.col_ = b.col_); unsigned i, j, k, col = A.col_, bcol = b.col_; RCP<const Basic> d; DenseMatrix A_ = DenseMatrix(A.row_, A.col_, A.m_); DenseMatrix b_ = DenseMatrix(b.row_, b.col_, b.m_); for (i = 0; i < col; i++) { if (i > 0) d = A_.m_[i*col - col + i - 1]; for (j = 0; j < col; j++) if (j != i) { for (k = 0; k < bcol; k++) { b_.m_[j*bcol + k] = sub(mul(A_.m_[i*col + i], b_.m_[j*bcol + k]), mul(A_.m_[j*col + i], b_.m_[i*bcol + k])); if (i > 0) b_.m_[j*bcol + k] = div(b_.m_[j*bcol + k], d); } for (k = 0; k < col; k++) { if (k != i) { A_.m_[j*col + k] = sub(mul(A_.m_[i*col + i], A_.m_[j*col + k]), mul(A_.m_[j*col + i], A_.m_[i*col + k])); if (i > 0) A_.m_[j*col + k] = div(A_.m_[j*col + k], d); } } } for (j = 0; j < col; j++) if (j != i) A_.m_[j*col + i] = zero; } // No checks are done to see if the diagonal entries are zero for (k = 0; k < bcol; k++) for (i = 0; i < col; i++) x.m_[i*bcol + k] = div(b_.m_[i*bcol + k], A_.m_[i*col + i]); }
// -------------------------------- Row Operations ---------------------------// void row_exchange_dense(DenseMatrix &A , unsigned i, unsigned j) { CSYMPY_ASSERT(i != j && i < A.row_ && j < A.row_); unsigned col = A.col_; for (unsigned k = 0; k < A.col_; k++) std::swap(A.m_[i*col + k], A.m_[j*col + k]); }
void forward_substitution(const DenseMatrix &A, const DenseMatrix &b, DenseMatrix &x) { CSYMPY_ASSERT(A.row_ == A.col_); CSYMPY_ASSERT(b.row_ == A.row_ && b.col_ == 1); CSYMPY_ASSERT(x.row_ == A.col_ && x.col_ == 1); unsigned col = A.col_; x.m_ = b.m_; for (unsigned i = 0; i < col - 1; i++) for (unsigned j = i + 1; j < col; j++) { x.m_[j] = sub(mul(A.m_[i*col + i], x.m_[j]), mul(A.m_[j*col + i], x.m_[i])); if (i > 0) x.m_[j] = div(x.m_[j], A.m_[i*col - col + i - 1]); } }
void row_mul_scalar_dense(DenseMatrix &A, unsigned i, RCP<const Basic> &c) { CSYMPY_ASSERT(i < A.row_); unsigned col = A.col_; for (unsigned j = 0; j < A.col_; j++) A.m_[i*col + j] = mul(c, A.m_[i*col + j]); }
void fraction_free_gaussian_elimination_solve(const DenseMatrix &A, const DenseMatrix &b, DenseMatrix &x) { CSYMPY_ASSERT(A.row_ == A.col_); CSYMPY_ASSERT(b.row_ == A.row_ && x.row_ == A.row_); CSYMPY_ASSERT(x.col_ == b.col_); int i, j, k, col = A.col_, bcol = b.col_; DenseMatrix A_ = DenseMatrix(A.row_, A.col_, A.m_); DenseMatrix b_ = DenseMatrix(b.row_, b.col_, b.m_); for (i = 0; i < col - 1; i++) for (j = i + 1; j < col; j++) { for (k = 0; k < bcol; k++) { b_.m_[j*bcol + k] = sub(mul(A_.m_[i*col + i], b_.m_[j*bcol + k]), mul(A_.m_[j*col + i], b_.m_[i*bcol + k])); if(i > 0) b_.m_[j*bcol + k] = div(b_.m_[j*bcol + k], A_.m_[i*col - col + i - 1]); } for (k = i + 1; k < col; k++) { A_.m_[j*col + k] = sub(mul(A_.m_[i*col + i], A_.m_[j*col + k]), mul(A_.m_[j*col + i], A_.m_[i*col + k])); if (i> 0) A_.m_[j*col + k] = div(A_.m_[j*col + k], A_.m_[i*col - col + i - 1]); } A_.m_[j*col + i] = zero; } for (i = 0; i < col*bcol; i++) x.m_[i] = zero; // Integer zero; for (k = 0; k < bcol; k++) { for (i = col - 1; i >= 0; i--) { for (j = i + 1; j < col; j++) b_.m_[i*bcol + k] = sub(b_.m_[i*bcol + k], mul(A_.m_[i*col + j], x.m_[j*bcol + k])); x.m_[i*bcol + k] = div(b_.m_[i*bcol + k], A_.m_[i*col + i]); } } }
// ----------------------------- Matrix Transpose ----------------------------// void transpose_dense(const DenseMatrix &A, DenseMatrix &B) { CSYMPY_ASSERT(B.row_ == A.row_ && B.col_ == A.col_); unsigned row = A.row_, col = A.col_; for (unsigned i = 0; i < row; i++) for (unsigned j = 0; j < col; j++) B.m_[j*col + i] = A.m_[i*col + j]; }
void row_add_row_dense(DenseMatrix &A, unsigned i, unsigned j, RCP<const Basic> &c) { CSYMPY_ASSERT(i != j && i < A.row_ && j < A.row_); unsigned col = A.col_; for (unsigned k = 0; k < A.col_; k++) A.m_[i*col + k] = add(A.m_[i*col + k], mul(c, A.m_[j*col + k])); }
// SymPy's fraction free LU decomposition, without pivoting // sympy.matrices.matrices.MatrixBase.LUdecompositionFF // W. Zhou & D.J. Jeffrey, "Fraction-free matrix factors: new forms for LU and QR factors". // Frontiers in Computer Science in China, Vol 2, no. 1, pp. 67-80, 2008. void fraction_free_LDU(const DenseMatrix &A, DenseMatrix &L, DenseMatrix &D, DenseMatrix &U) { CSYMPY_ASSERT(A.row_ == L.row_ && A.row_ == U.row_); CSYMPY_ASSERT(A.col_ == L.col_ && A.col_ == U.col_); unsigned row = A.row_, col = A.col_; unsigned i, j, k; RCP<const Basic> old = integer(1); U.m_ = A.m_; // Initialize L for (i = 0; i < row; i++) for (j = 0; j < row; j++) if (i != j) L.m_[i*col + j] = zero; else L.m_[i*col + i] = one; // Initialize D for (i = 0; i < row*row; i++) D.m_[i] = zero; // Integer zero for (k = 0; k < row - 1; k++) { L.m_[k*col + k] = U.m_[k*col + k]; D.m_[k*col + k] = mul(old, U.m_[k*col + k]); for (i = k + 1; i < row; i++) { L.m_[i*col + k] = U.m_[i*col + k]; for (j = k + 1; j < col; j++) U.m_[i*col + j] = div(sub(mul(U.m_[k*col + k], U.m_[i*col + j]), mul(U.m_[k*col + j], U.m_[i*col + k])), old); U.m_[i*col + k] = zero; // Integer zero } old = U.m_[k*col + k]; } D.m_[row*col - col + row - 1] = old; }
void pivoted_gauss_jordan_elimination(const DenseMatrix &A, DenseMatrix &B, std::vector<unsigned> &pivotlist) { CSYMPY_ASSERT(A.row_ == B.row_ && A.col_ == B.col_); CSYMPY_ASSERT(pivotlist.size() == A.row_); unsigned row = A.row_, col = A.col_; unsigned index = 0, i, j, k; RCP<const Basic> scale; B.m_ = A.m_; for (i = 0; i < row; i++) pivotlist[i] = i; for (i = 0; i < col; i++) { if (index == row) break; k = pivot(B, index, i); if (k == row) continue; if (k != index) { row_exchange_dense(B, k, index); std::swap(pivotlist[k], pivotlist[index]); } scale = div(one, B.m_[index*col + i]); row_mul_scalar_dense(B, index, scale); for (j = 0; j < row; j++) { if (j == index) continue; scale = mul(minus_one, B.m_[j*col + i]); row_add_row_dense(B, j, index, scale); } index++; } }
void mul_dense_scalar(const DenseMatrix &A, RCP<const Basic> &k, DenseMatrix& B) { CSYMPY_ASSERT(A.col_ == B.col_ && A.row_ == B.row_); std::vector<RCP<const Basic>>::const_iterator ait = A.m_.begin(); std::vector<RCP<const Basic>>::iterator bit = B.m_.begin(); while (ait != A.m_.end()) { *bit = mul(*ait, k); ait++; bit++; } }
// SymPy LUDecomposition algorithm, in sympy.matrices.matrices.Matrix.LUdecomposition // with no pivoting void LU(const DenseMatrix &A, DenseMatrix &L, DenseMatrix &U) { CSYMPY_ASSERT(A.row_ == A.col_ && L.row_ == L.col_ && U.row_ == U.col_); CSYMPY_ASSERT(A.row_ == L.row_ && A.row_ == U.row_); unsigned n = A.row_; unsigned i, j, k; RCP<const Basic> scale; U.m_ = A.m_; for (j = 0; j < n; j++) { for (i = 0; i < j; i++) for (k = 0; k < i; k++) U.m_[i*n + j] = sub(U.m_[i*n + j], mul(U.m_[i*n + k], U.m_[k*n + j])); for (i = j; i < n; i++) { for (k = 0; k < j; k++) U.m_[i*n + j] = sub(U.m_[i*n + j], mul(U.m_[i*n + k], U.m_[k*n + j])); } scale = div(one, U.m_[j*n + j]); for (i = j + 1; i < n; i++) U.m_[i*n + j] = mul(U.m_[i*n + j], scale); } for(i = 0; i < n; i++) { for(j = 0; j < i; j++) { L.m_[i*n + j] = U.m_[i*n + j]; U.m_[i*n + j] = zero; // Integer zero } L.m_[i*n + i] = one; // Integer one for (j = i + 1; j < n; j++) L.m_[i*n + j] = zero; // Integer zero } }
// SymPy's QRecomposition in sympy.matrices.matrices.MatrixBase.QRdecomposition // Rank check is not performed void QR(const DenseMatrix &A, DenseMatrix &Q, DenseMatrix &R) { unsigned row = A.row_; unsigned col = A.col_; CSYMPY_ASSERT(Q.row_ == row && Q.col_ == col && R.row_ == col && R.col_ == col); unsigned i, j, k; RCP<const Basic> t; std::vector<RCP<const Basic>> tmp (row); // Initialize Q for (i = 0; i < row*col; i++) Q.m_[i] = zero; // Initialize R for (i = 0; i < col*col; i++) R.m_[i] = zero; for (j = 0; j < col; j++) { // Use submatrix for this for (k = 0; k < row; k++) tmp[k] = A.m_[k*col + j]; for (i = 0; i < j; i++) { t = zero; for (k = 0; k < row; k++) t = add(t, mul(A.m_[k*col + j], Q.m_[k*col + i])); for (k = 0; k < row; k++) tmp[k] = expand(sub(tmp[k], mul(Q.m_[k*col + i], t))); } // calculate norm t = zero; for (k = 0; k < row; k++) t = add(t, pow(tmp[k], integer(2))); t = pow(t, div(one, integer(2))); R.m_[j*col + j] = t; for (k = 0; k < row; k++) Q.m_[k*col + j] = div(tmp[k], t); for (i = 0; i < j; i++) { t = zero; for (k = 0; k < row; k++) t = add(t, mul(Q.m_[k*col + i], A.m_[k*col + j])); R.m_[i*col + j] = t; } } }
// ------------------------------- Matrix Addition ---------------------------// void add_dense_dense(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &C) { CSYMPY_ASSERT(A.row_ == B.row_ && A.col_ == B.col_ && A.row_ == C.row_ && A.col_ == C.col_); std::vector<RCP<const Basic>>::const_iterator ait = A.m_.begin(); std::vector<RCP<const Basic>>::const_iterator bit = B.m_.begin(); std::vector<RCP<const Basic>>::iterator cit = C.m_.begin(); while(ait != A.m_.end()) { *cit = add(*ait, *bit); ait++; bit++; cit++; } }
// SymPy's LDL decomposition, Assuming A is a symmetric, square, positive // definite non singular matrix void LDL(const DenseMatrix &A, DenseMatrix &L, DenseMatrix &D) { CSYMPY_ASSERT(A.row_ == A.col_); CSYMPY_ASSERT(L.row_ == A.row_ && L.col_ == A.row_); CSYMPY_ASSERT(D.row_ == A.row_ && D.col_ == A.row_); unsigned col = A.col_; unsigned i, k, j; RCP<const Basic> sum; RCP<const Basic> i2 = integer(2); // Initialize D for (i = 0; i < col; i++) for (j = 0; j < col; j++) D.m_[i*col + j] = zero; // Integer zero // Initialize L for (i = 0; i < col; i++) for (j = 0; j < col; j++) L.m_[i*col + j] = (i != j) ? zero : one; for (i = 0; i < col; i++) { for (j = 0; j < i; j++) { sum = zero; for (k = 0; k < j; k++) sum = add(sum, mul(mul(L.m_[i*col + k], L.m_[j*col + k]), D.m_[k*col + k])); L.m_[i*col + j] = mul(div(one, D.m_[j*col + j]), sub(A.m_[i*col + j], sum)); } sum = zero; for (k = 0; k < i; k++) sum = add(sum, mul(pow(L.m_[i*col + k], i2), D.m_[k*col + k])); D.m_[i*col + i] = sub(A.m_[i*col + i], sum); } }
// ------------------------------- Matrix Multiplication ---------------------// void mul_dense_dense(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &C) { CSYMPY_ASSERT(A.col_ == B.row_ && C.row_ == A.row_ && C.col_ == B.col_); unsigned row = A.row_, col = B.col_; for (unsigned r = 0; r<row; r++) { for (unsigned c = 0; c<col; c++) { C.m_[r*col + c] = zero; // Integer Zero for (unsigned k = 0; k<A.col_; k++) C.m_[r*col + c] = add(C.m_[r*col + c], mul(A.m_[r*A.col_ + k], B.m_[k*col + c])); } } }
// Algorithm 3, page 14, Nakos, G. C., Turner, P. R., Williams, R. M. (1997). // Fraction-free algorithms for linear and polynomial equations. // ACM SIGSAM Bulletin, 31(3), 11–19. doi:10.1145/271130.271133. // This algorithms is not a true factorization of the matrix A(i.e. A != LU)) // but can be used to solve linear systems by applying forward and backward // substitutions respectively. void fraction_free_LU(const DenseMatrix &A, DenseMatrix &LU) { CSYMPY_ASSERT(A.row_ == A.col_ && LU.row_ == LU.col_ && A.row_ == LU.row_); unsigned n = A.row_; unsigned i, j, k; LU.m_ = A.m_; for (i = 0; i < n - 1; i++) for (j = i + 1; j < n; j++) for (k = i + 1; k < n; k++) { LU.m_[j*n + k] = sub(mul(LU.m_[i*n + i], LU.m_[j*n + k]), mul(LU.m_[j*n + i], LU.m_[i*n + k])); if (i) LU.m_[j*n + k] = div(LU.m_[j*n + k], LU.m_[i*n - n + i - 1]); } }
// Algorithm 1, page 12, Nakos, G. C., Turner, P. R., Williams, R. M. (1997). // Fraction-free algorithms for linear and polynomial equations. // ACM SIGSAM Bulletin, 31(3), 11–19. doi:10.1145/271130.271133. void fraction_free_gaussian_elimination(const DenseMatrix &A, DenseMatrix &B) { CSYMPY_ASSERT(A.row_ == B.row_ && A.col_ == B.col_); unsigned col = A.col_; B.m_ = A.m_; for (unsigned i = 0; i < col - 1; i++) for (unsigned j = i + 1; j < A.row_; j++) { for (unsigned k = i + 1; k < col; k++) { B.m_[j*col + k] = sub(mul(B.m_[i*col + i], B.m_[j*col + k]), mul(B.m_[j*col + i], B.m_[i*col + k])); if (i > 0) B.m_[j*col + k] = div(B.m_[j*col + k], B.m_[i*col - col + i - 1]); } B.m_[j*col + i] = zero; } }
void inverse_gauss_jordan(const DenseMatrix &A, DenseMatrix &B) { CSYMPY_ASSERT(A.row_ == A.col_ && B.row_ == B.col_ && B.row_ == A.row_); unsigned n = A.row_; DenseMatrix e = DenseMatrix(n, n); // Initialize matrices for (unsigned i = 0; i < n; i++) for (unsigned j = 0; j < n; j++) { if (i != j) { e.m_[i*n + j] = zero; } else { e.m_[i*n + i] = one; } B.m_[i*n + j] = zero; } fraction_free_gauss_jordan_solve(A, e, B); }
void inverse_LU(const DenseMatrix &A, DenseMatrix&B) { CSYMPY_ASSERT(A.row_ == A.col_ && B.row_ == B.col_ && B.row_ == A.row_); unsigned n = A.row_, i; DenseMatrix L = DenseMatrix(n, n); DenseMatrix U = DenseMatrix(n, n); DenseMatrix e = DenseMatrix(n, 1); DenseMatrix x = DenseMatrix(n, 1); DenseMatrix x_ = DenseMatrix(n, 1); // Initialize matrices for (i = 0; i < n*n; i++) { L.m_[i] = zero; U.m_[i] = zero; B.m_[i] = zero; } for (i = 0; i < n; i++) { e.m_[i] = zero; x.m_[i] = zero; x_.m_[i] = zero; } LU(A, L, U); // We solve AX_{i} = e_{i} for i = 1, 2, .. n and combine the column vectors // X_{1}, X_{2}, ... X_{n} to form the inverse of A. Here, e_{i}'s are the // elements of the standard basis. for (unsigned j = 0; j < n; j++) { e.m_[j] = one; forward_substitution(L, e, x_); back_substitution(U, x_, x); for (i = 0; i < n; i++) B.m_[i*n + j] = x.m_[i]; e.m_[j] = zero; } }
Sec::Sec(const RCP<const Basic> &arg) { CSYMPY_ASSERT(is_canonical(arg)) set_arg(arg); }
// Returns the coefficients of characterisitc polynomials of leading principal // minors of Matrix A as elements in `polys`. Principal leading minor of kth // order is the submatrix of A obtained by deleting last n-k rows and columns // from A. Here `n` is the dimension of the square matrix A. void berkowitz(const DenseMatrix &A, std::vector<DenseMatrix> &polys) { CSYMPY_ASSERT(A.row_ == A.col_); unsigned col = A.col_; unsigned i, k, l, m; std::vector<DenseMatrix> items; std::vector<DenseMatrix> transforms; std::vector<RCP<const Basic>> items_; for (unsigned n = col; n > 1; n--) { items.clear(); k = n - 1; DenseMatrix T = DenseMatrix(n + 1, n); DenseMatrix C = DenseMatrix(k, 1); // Initialize T and C for (i = 0; i < n*(n + 1); i++) T.m_[i] = zero; for (i = 0; i < k; i++) C.m_[i] = A.m_[i*col + k]; items.push_back(C); for (i = 0; i < n - 2; i++) { DenseMatrix B = DenseMatrix(k, 1); for (l = 0; l < k; l++) { B.m_[l] = zero; for (m = 0; m < k; m++) B.m_[l] = add(B.m_[l], mul(A.m_[l*col + m], items[i].m_[m])); } items.push_back(B); } items_.clear(); for (i = 0; i < n - 1; i++) { RCP<const Basic> element = zero; for (l = 0; l < k; l++) element = add(element, mul(A.m_[k*col + l], items[i].m_[l])); items_.push_back(mul(minus_one, element)); } items_.insert(items_.begin(), mul(minus_one, A.m_[k*col + k])); items_.insert(items_.begin(), one); for (i = 0; i < n; i++) { for (l = 0; l < n - i + 1; l++) T.m_[(i + l)*n + i] = items_[l]; } transforms.push_back(T); } polys.push_back(DenseMatrix(2, 1, {one, mul(A.m_[0], minus_one)})); for(i = 0; i < col - 1; i++) { unsigned t_row = transforms[col - 2 - i].nrows(); unsigned t_col = transforms[col - 2 - i].ncols(); DenseMatrix B = DenseMatrix(t_row, 1); for (l = 0; l < t_row; l++) { B.m_[l] = zero; for (m = 0; m < t_col; m++) { B.m_[l] = add(B.m_[l], mul(transforms[col - 2 - i].m_[l*t_col + m], polys[i].m_[m])); B.m_[l] = expand(B.m_[l]); } } polys.push_back(B); } }
// ----------------------------- Determinant ---------------------------------// RCP<const Basic> det_bareis(const DenseMatrix &A) { CSYMPY_ASSERT(A.row_ == A.col_); unsigned n = A.row_; if (n == 1) { return A.m_[0]; } else if(n == 2) { // If A = [[a, b], [c, d]] then det(A) = ad - bc return sub(mul(A.m_[0], A.m_[3]), mul(A.m_[1], A.m_[2])); } else if (n == 3) { // if A = [[a, b, c], [d, e, f], [g, h, i]] then // det(A) = (aei + bfg + cdh) - (ceg + bdi + afh) return sub( add( add( mul(mul(A.m_[0], A.m_[4]), A.m_[8]), mul(mul(A.m_[1], A.m_[5]), A.m_[6]) ), mul(mul(A.m_[2], A.m_[3]), A.m_[7]) ), add( add( mul(mul(A.m_[2], A.m_[4]), A.m_[6]), mul(mul(A.m_[1], A.m_[3]), A.m_[8]) ), mul(mul(A.m_[0], A.m_[5]), A.m_[7]) ) ); } else { DenseMatrix B = DenseMatrix(n, n, A.m_); unsigned i, sign = 1; RCP<const Basic> d; for (unsigned k = 0; k < n - 1; k++) { if (eq(B.m_[k*n + k], zero)) { for (i = k + 1; i < n; i++) if (neq(B.m_[i*n + k], zero)) { row_exchange_dense(B, i, k); sign *= -1; break; } if (i == n) return zero; } for (i = k + 1; i < n; i++) { for (unsigned j = k + 1; j < n; j++) { d = sub(mul(B.m_[k*n + k], B.m_[i*n + j]), mul(B.m_[i*n + k], B.m_[k*n + j])); if (k > 0) d = div(d, B.m_[(k-1)*n + k - 1]); B.m_[i*n + j] = d; } } } return (sign == 1) ? B.m_[n*n - 1] : mul(minus_one, B.m_[n*n - 1]); } }
void DenseMatrix::set(unsigned i, unsigned j, const RCP<const Basic> &e) { CSYMPY_ASSERT(i < row_ && j < col_); m_[i*col_ + j] = e; }