1 #include <symengine/matrix.h>
6 #include <symengine/subs.h>
7 #include <symengine/symengine_exception.h>
8 #include <symengine/polys/uexprpoly.h>
10 #include <symengine/test_visitors.h>
16 DenseMatrix::DenseMatrix() {}
18 DenseMatrix::DenseMatrix(
unsigned row,
unsigned col) : row_(row), col_(col)
23 DenseMatrix::DenseMatrix(
unsigned row,
unsigned col,
const vec_basic &l)
24 : m_{l}, row_(row), col_(col){SYMENGINE_ASSERT(m_.size() == row * col)}
26 DenseMatrix::DenseMatrix(
const vec_basic &column_elements)
27 : m_(column_elements), row_(static_cast<unsigned>(column_elements.size())),
33 void DenseMatrix::resize(
unsigned row,
unsigned col)
41 RCP<const Basic> DenseMatrix::get(
unsigned i,
unsigned j)
const
43 SYMENGINE_ASSERT(i < row_ and j < col_);
44 return m_[i * col_ + j];
47 void DenseMatrix::set(
unsigned i,
unsigned j,
const RCP<const Basic> &e)
49 SYMENGINE_ASSERT(i < row_ and j < col_);
54 vec_basic DenseMatrix::as_vec_basic()
const
59 RCP<const Basic> DenseMatrix::trace()
const
61 SYMENGINE_ASSERT(row_ == col_);
64 for (
unsigned i = 0; i < row_; i++) {
65 diag.push_back(m_[offset]);
72 unsigned DenseMatrix::rank()
const
74 throw NotImplementedError(
"Not Implemented");
77 bool DenseMatrix::is_lower()
const
80 unsigned n = A.nrows();
81 for (
unsigned i = 1; i < n; ++i) {
82 for (
unsigned j = 0; j < i; ++j) {
91 bool DenseMatrix::is_upper()
const
94 unsigned n = A.nrows();
95 for (
unsigned i = 0; i < n - 1; ++i) {
96 for (
unsigned j = i + 1; j < n; ++j) {
108 tribool cur = tribool::tritrue;
110 cur = and_tribool(cur, SymEngine::is_zero(*e));
118 tribool DenseMatrix::is_diagonal()
const
121 if (not A.is_square()) {
122 return tribool::trifalse;
124 unsigned ncols = A.ncols();
126 tribool cur = tribool::tritrue;
127 for (
unsigned i = 0; i < ncols; i++) {
129 for (
unsigned j = 0; j < ncols; j++) {
131 auto &e = m_[offset];
132 cur = and_tribool(cur, SymEngine::is_zero(*e));
143 tribool DenseMatrix::is_real(
const Assumptions *assumptions)
const
145 RealVisitor visitor(assumptions);
146 tribool cur = tribool::tritrue;
148 cur = and_tribool(cur, visitor.apply(*e));
156 tribool DenseMatrix::is_symmetric()
const
159 if (not A.is_square()) {
160 return tribool::trifalse;
162 unsigned ncols = A.ncols();
163 tribool cur = tribool::tritrue;
164 for (
unsigned i = 0; i < ncols; i++) {
165 for (
unsigned j = 0; j <= i; j++) {
167 auto &e = m_[i * ncols + j];
168 auto &e2 = m_[j * ncols + i];
169 cur = and_tribool(cur, SymEngine::is_zero(*
sub(e, e2)));
179 tribool DenseMatrix::is_hermitian()
const
182 if (not A.is_square()) {
183 return tribool::trifalse;
185 unsigned ncols = A.ncols();
186 tribool cur = tribool::tritrue;
187 for (
unsigned i = 0; i < ncols; i++) {
188 for (
unsigned j = 0; j <= i; j++) {
189 auto &e = m_[i * ncols + j];
191 auto &e2 = m_[j * ncols + i];
195 cur = and_tribool(cur, SymEngine::is_real(*e));
205 tribool DenseMatrix::is_weakly_diagonally_dominant()
const
208 if (not A.is_square()) {
209 return tribool::trifalse;
212 unsigned ncols = A.ncols();
213 RCP<const Basic> diag;
214 RCP<const Basic> sum;
215 tribool diagdom = tribool::tritrue;
216 for (
unsigned i = 0; i < ncols; i++) {
218 for (
unsigned j = 0; j < ncols; j++) {
219 auto &e = m_[i * ncols + j];
226 diagdom = and_tribool(diagdom, is_nonnegative(*
sub(diag, sum)));
227 if (is_false(diagdom)) {
234 tribool DenseMatrix::is_strictly_diagonally_dominant()
const
237 if (not A.is_square()) {
238 return tribool::trifalse;
241 unsigned ncols = A.ncols();
242 RCP<const Basic> diag;
243 RCP<const Basic> sum;
244 tribool diagdom = tribool::tritrue;
245 for (
unsigned i = 0; i < ncols; i++) {
247 for (
unsigned j = 0; j < ncols; j++) {
248 auto &e = m_[i * ncols + j];
255 diagdom = and_tribool(diagdom, is_positive(*
sub(diag, sum)));
256 if (is_false(diagdom)) {
263 tribool DenseMatrix::shortcut_to_posdef()
const
265 tribool is_diagonal_positive = tribool::tritrue;
267 for (
unsigned i = 0; i < row_; i++) {
269 = and_tribool(is_diagonal_positive, is_positive(*m_[offset]));
270 if (is_false(is_diagonal_positive))
271 return is_diagonal_positive;
274 if (is_true(and_tribool(is_diagonal_positive,
275 this->is_strictly_diagonally_dominant())))
276 return tribool::tritrue;
277 return tribool::indeterminate;
280 tribool DenseMatrix::is_positive_definite_GE()
283 for (
unsigned i = 0; i < size; i++) {
284 auto ispos = is_positive(*m_[i * size + i]);
287 for (
unsigned j = i + 1; j < size; j++) {
288 for (
unsigned k = i + 1; k < size; k++) {
289 m_[j * size + k] =
sub(
mul(m_[i * size + i], m_[j * size + k]),
290 mul(m_[j * size + i], m_[i * size + k]));
294 return tribool::tritrue;
297 tribool DenseMatrix::is_positive_definite()
const
302 const DenseMatrix *H;
303 if (!is_true(A.is_hermitian())) {
305 return tribool::trifalse;
306 DenseMatrix tmp1 = DenseMatrix(A.row_, A.col_);
308 A.conjugate_transpose(tmp1);
309 add_dense_dense(A, tmp1, *B.
get());
315 tribool shortcut = H->shortcut_to_posdef();
316 if (!is_indeterminate(shortcut))
322 return B->is_positive_definite_GE();
325 tribool DenseMatrix::is_negative_definite()
const
327 auto res = DenseMatrix(row_, col_);
328 mul_dense_scalar(*
this,
integer(-1), res);
329 return res.is_positive_definite();
332 RCP<const Basic> DenseMatrix::det()
const
334 return det_bareis(*
this);
337 void DenseMatrix::inv(MatrixBase &result)
const
339 if (is_a<DenseMatrix>(result)) {
340 DenseMatrix &r = down_cast<DenseMatrix &>(result);
341 inverse_pivoted_LU(*
this, r);
345 void DenseMatrix::add_matrix(
const MatrixBase &other, MatrixBase &result)
const
347 SYMENGINE_ASSERT(row_ == result.nrows() and col_ == result.ncols());
349 if (is_a<DenseMatrix>(other) and is_a<DenseMatrix>(result)) {
350 const DenseMatrix &o = down_cast<const DenseMatrix &>(other);
351 DenseMatrix &r = down_cast<DenseMatrix &>(result);
352 add_dense_dense(*
this, o, r);
356 void DenseMatrix::mul_matrix(
const MatrixBase &other, MatrixBase &result)
const
358 SYMENGINE_ASSERT(row_ == result.nrows()
359 and other.ncols() == result.ncols());
361 if (is_a<DenseMatrix>(other) and is_a<DenseMatrix>(result)) {
362 const DenseMatrix &o = down_cast<const DenseMatrix &>(other);
363 DenseMatrix &r = down_cast<DenseMatrix &>(result);
364 mul_dense_dense(*
this, o, r);
368 void DenseMatrix::elementwise_mul_matrix(
const MatrixBase &other,
369 MatrixBase &result)
const
371 SYMENGINE_ASSERT(row_ == result.nrows() and col_ == result.ncols()
372 and row_ == other.nrows() and col_ == other.ncols());
374 if (is_a<DenseMatrix>(other) and is_a<DenseMatrix>(result)) {
375 const DenseMatrix &o = down_cast<const DenseMatrix &>(other);
376 DenseMatrix &r = down_cast<DenseMatrix &>(result);
377 elementwise_mul_dense_dense(*
this, o, r);
382 void DenseMatrix::add_scalar(
const RCP<const Basic> &k,
383 MatrixBase &result)
const
385 if (is_a<DenseMatrix>(result)) {
386 DenseMatrix &r = down_cast<DenseMatrix &>(result);
387 add_dense_scalar(*
this, k, r);
392 void DenseMatrix::mul_scalar(
const RCP<const Basic> &k,
393 MatrixBase &result)
const
395 if (is_a<DenseMatrix>(result)) {
396 DenseMatrix &r = down_cast<DenseMatrix &>(result);
397 mul_dense_scalar(*
this, k, r);
402 void DenseMatrix::conjugate(MatrixBase &result)
const
404 if (is_a<DenseMatrix>(result)) {
405 DenseMatrix &r = down_cast<DenseMatrix &>(result);
406 conjugate_dense(*
this, r);
411 void DenseMatrix::transpose(MatrixBase &result)
const
413 if (is_a<DenseMatrix>(result)) {
414 DenseMatrix &r = down_cast<DenseMatrix &>(result);
415 transpose_dense(*
this, r);
420 void DenseMatrix::conjugate_transpose(MatrixBase &result)
const
422 if (is_a<DenseMatrix>(result)) {
423 DenseMatrix &r = down_cast<DenseMatrix &>(result);
424 conjugate_transpose_dense(*
this, r);
429 void DenseMatrix::submatrix(MatrixBase &result,
unsigned row_start,
430 unsigned col_start,
unsigned row_end,
431 unsigned col_end,
unsigned row_step,
432 unsigned col_step)
const
434 if (is_a<DenseMatrix>(result)) {
435 DenseMatrix &r = down_cast<DenseMatrix &>(result);
436 submatrix_dense(*
this, r, row_start, col_start, row_end, col_end,
442 void DenseMatrix::LU(MatrixBase &L, MatrixBase &U)
const
444 if (is_a<DenseMatrix>(L) and is_a<DenseMatrix>(U)) {
445 DenseMatrix &L_ = down_cast<DenseMatrix &>(L);
446 DenseMatrix &U_ = down_cast<DenseMatrix &>(U);
447 SymEngine::LU(*
this, L_, U_);
452 void DenseMatrix::LDL(MatrixBase &L, MatrixBase &D)
const
454 if (is_a<DenseMatrix>(L) and is_a<DenseMatrix>(D)) {
455 DenseMatrix &L_ = down_cast<DenseMatrix &>(L);
456 DenseMatrix &D_ = down_cast<DenseMatrix &>(D);
457 SymEngine::LDL(*
this, L_, D_);
462 void DenseMatrix::LU_solve(
const MatrixBase &b, MatrixBase &x)
const
464 if (is_a<DenseMatrix>(b) and is_a<DenseMatrix>(x)) {
465 const DenseMatrix &b_ = down_cast<const DenseMatrix &>(b);
466 DenseMatrix &x_ = down_cast<DenseMatrix &>(x);
467 SymEngine::LU_solve(*
this, b_, x_);
472 void DenseMatrix::FFLU(MatrixBase &LU)
const
474 if (is_a<DenseMatrix>(LU)) {
475 DenseMatrix &LU_ = down_cast<DenseMatrix &>(LU);
476 fraction_free_LU(*
this, LU_);
481 void DenseMatrix::FFLDU(MatrixBase &L, MatrixBase &D, MatrixBase &U)
const
483 if (is_a<DenseMatrix>(L) and is_a<DenseMatrix>(D)
484 and is_a<DenseMatrix>(U)) {
485 DenseMatrix &L_ = down_cast<DenseMatrix &>(L);
486 DenseMatrix &D_ = down_cast<DenseMatrix &>(D);
487 DenseMatrix &U_ = down_cast<DenseMatrix &>(U);
488 fraction_free_LDU(*
this, L_, D_, U_);
493 void DenseMatrix::QR(MatrixBase &Q, MatrixBase &R)
const
495 if (is_a<DenseMatrix>(Q) and is_a<DenseMatrix>(R)) {
496 DenseMatrix &Q_ = down_cast<DenseMatrix &>(Q);
497 DenseMatrix &R_ = down_cast<DenseMatrix &>(R);
498 SymEngine::QR(*
this, Q_, R_);
503 void DenseMatrix::cholesky(MatrixBase &L)
const
505 if (is_a<DenseMatrix>(L)) {
506 DenseMatrix &L_ = down_cast<DenseMatrix &>(L);
507 SymEngine::cholesky(*
this, L_);
513 void jacobian(
const DenseMatrix &A,
const DenseMatrix &x, DenseMatrix &result,
516 SYMENGINE_ASSERT(A.col_ == 1);
517 SYMENGINE_ASSERT(x.col_ == 1);
518 SYMENGINE_ASSERT(A.row_ == result.nrows() and x.row_ == result.ncols());
520 #pragma omp parallel for
521 for (
unsigned i = 0; i < result.row_; i++) {
522 for (
unsigned j = 0; j < result.col_; j++) {
523 if (is_a<Symbol>(*(x.m_[j]))) {
524 const RCP<const Symbol> x_
525 = rcp_static_cast<const Symbol>(x.m_[j]);
526 result.m_[i * result.col_ + j] = A.m_[i]->diff(x_, diff_cache);
534 throw SymEngineException(
535 "'x' must contain Symbols only. "
536 "Use sjacobian for SymPy style differentiation");
540 void sjacobian(
const DenseMatrix &A,
const DenseMatrix &x, DenseMatrix &result,
543 SYMENGINE_ASSERT(A.col_ == 1);
544 SYMENGINE_ASSERT(x.col_ == 1);
545 SYMENGINE_ASSERT(A.row_ == result.nrows() and x.row_ == result.ncols());
546 #pragma omp parallel for
547 for (
unsigned i = 0; i < result.row_; i++) {
548 for (
unsigned j = 0; j < result.col_; j++) {
549 if (is_a<Symbol>(*(x.m_[j]))) {
550 const RCP<const Symbol> x_
551 = rcp_static_cast<const Symbol>(x.m_[j]);
552 result.m_[i * result.col_ + j] = A.m_[i]->diff(x_, diff_cache);
555 const RCP<const Symbol> x_ =
symbol(
"x_");
556 result.m_[i * result.col_ + j] =
ssubs(
557 ssubs(A.m_[i], {{x.m_[j], x_}})->diff(x_, diff_cache),
566 void diff(
const DenseMatrix &A,
const RCP<const Symbol> &x, DenseMatrix &result,
569 SYMENGINE_ASSERT(A.row_ == result.nrows() and A.col_ == result.ncols());
570 #pragma omp parallel for
571 for (
unsigned i = 0; i < result.row_; i++) {
572 for (
unsigned j = 0; j < result.col_; j++) {
573 result.m_[i * result.col_ + j]
574 = A.m_[i * result.col_ + j]->diff(x, diff_cache);
579 void sdiff(
const DenseMatrix &A,
const RCP<const Basic> &x, DenseMatrix &result,
582 SYMENGINE_ASSERT(A.row_ == result.nrows() and A.col_ == result.ncols());
583 #pragma omp parallel for
584 for (
unsigned i = 0; i < result.row_; i++) {
585 for (
unsigned j = 0; j < result.col_; j++) {
586 if (is_a<Symbol>(*x)) {
587 const RCP<const Symbol> x_ = rcp_static_cast<const Symbol>(x);
588 result.m_[i * result.col_ + j]
589 = A.m_[i * result.col_ + j]->diff(x_, diff_cache);
592 const RCP<const Symbol> x_ =
symbol(
"_x");
593 result.m_[i * result.col_ + j]
594 =
ssubs(
ssubs(A.m_[i * result.col_ + j], {{x, x_}})
595 ->diff(x_, diff_cache),
603 void conjugate_dense(
const DenseMatrix &A, DenseMatrix &B)
605 SYMENGINE_ASSERT(B.col_ == A.col_ and B.row_ == A.row_);
607 for (
unsigned i = 0; i < A.row_; i++)
608 for (
unsigned j = 0; j < A.col_; j++)
609 B.m_[i * B.col_ + j] =
conjugate(A.m_[i * A.col_ + j]);
613 void transpose_dense(
const DenseMatrix &A, DenseMatrix &B)
615 SYMENGINE_ASSERT(B.row_ == A.col_ and B.col_ == A.row_);
617 for (
unsigned i = 0; i < A.row_; i++)
618 for (
unsigned j = 0; j < A.col_; j++)
619 B.m_[j * B.col_ + i] = A.m_[i * A.col_ + j];
623 void conjugate_transpose_dense(
const DenseMatrix &A, DenseMatrix &B)
625 SYMENGINE_ASSERT(B.row_ == A.col_ and B.col_ == A.row_);
627 for (
unsigned i = 0; i < A.row_; i++)
628 for (
unsigned j = 0; j < A.col_; j++)
629 B.m_[j * B.col_ + i] =
conjugate(A.m_[i * A.col_ + j]);
633 void submatrix_dense(
const DenseMatrix &A, DenseMatrix &B,
unsigned row_start,
634 unsigned col_start,
unsigned row_end,
unsigned col_end,
635 unsigned row_step,
unsigned col_step)
637 SYMENGINE_ASSERT(row_end >= row_start and col_end >= col_start);
638 SYMENGINE_ASSERT(row_end < A.row_);
639 SYMENGINE_ASSERT(col_end < A.col_);
640 SYMENGINE_ASSERT(B.row_ == row_end - row_start + 1
641 and B.col_ == col_end - col_start + 1);
643 unsigned row = B.row_, col = B.col_;
645 for (
unsigned i = 0; i < row; i += row_step)
646 for (
unsigned j = 0; j < col; j += col_step)
647 B.m_[i * col + j] = A.m_[(row_start + i) * A.col_ + col_start + j];
651 void add_dense_dense(
const DenseMatrix &A,
const DenseMatrix &B, DenseMatrix &C)
653 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_ and A.row_ == C.row_
654 and A.col_ == C.col_);
656 unsigned row = A.row_, col = A.col_;
658 for (
unsigned i = 0; i < row; i++) {
659 for (
unsigned j = 0; j < col; j++) {
660 C.m_[i * col + j] =
add(A.m_[i * col + j], B.m_[i * col + j]);
665 void add_dense_scalar(
const DenseMatrix &A,
const RCP<const Basic> &k,
668 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
670 unsigned row = A.row_, col = A.col_;
672 for (
unsigned i = 0; i < row; i++) {
673 for (
unsigned j = 0; j < col; j++) {
674 B.m_[i * col + j] =
add(A.m_[i * col + j], k);
680 void mul_dense_dense(
const DenseMatrix &A,
const DenseMatrix &B, DenseMatrix &C)
682 SYMENGINE_ASSERT(A.col_ == B.row_ and C.row_ == A.row_
683 and C.col_ == B.col_);
685 unsigned row = A.row_, col = B.col_;
687 if (&A != &C and &B != &C) {
688 for (
unsigned r = 0; r < row; r++) {
689 for (
unsigned c = 0; c < col; c++) {
690 C.m_[r * col + c] = zero;
691 for (
unsigned k = 0; k < A.col_; k++)
693 =
add(C.m_[r * col + c],
694 mul(A.m_[r * A.col_ + k], B.m_[k * col + c]));
698 DenseMatrix tmp = DenseMatrix(A.row_, B.col_);
699 mul_dense_dense(A, B, tmp);
704 void elementwise_mul_dense_dense(
const DenseMatrix &A,
const DenseMatrix &B,
707 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_ and A.row_ == C.row_
708 and A.col_ == C.col_);
710 unsigned row = A.row_, col = A.col_;
712 for (
unsigned i = 0; i < row; i++) {
713 for (
unsigned j = 0; j < col; j++) {
714 C.m_[i * col + j] =
mul(A.m_[i * col + j], B.m_[i * col + j]);
719 void mul_dense_scalar(
const DenseMatrix &A,
const RCP<const Basic> &k,
722 SYMENGINE_ASSERT(A.col_ == B.col_ and A.row_ == B.row_);
724 unsigned row = A.row_, col = A.col_;
726 for (
unsigned i = 0; i < row; i++) {
727 for (
unsigned j = 0; j < col; j++) {
728 B.m_[i * col + j] =
mul(A.m_[i * col + j], k);
734 void DenseMatrix::row_join(
const DenseMatrix &B)
736 this->col_insert(B, col_);
739 void DenseMatrix::col_join(
const DenseMatrix &B)
741 this->row_insert(B, row_);
744 void DenseMatrix::row_insert(
const DenseMatrix &B,
unsigned pos)
746 SYMENGINE_ASSERT(col_ == B.col_ and pos <= row_)
748 unsigned row = row_, col = col_;
749 this->resize(row_ + B.row_, col_);
751 for (
unsigned i = row; i-- > pos;) {
752 for (
unsigned j = col; j-- > 0;) {
753 this->m_[(i + B.row_) * col + j] = this->m_[i * col + j];
757 for (
unsigned i = 0; i < B.row_; i++) {
758 for (
unsigned j = 0; j < col; j++) {
759 this->m_[(i + pos) * col + j] = B.m_[i * col + j];
764 void DenseMatrix::col_insert(
const DenseMatrix &B,
unsigned pos)
766 SYMENGINE_ASSERT(row_ == B.row_ and pos <= col_)
768 unsigned row = row_, col = col_;
769 this->resize(row_, col_ + B.col_);
771 for (
unsigned i = row; i-- > 0;) {
772 for (
unsigned j = col; j-- > 0;) {
774 this->m_[i * (col + B.col_) + j + B.col_]
775 = this->m_[i * col + j];
777 this->m_[i * (col + B.col_) + j] = this->m_[i * col + j];
782 for (
unsigned i = 0; i < row; i++) {
783 for (
unsigned j = 0; j < B.col_; j++) {
784 this->m_[i * (col + B.col_) + j + pos] = B.m_[i * B.col_ + j];
789 void DenseMatrix::row_del(
unsigned k)
791 SYMENGINE_ASSERT(k < row_)
796 for (
unsigned i = k; i < row_ - 1; i++) {
797 row_exchange_dense(*
this, i, i + 1);
799 this->resize(row_ - 1, col_);
803 void DenseMatrix::col_del(
unsigned k)
805 SYMENGINE_ASSERT(k < col_)
810 unsigned row = row_, col = col_, m = 0;
812 for (
unsigned i = 0; i < row; i++) {
813 for (
unsigned j = 0; j < col; j++) {
815 this->m_[m] = this->m_[i * col + j];
820 this->resize(row_, col_ - 1);
825 void row_exchange_dense(DenseMatrix &A,
unsigned i,
unsigned j)
827 SYMENGINE_ASSERT(i != j and i < A.row_ and j < A.row_);
829 unsigned col = A.col_;
831 for (
unsigned k = 0; k < A.col_; k++)
832 std::swap(A.m_[i * col + k], A.m_[j * col + k]);
835 void row_mul_scalar_dense(DenseMatrix &A,
unsigned i, RCP<const Basic> &c)
837 SYMENGINE_ASSERT(i < A.row_);
839 unsigned col = A.col_;
841 for (
unsigned j = 0; j < A.col_; j++)
842 A.m_[i * col + j] =
mul(c, A.m_[i * col + j]);
845 void row_add_row_dense(DenseMatrix &A,
unsigned i,
unsigned j,
848 SYMENGINE_ASSERT(i != j and i < A.row_ and j < A.row_);
850 unsigned col = A.col_;
852 for (
unsigned k = 0; k < A.col_; k++)
853 A.m_[i * col + k] =
add(A.m_[i * col + k],
mul(c, A.m_[j * col + k]));
856 void permuteFwd(DenseMatrix &A, permutelist &pl)
859 row_exchange_dense(A, p.first, p.second);
864 void column_exchange_dense(DenseMatrix &A,
unsigned i,
unsigned j)
866 SYMENGINE_ASSERT(i != j and i < A.col_ and j < A.col_);
868 unsigned col = A.col_;
870 for (
unsigned k = 0; k < A.row_; k++)
871 std::swap(A.m_[k * col + i], A.m_[k * col + j]);
875 void pivoted_gaussian_elimination(
const DenseMatrix &A, DenseMatrix &B,
878 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
880 unsigned row = A.row_, col = A.col_;
881 unsigned index = 0, i, j, k;
884 RCP<const Basic> scale;
886 for (i = 0; i < col - 1; i++) {
890 k = pivot(B, index, i);
894 row_exchange_dense(B, k, index);
895 pl.push_back({k, index});
898 scale =
div(one, B.m_[index * col + i]);
899 row_mul_scalar_dense(B, index, scale);
901 for (j = i + 1; j < row; j++) {
902 for (k = i + 1; k < col; k++)
904 =
sub(B.m_[j * col + k],
905 mul(B.m_[j * col + i], B.m_[i * col + k]));
906 B.m_[j * col + i] = zero;
916 void fraction_free_gaussian_elimination(
const DenseMatrix &A, DenseMatrix &B)
918 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
920 unsigned col = A.col_;
923 for (
unsigned i = 0; i < col - 1; i++)
924 for (
unsigned j = i + 1; j < A.row_; j++) {
925 for (
unsigned k = i + 1; k < col; k++) {
927 =
sub(
mul(B.m_[i * col + i], B.m_[j * col + k]),
928 mul(B.m_[j * col + i], B.m_[i * col + k]));
931 =
div(B.m_[j * col + k], B.m_[i * col - col + i - 1]);
933 B.m_[j * col + i] = zero;
938 void pivoted_fraction_free_gaussian_elimination(
const DenseMatrix &A,
939 DenseMatrix &B, permutelist &pl)
941 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
943 unsigned col = A.col_, row = A.row_;
944 unsigned index = 0, i, k, j;
947 for (i = 0; i < col - 1; i++) {
951 k = pivot(B, index, i);
955 row_exchange_dense(B, k, index);
956 pl.push_back({k, index});
959 for (j = i + 1; j < row; j++) {
960 for (k = i + 1; k < col; k++) {
962 =
sub(
mul(B.m_[i * col + i], B.m_[j * col + k]),
963 mul(B.m_[j * col + i], B.m_[i * col + k]));
966 =
div(B.m_[j * col + k], B.m_[i * col - col + i - 1]);
968 B.m_[j * col + i] = zero;
975 void pivoted_gauss_jordan_elimination(
const DenseMatrix &A, DenseMatrix &B,
978 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
980 unsigned row = A.row_, col = A.col_;
981 unsigned index = 0, i, j, k;
982 RCP<const Basic> scale;
985 for (i = 0; i < col; i++) {
989 k = pivot(B, index, i);
993 row_exchange_dense(B, k, index);
994 pl.push_back({k, index});
997 scale =
div(one, B.m_[index * col + i]);
998 row_mul_scalar_dense(B, index, scale);
1000 for (j = 0; j < row; j++) {
1004 scale =
mul(minus_one, B.m_[j * col + i]);
1005 row_add_row_dense(B, j, index, scale);
1015 void fraction_free_gauss_jordan_elimination(
const DenseMatrix &A,
1018 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
1020 unsigned row = A.row_, col = A.col_;
1026 for (i = 0; i < col; i++) {
1028 d = B.m_[i * col - col + i - 1];
1029 for (j = 0; j < row; j++)
1031 for (k = 0; k < col; k++) {
1034 =
sub(
mul(B.m_[i * col + i], B.m_[j * col + k]),
1035 mul(B.m_[j * col + i], B.m_[i * col + k]));
1037 B.m_[j * col + k] =
div(B.m_[j * col + k], d);
1040 for (j = 0; j < row; j++)
1042 B.m_[j * col + i] = zero;
1046 void pivoted_fraction_free_gauss_jordan_elimination(
const DenseMatrix &A,
1050 SYMENGINE_ASSERT(A.row_ == B.row_ and A.col_ == B.col_);
1052 unsigned row = A.row_, col = A.col_;
1053 unsigned index = 0, i, k, j;
1058 for (i = 0; i < col; i++) {
1062 k = pivot(B, index, i);
1066 row_exchange_dense(B, k, index);
1067 pl.push_back({k, index});
1070 for (j = 0; j < row; j++) {
1073 for (k = 0; k < col; k++) {
1077 =
sub(
mul(B.m_[index * col + i], B.m_[j * col + k]),
1078 mul(B.m_[j * col + i], B.m_[index * col + k]));
1081 B.m_[j * col + k] =
div(B.m_[j * col + k], d);
1085 d = B.m_[index * col + i];
1087 for (j = 0; j < row; j++) {
1090 B.m_[j * col + i] = zero;
1096 unsigned pivot(DenseMatrix &B,
unsigned r,
unsigned c)
1098 for (
unsigned k = r; k < B.row_; k++) {
1099 if (!is_true(
is_zero(*(B.m_[k * B.col_ + c])))) {
1106 void reduced_row_echelon_form(
const DenseMatrix &A, DenseMatrix &b,
1107 vec_uint &pivot_cols,
bool normalize_last)
1110 if (normalize_last) {
1111 pivoted_fraction_free_gauss_jordan_elimination(A, b, pl);
1113 pivoted_gauss_jordan_elimination(A, b, pl);
1116 for (
unsigned col = 0; col < b.col_ && row < b.row_; col++) {
1117 if (is_true(
is_zero(*b.get(row, col))))
1119 pivot_cols.push_back(col);
1120 if (row == 0 and normalize_last) {
1121 RCP<const Basic> m =
div(one, b.get(row, col));
1130 void diagonal_solve(
const DenseMatrix &A,
const DenseMatrix &b, DenseMatrix &x)
1132 SYMENGINE_ASSERT(A.row_ == A.col_);
1133 SYMENGINE_ASSERT(x.row_ == A.col_ and x.col_ == b.col_);
1135 const unsigned sys = b.col_;
1138 for (
unsigned k = 0; k < sys; k++) {
1139 for (
unsigned i = 0; i < A.col_; i++) {
1140 x.m_[i * sys + k] =
div(b.m_[i * sys + k], A.m_[i * A.col_ + i]);
1145 void back_substitution(
const DenseMatrix &U,
const DenseMatrix &b,
1148 SYMENGINE_ASSERT(U.row_ == U.col_);
1149 SYMENGINE_ASSERT(b.row_ == U.row_);
1150 SYMENGINE_ASSERT(x.row_ == U.col_ and x.col_ == b.col_);
1152 const unsigned col = U.col_;
1153 const unsigned sys = b.col_;
1156 for (
unsigned k = 0; k < sys; k++) {
1157 for (
int i = col - 1; i >= 0; i--) {
1158 for (
unsigned j = i + 1; j < col; j++)
1160 =
sub(x.m_[i * sys + k],
1161 mul(U.m_[i * col + j], x.m_[j * sys + k]));
1162 x.m_[i * sys + k] =
div(x.m_[i * sys + k], U.m_[i * col + i]);
1167 void forward_substitution(
const DenseMatrix &A,
const DenseMatrix &b,
1170 SYMENGINE_ASSERT(A.row_ == A.col_);
1171 SYMENGINE_ASSERT(b.row_ == A.row_);
1172 SYMENGINE_ASSERT(x.row_ == A.col_ and x.col_ == b.col_);
1174 unsigned col = A.col_;
1175 const unsigned sys = b.col_;
1178 for (
unsigned k = 0; k < b.col_; k++) {
1179 for (
unsigned i = 0; i < col - 1; i++) {
1180 for (
unsigned j = i + 1; j < col; j++) {
1182 =
sub(
mul(A.m_[i * col + i], x.m_[j * sys + k]),
1183 mul(A.m_[j * col + i], x.m_[i * sys + k]));
1186 =
div(x.m_[j * sys + k], A.m_[(i - 1) * col + i - 1]);
1192 void fraction_free_gaussian_elimination_solve(
const DenseMatrix &A,
1193 const DenseMatrix &b,
1196 SYMENGINE_ASSERT(A.row_ == A.col_);
1197 SYMENGINE_ASSERT(b.row_ == A.row_ and x.row_ == A.row_);
1198 SYMENGINE_ASSERT(x.col_ == b.col_);
1200 int i, j, k, col = A.col_, bcol = b.col_;
1201 DenseMatrix A_ = DenseMatrix(A.row_, A.col_, A.m_);
1202 DenseMatrix b_ = DenseMatrix(b.row_, b.col_, b.m_);
1204 for (i = 0; i < col - 1; i++)
1205 for (j = i + 1; j < col; j++) {
1206 for (k = 0; k < bcol; k++) {
1208 =
sub(
mul(A_.m_[i * col + i], b_.m_[j * bcol + k]),
1209 mul(A_.m_[j * col + i], b_.m_[i * bcol + k]));
1211 b_.m_[j * bcol + k] =
div(b_.m_[j * bcol + k],
1212 A_.m_[i * col - col + i - 1]);
1215 for (k = i + 1; k < col; k++) {
1217 =
sub(
mul(A_.m_[i * col + i], A_.m_[j * col + k]),
1218 mul(A_.m_[j * col + i], A_.m_[i * col + k]));
1221 =
div(A_.m_[j * col + k], A_.m_[i * col - col + i - 1]);
1223 A_.m_[j * col + i] = zero;
1226 for (i = 0; i < col * bcol; i++)
1229 for (k = 0; k < bcol; k++) {
1230 for (i = col - 1; i >= 0; i--) {
1231 for (j = i + 1; j < col; j++)
1233 =
sub(b_.m_[i * bcol + k],
1234 mul(A_.m_[i * col + j], x.m_[j * bcol + k]));
1235 x.m_[i * bcol + k] =
div(b_.m_[i * bcol + k], A_.m_[i * col + i]);
1240 void fraction_free_gauss_jordan_solve(
const DenseMatrix &A,
1241 const DenseMatrix &b, DenseMatrix &x,
1244 SYMENGINE_ASSERT(A.row_ == A.col_);
1245 SYMENGINE_ASSERT(b.row_ == A.row_ and x.row_ == A.row_);
1246 SYMENGINE_ASSERT(x.col_ == b.col_);
1248 unsigned i, j, k, p, col = A.col_, bcol = b.col_;
1250 DenseMatrix A_ = DenseMatrix(A.row_, A.col_, A.m_);
1251 DenseMatrix b_ = DenseMatrix(b.row_, b.col_, b.m_);
1253 for (i = 0; i < col; i++) {
1255 d = A_.m_[i * col - col + i - 1];
1258 while (p < col and
eq(*A_.m_[p * col + i], *zero)) {
1261 SYMENGINE_ASSERT(p != col);
1264 for (k = i; k < col; k++) {
1265 std::swap(A_.m_[p * col + k], A_.m_[i * col + k]);
1267 for (k = 0; k < bcol; k++) {
1268 std::swap(b_.m_[p * bcol + k], b_.m_[i * bcol + k]);
1272 for (j = 0; j < col; j++)
1274 for (k = 0; k < bcol; k++) {
1276 =
sub(
mul(A_.m_[i * col + i], b_.m_[j * bcol + k]),
1277 mul(A_.m_[j * col + i], b_.m_[i * bcol + k]));
1279 b_.m_[j * bcol + k] =
div(b_.m_[j * bcol + k], d);
1282 for (k = 0; k < col; k++) {
1285 =
sub(
mul(A_.m_[i * col + i], A_.m_[j * col + k]),
1286 mul(A_.m_[j * col + i], A_.m_[i * col + k]));
1288 A_.m_[j * col + k] =
div(A_.m_[j * col + k], d);
1293 for (j = 0; j < col; j++)
1295 A_.m_[j * col + i] = zero;
1299 for (k = 0; k < bcol; k++)
1300 for (i = 0; i < col; i++)
1301 x.m_[i * bcol + k] =
div(b_.m_[i * bcol + k], A_.m_[i * col + i]);
1304 void fraction_free_LU_solve(
const DenseMatrix &A,
const DenseMatrix &b,
1307 DenseMatrix LU = DenseMatrix(A.nrows(), A.ncols());
1308 DenseMatrix x_ = DenseMatrix(b.nrows(), b.ncols());
1310 fraction_free_LU(A, LU);
1311 forward_substitution(LU, b, x_);
1312 back_substitution(LU, x_, x);
1315 void LU_solve(
const DenseMatrix &A,
const DenseMatrix &b, DenseMatrix &x)
1317 DenseMatrix L = DenseMatrix(A.nrows(), A.ncols());
1318 DenseMatrix U = DenseMatrix(A.nrows(), A.ncols());
1319 DenseMatrix x_ = DenseMatrix(b.nrows(), b.ncols());
1322 forward_substitution(L, b, x_);
1323 back_substitution(U, x_, x);
1326 void pivoted_LU_solve(
const DenseMatrix &A,
const DenseMatrix &b,
1329 DenseMatrix L = DenseMatrix(A.nrows(), A.ncols());
1330 DenseMatrix U = DenseMatrix(A.nrows(), A.ncols());
1331 DenseMatrix x_ = DenseMatrix(b);
1334 pivoted_LU(A, L, U, pl);
1336 forward_substitution(L, x_, x_);
1337 back_substitution(U, x_, x);
1340 void LDL_solve(
const DenseMatrix &A,
const DenseMatrix &b, DenseMatrix &x)
1342 DenseMatrix L = DenseMatrix(A.nrows(), A.ncols());
1343 DenseMatrix D = DenseMatrix(A.nrows(), A.ncols());
1344 DenseMatrix x_ = DenseMatrix(b.nrows(), b.ncols());
1346 if (not is_symmetric_dense(A))
1347 throw SymEngineException(
"Matrix must be symmetric");
1350 forward_substitution(L, b, x);
1351 diagonal_solve(D, x, x_);
1352 transpose_dense(L, D);
1353 back_substitution(D, x_, x);
1364 void fraction_free_LU(
const DenseMatrix &A, DenseMatrix &LU)
1366 SYMENGINE_ASSERT(A.row_ == A.col_ and LU.row_ == LU.col_
1367 and A.row_ == LU.row_);
1369 unsigned n = A.row_;
1374 for (i = 0; i < n - 1; i++)
1375 for (j = i + 1; j < n; j++)
1376 for (k = i + 1; k < n; k++) {
1377 LU.m_[j * n + k] =
sub(
mul(LU.m_[i * n + i], LU.m_[j * n + k]),
1378 mul(LU.m_[j * n + i], LU.m_[i * n + k]));
1381 =
div(LU.m_[j * n + k], LU.m_[i * n - n + i - 1]);
1388 void LU(
const DenseMatrix &A, DenseMatrix &L, DenseMatrix &U)
1390 SYMENGINE_ASSERT(A.row_ == A.col_ and L.row_ == L.col_
1391 and U.row_ == U.col_);
1392 SYMENGINE_ASSERT(A.row_ == L.row_ and A.row_ == U.row_);
1394 unsigned n = A.row_;
1396 RCP<const Basic> scale;
1400 for (j = 0; j < n; j++) {
1401 for (i = 0; i < j; i++)
1402 for (k = 0; k < i; k++)
1403 U.m_[i * n + j] =
sub(U.m_[i * n + j],
1404 mul(U.m_[i * n + k], U.m_[k * n + j]));
1406 for (i = j; i < n; i++) {
1407 for (k = 0; k < j; k++)
1408 U.m_[i * n + j] =
sub(U.m_[i * n + j],
1409 mul(U.m_[i * n + k], U.m_[k * n + j]));
1412 scale =
div(one, U.m_[j * n + j]);
1414 for (i = j + 1; i < n; i++)
1415 U.m_[i * n + j] =
mul(U.m_[i * n + j], scale);
1418 for (i = 0; i < n; i++) {
1419 for (j = 0; j < i; j++) {
1420 L.m_[i * n + j] = U.m_[i * n + j];
1421 U.m_[i * n + j] = zero;
1423 L.m_[i * n + i] = one;
1424 for (j = i + 1; j < n; j++)
1425 L.m_[i * n + j] = zero;
1432 void pivoted_LU(
const DenseMatrix &A, DenseMatrix &LU, permutelist &pl)
1434 SYMENGINE_ASSERT(A.row_ == A.col_ and LU.row_ == LU.col_);
1435 SYMENGINE_ASSERT(A.row_ == LU.row_);
1437 unsigned n = A.row_;
1439 RCP<const Basic> scale;
1444 for (j = 0; j < n; j++) {
1445 for (i = 0; i < j; i++)
1446 for (k = 0; k < i; k++)
1447 LU.m_[i * n + j] =
sub(LU.m_[i * n + j],
1448 mul(LU.m_[i * n + k], LU.m_[k * n + j]));
1450 for (i = j; i < n; i++) {
1451 for (k = 0; k < j; k++) {
1452 LU.m_[i * n + j] =
sub(LU.m_[i * n + j],
1453 mul(LU.m_[i * n + k], LU.m_[k * n + j]));
1455 if (pivot == -1 and !is_true(
is_zero(*LU.m_[i * n + j])))
1459 throw SymEngineException(
"Matrix is rank deficient");
1460 if (pivot - j != 0) {
1461 row_exchange_dense(LU, pivot, j);
1462 pl.push_back({pivot, j});
1464 scale =
div(one, LU.m_[j * n + j]);
1466 for (i = j + 1; i < n; i++)
1467 LU.m_[i * n + j] =
mul(LU.m_[i * n + j], scale);
1474 void pivoted_LU(
const DenseMatrix &A, DenseMatrix &L, DenseMatrix &U,
1477 SYMENGINE_ASSERT(A.row_ == A.col_ and L.row_ == L.col_
1478 and U.row_ == U.col_);
1479 SYMENGINE_ASSERT(A.row_ == L.row_ and A.row_ == U.row_);
1481 pivoted_LU(A, U, pl);
1482 unsigned n = A.col_;
1483 for (
unsigned i = 0; i < n; i++) {
1484 for (
unsigned j = 0; j < i; j++) {
1485 L.m_[i * n + j] = U.m_[i * n + j];
1486 U.m_[i * n + j] = zero;
1488 L.m_[i * n + i] = one;
1489 for (
unsigned j = i + 1; j < n; j++)
1490 L.m_[i * n + j] = zero;
1499 void fraction_free_LDU(
const DenseMatrix &A, DenseMatrix &L, DenseMatrix &D,
1502 SYMENGINE_ASSERT(A.row_ == L.row_ and A.row_ == U.row_);
1503 SYMENGINE_ASSERT(A.col_ == L.col_ and A.col_ == U.col_);
1505 unsigned row = A.row_, col = A.col_;
1507 RCP<const Basic> old =
integer(1);
1512 for (i = 0; i < row; i++)
1513 for (j = 0; j < row; j++)
1515 L.m_[i * col + j] = zero;
1517 L.m_[i * col + i] = one;
1520 for (i = 0; i < row * row; i++)
1523 for (k = 0; k < row - 1; k++) {
1524 L.m_[k * col + k] = U.m_[k * col + k];
1525 D.m_[k * col + k] =
mul(old, U.m_[k * col + k]);
1527 for (i = k + 1; i < row; i++) {
1528 L.m_[i * col + k] = U.m_[i * col + k];
1529 for (j = k + 1; j < col; j++)
1531 =
div(
sub(
mul(U.m_[k * col + k], U.m_[i * col + j]),
1532 mul(U.m_[k * col + j], U.m_[i * col + k])),
1534 U.m_[i * col + k] = zero;
1537 old = U.m_[k * col + k];
1540 D.m_[row * col - col + row - 1] = old;
1545 void QR(
const DenseMatrix &A, DenseMatrix &Q, DenseMatrix &R)
1547 unsigned row = A.row_;
1548 unsigned col = A.col_;
1550 SYMENGINE_ASSERT(Q.row_ == row and Q.col_ == col and R.row_ == col
1558 for (i = 0; i < row * col; i++)
1562 for (i = 0; i < col * col; i++)
1565 for (j = 0; j < col; j++) {
1567 for (k = 0; k < row; k++)
1568 tmp[k] = A.m_[k * col + j];
1570 for (i = 0; i < j; i++) {
1572 for (k = 0; k < row; k++)
1573 t =
add(t,
mul(A.m_[k * col + j], Q.m_[k * col + i]));
1574 for (k = 0; k < row; k++)
1575 tmp[k] =
expand(
sub(tmp[k],
mul(Q.m_[k * col + i], t)));
1580 for (k = 0; k < row; k++)
1585 R.m_[j * col + j] = t;
1586 for (k = 0; k < row; k++)
1587 Q.m_[k * col + j] =
div(tmp[k], t);
1589 for (i = 0; i < j; i++) {
1591 for (k = 0; k < row; k++)
1592 t =
add(t,
mul(Q.m_[k * col + i], A.m_[k * col + j]));
1593 R.m_[i * col + j] = t;
1600 void LDL(
const DenseMatrix &A, DenseMatrix &L, DenseMatrix &D)
1602 SYMENGINE_ASSERT(A.row_ == A.col_);
1603 SYMENGINE_ASSERT(L.row_ == A.row_ and L.col_ == A.row_);
1604 SYMENGINE_ASSERT(D.row_ == A.row_ and D.col_ == A.row_);
1606 unsigned col = A.col_;
1608 RCP<const Basic> sum;
1609 RCP<const Basic> i2 =
integer(2);
1612 for (i = 0; i < col; i++)
1613 for (j = 0; j < col; j++)
1614 D.m_[i * col + j] = zero;
1617 for (i = 0; i < col; i++)
1618 for (j = 0; j < col; j++)
1619 L.m_[i * col + j] = (i != j) ? zero : one;
1621 for (i = 0; i < col; i++) {
1622 for (j = 0; j < i; j++) {
1624 for (k = 0; k < j; k++)
1625 sum =
add(sum,
mul(
mul(L.m_[i * col + k], L.m_[j * col + k]),
1626 D.m_[k * col + k]));
1628 =
mul(
div(one, D.m_[j * col + j]),
sub(A.m_[i * col + j], sum));
1631 for (k = 0; k < i; k++)
1632 sum =
add(sum,
mul(
pow(L.m_[i * col + k], i2), D.m_[k * col + k]));
1633 D.m_[i * col + i] =
sub(A.m_[i * col + i], sum);
1638 void cholesky(
const DenseMatrix &A, DenseMatrix &L)
1640 SYMENGINE_ASSERT(A.row_ == A.col_);
1641 SYMENGINE_ASSERT(L.row_ == A.row_ and L.col_ == A.row_);
1643 unsigned col = A.col_;
1645 RCP<const Basic> sum;
1646 RCP<const Basic> i2 =
integer(2);
1647 RCP<const Basic> half =
div(one, i2);
1650 for (i = 0; i < col; i++)
1651 for (j = 0; j < col; j++)
1652 L.m_[i * col + j] = zero;
1654 for (i = 0; i < col; i++) {
1655 for (j = 0; j < i; j++) {
1657 for (k = 0; k < j; k++)
1658 sum =
add(sum,
mul(L.m_[i * col + k], L.m_[j * col + k]));
1661 =
mul(
div(one, L.m_[j * col + j]),
sub(A.m_[i * col + j], sum));
1664 for (k = 0; k < i; k++)
1665 sum =
add(sum,
pow(L.m_[i * col + k], i2));
1666 L.m_[i * col + i] =
pow(
sub(A.m_[i * col + i], sum), half);
1671 bool is_symmetric_dense(
const DenseMatrix &A)
1673 if (A.col_ != A.row_)
1676 unsigned col = A.col_;
1679 for (
unsigned i = 0; i < col; i++)
1680 for (
unsigned j = i + 1; j < col; j++)
1681 if (not
eq(*(A.m_[j * col + i]), *(A.m_[i * col + j]))) {
1690 RCP<const Basic> det_bareis(
const DenseMatrix &A)
1692 SYMENGINE_ASSERT(A.row_ == A.col_);
1694 unsigned n = A.row_;
1698 }
else if (n == 2) {
1700 return sub(
mul(A.m_[0], A.m_[3]),
mul(A.m_[1], A.m_[2]));
1701 }
else if (n == 3) {
1705 mul(
mul(A.m_[1], A.m_[5]), A.m_[6])),
1706 mul(
mul(A.m_[2], A.m_[3]), A.m_[7])),
1708 mul(
mul(A.m_[1], A.m_[3]), A.m_[8])),
1709 mul(
mul(A.m_[0], A.m_[5]), A.m_[7])));
1712 if (A.is_lower() or A.is_upper()) {
1713 RCP<const Basic> det = A.m_[0];
1714 for (
unsigned i = 1; i < n; ++i) {
1715 det =
mul(det, A.m_[i * n + i]);
1720 DenseMatrix B = DenseMatrix(n, n, A.m_);
1721 unsigned i,
sign = 1;
1724 for (
unsigned k = 0; k < n - 1; k++) {
1725 if (is_true(
is_zero(*B.m_[k * n + k]))) {
1726 for (i = k + 1; i < n; i++)
1727 if (!is_true(
is_zero(*B.m_[i * n + k]))) {
1728 row_exchange_dense(B, i, k);
1736 for (i = k + 1; i < n; i++) {
1737 for (
unsigned j = k + 1; j < n; j++) {
1738 d =
sub(
mul(B.m_[k * n + k], B.m_[i * n + j]),
1739 mul(B.m_[i * n + k], B.m_[k * n + j]));
1741 d =
div(d, B.m_[(k - 1) * n + k - 1]);
1742 B.m_[i * n + j] = d;
1747 return (sign == 1) ? B.m_[n * n - 1] :
mul(minus_one, B.m_[n * n - 1]);
1757 SYMENGINE_ASSERT(A.row_ == A.col_);
1759 unsigned col = A.col_;
1760 unsigned i, k, l, m;
1766 for (
unsigned n = col; n > 1; n--) {
1769 DenseMatrix T = DenseMatrix(n + 1, n);
1770 DenseMatrix C = DenseMatrix(k, 1);
1773 for (i = 0; i < n * (n + 1); i++)
1775 for (i = 0; i < k; i++)
1776 C.m_[i] = A.m_[i * col + k];
1779 for (i = 0; i < n - 2; i++) {
1780 DenseMatrix B = DenseMatrix(k, 1);
1781 for (l = 0; l < k; l++) {
1783 for (m = 0; m < k; m++)
1785 =
add(B.m_[l],
mul(A.m_[l * col + m], items[i].m_[m]));
1791 for (i = 0; i < n - 1; i++) {
1792 RCP<const Basic> element = zero;
1793 for (l = 0; l < k; l++)
1794 element =
add(element,
mul(A.m_[k * col + l], items[i].m_[l]));
1797 items_.
insert(items_.
begin(),
mul(minus_one, A.m_[k * col + k]));
1800 for (i = 0; i < n; i++) {
1801 for (l = 0; l < n - i + 1; l++)
1802 T.m_[(i + l) * n + i] = items_[l];
1808 polys.
push_back(DenseMatrix(2, 1, {one,
mul(A.m_[0], minus_one)}));
1810 for (i = 0; i < col - 1; i++) {
1811 unsigned t_row = transforms[col - 2 - i].nrows();
1812 unsigned t_col = transforms[col - 2 - i].ncols();
1813 DenseMatrix B = DenseMatrix(t_row, 1);
1815 for (l = 0; l < t_row; l++) {
1817 for (m = 0; m < t_col; m++) {
1818 B.m_[l] =
add(B.m_[l],
1819 mul(transforms[col - 2 - i].m_[l * t_col + m],
1821 B.m_[l] =
expand(B.m_[l]);
1828 RCP<const Basic> det_berkowitz(
const DenseMatrix &A)
1832 berkowitz(A, polys);
1833 DenseMatrix poly = polys[polys.
size() - 1];
1835 if (polys.
size() % 2 == 1)
1836 return mul(minus_one, poly.get(poly.nrows() - 1, 0));
1838 return poly.get(poly.nrows() - 1, 0);
1841 void char_poly(
const DenseMatrix &A, DenseMatrix &B)
1843 SYMENGINE_ASSERT(B.ncols() == 1 and B.nrows() == A.nrows() + 1);
1844 SYMENGINE_ASSERT(A.nrows() == A.ncols());
1848 berkowitz(A, polys);
1849 B = polys[polys.
size() - 1];
1852 void inverse_fraction_free_LU(
const DenseMatrix &A, DenseMatrix &B)
1854 SYMENGINE_ASSERT(A.row_ == A.col_ and B.row_ == B.col_
1855 and B.row_ == A.row_);
1857 unsigned n = A.row_, i;
1858 DenseMatrix LU = DenseMatrix(n, n);
1859 DenseMatrix e = DenseMatrix(n, 1);
1860 DenseMatrix x = DenseMatrix(n, 1);
1861 DenseMatrix x_ = DenseMatrix(n, 1);
1864 for (i = 0; i < n * n; i++) {
1868 for (i = 0; i < n; i++) {
1874 fraction_free_LU(A, LU);
1879 for (
unsigned j = 0; j < n; j++) {
1882 forward_substitution(LU, e, x_);
1883 back_substitution(LU, x_, x);
1885 for (i = 0; i < n; i++)
1886 B.m_[i * n + j] = x.m_[i];
1892 void inverse_LU(
const DenseMatrix &A, DenseMatrix &B)
1894 SYMENGINE_ASSERT(A.row_ == A.col_ and B.row_ == B.col_
1895 and B.row_ == A.row_);
1896 DenseMatrix e = DenseMatrix(A.row_, A.col_);
1901 void inverse_pivoted_LU(
const DenseMatrix &A, DenseMatrix &B)
1903 SYMENGINE_ASSERT(A.row_ == A.col_ and B.row_ == B.col_
1904 and B.row_ == A.row_);
1905 DenseMatrix e = DenseMatrix(A.row_, A.col_);
1907 pivoted_LU_solve(A, e, B);
1910 void inverse_gauss_jordan(
const DenseMatrix &A, DenseMatrix &B)
1912 SYMENGINE_ASSERT(A.row_ == A.col_ and B.row_ == B.col_
1913 and B.row_ == A.row_);
1915 unsigned n = A.row_;
1916 DenseMatrix e = DenseMatrix(n, n);
1919 for (
unsigned i = 0; i < n; i++)
1920 for (
unsigned j = 0; j < n; j++) {
1922 e.m_[i * n + j] = zero;
1924 e.m_[i * n + i] = one;
1926 B.m_[i * n + j] = zero;
1929 fraction_free_gauss_jordan_solve(A, e, B);
1934 void dot(
const DenseMatrix &A,
const DenseMatrix &B, DenseMatrix &C)
1936 if (A.col_ == B.row_) {
1938 DenseMatrix tmp1 = DenseMatrix(A.col_, A.row_);
1940 DenseMatrix tmp2 = DenseMatrix(B.col_, B.row_);
1942 C.resize(tmp1.row_, tmp2.col_);
1943 mul_dense_dense(tmp1, tmp2, C);
1945 C.resize(A.row_, B.col_);
1946 mul_dense_dense(A, B, C);
1948 C.resize(1, C.row_ * C.col_);
1949 }
else if (A.col_ == B.col_) {
1950 DenseMatrix tmp2 = DenseMatrix(B.col_, B.row_);
1953 }
else if (A.row_ == B.row_) {
1954 DenseMatrix tmp1 = DenseMatrix(A.col_, A.row_);
1958 throw SymEngineException(
"Dimensions incorrect for dot product");
1962 void cross(
const DenseMatrix &A,
const DenseMatrix &B, DenseMatrix &C)
1964 SYMENGINE_ASSERT((A.row_ * A.col_ == 3 and B.row_ * B.col_ == 3)
1965 and (A.row_ == C.row_ and A.col_ == C.col_));
1967 C.m_[0] =
sub(
mul(A.m_[1], B.m_[2]),
mul(A.m_[2], B.m_[1]));
1968 C.m_[1] =
sub(
mul(A.m_[2], B.m_[0]),
mul(A.m_[0], B.m_[2]));
1969 C.m_[2] =
sub(
mul(A.m_[0], B.m_[1]),
mul(A.m_[1], B.m_[0]));
1972 RCP<const Set> eigen_values(
const DenseMatrix &A)
1974 unsigned n = A.nrows();
1975 if (A.is_lower() or A.is_upper()) {
1976 RCP<const Set> eigenvals =
emptyset();
1978 for (
unsigned i = 0; i < n; ++i) {
1985 DenseMatrix B = DenseMatrix(A.nrows() + 1, 1);
1987 map_int_Expr coeffs;
1988 auto nr = A.nrows();
1989 for (
unsigned i = 0; i <= nr; i++)
1990 insert(coeffs, nr - i, B.get(i, 0));
1991 auto lambda =
symbol(
"lambda");
1992 return solve_poly(uexpr_poly(lambda, coeffs), lambda);
1998 void eye(DenseMatrix &A,
int k)
2000 if ((k >= 0 and (
unsigned) k >= A.col_) or k + A.row_ <= 0) {
2004 vec_basic v = vec_basic(k > 0 ? A.col_ - k : A.row_ + k, one);
2010 void diag(DenseMatrix &A, vec_basic &v,
int k)
2012 SYMENGINE_ASSERT(v.size() > 0);
2014 unsigned k_ = std::abs(k);
2017 for (
unsigned i = 0; i < A.row_; i++) {
2018 for (
unsigned j = 0; j < A.col_; j++) {
2019 if (j != (
unsigned)k) {
2020 A.m_[i * A.col_ + j] = zero;
2022 A.m_[i * A.col_ + j] = v[k - k_];
2030 for (
unsigned j = 0; j < A.col_; j++) {
2031 for (
unsigned i = 0; i < A.row_; i++) {
2032 if (i != (
unsigned)k) {
2033 A.m_[i * A.col_ + j] = zero;
2035 A.m_[i * A.col_ + j] = v[k - k_];
2044 void ones(DenseMatrix &A)
2046 for (
unsigned i = 0; i < A.row_ * A.col_; i++) {
2052 void zeros(DenseMatrix &A)
2054 for (
unsigned i = 0; i < A.row_ * A.col_; i++) {
Classes and functions relating to the binary operation of addition.
RCP< const Basic > sub(const RCP< const Basic > &a, const RCP< const Basic > &b)
Substracts b from a.
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Main namespace for SymEngine package.
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
bool is_number_and_zero(const Basic &b)
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const EmptySet > emptyset()
RCP< const Basic > sign(const RCP< const Basic > &arg)
Canonicalize Sign.
RCP< const Basic > abs(const RCP< const Basic > &arg)
Canonicalize Abs:
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
void insert(T1 &m, const T2 &first, const T3 &second)
tribool is_zero(const Basic &b, const Assumptions *assumptions=nullptr)
Check if a number is zero.
RCP< const Set > finiteset(const set_basic &container)
RCP< const Basic > expand(const RCP< const Basic > &self, bool deep=true)
Expands self
RCP< const Basic > ssubs(const RCP< const Basic > &x, const map_basic_basic &subs_dict, bool cache=true)
SymPy compatible subs.
RCP< const Basic > conjugate(const RCP< const Basic > &arg)
Canonicalize Conjugate.