// ----------------------------- Determinant ---------------------------------// RCP<const Basic> det_bareis(const DenseMatrix &A) { SYMENGINE_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 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++; } }
void pivoted_fraction_free_gauss_jordan_elimination(const DenseMatrix &A, DenseMatrix &B, permutelist &pl) { SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_); 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 < col; i++) { if (index == row) break; k = pivot(B, index, i); if (k == row) continue; if (k != index) { row_exchange_dense(B, k, index); pl.push_back({k, 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++; } }
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++; } }
// SymPy LUDecomposition_Simple algorithm, in // sympy.matrices.matrices.Matrix.LUdecomposition_Simple with pivoting. // P must be an initialized matrix and will be permuted. void pivoted_LU(const DenseMatrix &A, DenseMatrix &LU, permutelist &pl) { SYMENGINE_ASSERT(A.row_ == A.col_ and LU.row_ == LU.col_); SYMENGINE_ASSERT(A.row_ == LU.row_); unsigned n = A.row_; unsigned i, j, k; RCP<const Basic> scale; int pivot; LU.m_ = A.m_; for (j = 0; j < n; j++) { for (i = 0; i < j; i++) for (k = 0; k < i; k++) LU.m_[i * n + j] = sub(LU.m_[i * n + j], mul(LU.m_[i * n + k], LU.m_[k * n + j])); pivot = -1; for (i = j; i < n; i++) { for (k = 0; k < j; k++) { LU.m_[i * n + j] = sub(LU.m_[i * n + j], mul(LU.m_[i * n + k], LU.m_[k * n + j])); } if (pivot == -1 and neq(*LU.m_[i * n + j], *zero)) pivot = i; } if (pivot == -1) throw SymEngineException("Matrix is rank deficient"); if (pivot - j != 0) { // row must be swapped row_exchange_dense(LU, pivot, j); pl.push_back({pivot, j}); } scale = div(one, LU.m_[j * n + j]); for (i = j + 1; i < n; i++) LU.m_[i * n + j] = mul(LU.m_[i * n + j], scale); } }
// ------------------------------ Gaussian Elimination -----------------------// void pivoted_gaussian_elimination(const DenseMatrix &A, DenseMatrix &B, permutelist &pl) { SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_); unsigned row = A.row_, col = A.col_; unsigned index = 0, i, j, k; B.m_ = A.m_; RCP<const Basic> scale; for (i = 0; i < col - 1; i++) { if (index == row) break; k = pivot(B, index, i); if (k == row) continue; if (k != index) { row_exchange_dense(B, k, index); pl.push_back({k, index}); } scale = div(one, B.m_[index * col + i]); row_mul_scalar_dense(B, index, scale); for (j = i + 1; j < row; j++) { for (k = i + 1; k < col; k++) B.m_[j * col + k] = sub(B.m_[j * col + k], mul(B.m_[j * col + i], B.m_[i * col + k])); B.m_[j * col + i] = zero; } index++; } }
void pivoted_gauss_jordan_elimination(const DenseMatrix &A, DenseMatrix &B, permutelist &pl) { SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_); 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 < col; i++) { if (index == row) break; k = pivot(B, index, i); if (k == row) continue; if (k != index) { row_exchange_dense(B, k, index); pl.push_back({k, 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 permuteFwd(DenseMatrix &A, permutelist &pl) { for (auto &p : pl) { row_exchange_dense(A, p.first, p.second); } }