// Scale the rows of a CSR matrix *in place* // A[i, :] *= X[i] void csr_scale_rows(CSRMatrix &A, const DenseMatrix &X) { SYMENGINE_ASSERT(A.row_ == X.nrows() and X.ncols() == 1); for (unsigned i = 0; i < A.row_; i++) { if (eq(*(X.get(i, 0)), *zero)) throw SymEngineException("Scaling factor can't be zero"); for (unsigned jj = A.p_[i]; jj < A.p_[i + 1]; jj++) A.x_[jj] = mul(A.x_[jj], X.get(i, 0)); } }
RCP<const Basic> det_berkowitz(const DenseMatrix &A) { std::vector<DenseMatrix> polys; berkowitz(A, polys); DenseMatrix poly = polys[polys.size() - 1]; if (polys.size() % 2 == 1) return mul(minus_one, poly.get(poly.nrows() - 1, 0)); return poly.get(poly.nrows() - 1, 0); }
// Scale the columns of a CSR matrix *in place* // A[:, i] *= X[i] void csr_scale_columns(CSRMatrix &A, const DenseMatrix &X) { SYMENGINE_ASSERT(A.col_ == X.nrows() and X.ncols() == 1); const unsigned nnz = A.p_[A.row_]; unsigned i; for (i = 0; i < A.col_; i++) { if (eq(*(X.get(i, 0)), *zero)) throw SymEngineException("Scaling factor can't be zero"); } for (i = 0; i < nnz; i++) A.x_[i] = mul(A.x_[i], X.get(A.j_[i], 0)); }
bool order(const DenseMatrix &t, const std::vector<DenseMatrix> &basis, unsigned k) { bool eq = true; for (unsigned j = 0; j < t.ncols(); j++) { SYMENGINE_ASSERT(is_a<Integer>(*t.get(0, j))); integer_class t_ = rcp_static_cast<const Integer>(t.get(0, j))->as_integer_class(); SYMENGINE_ASSERT(is_a<Integer>(*basis[k].get(0, j))); integer_class b_ = rcp_static_cast<const Integer>(basis[k].get(0, j)) ->as_integer_class(); if (t_ < b_) { return false; } if (t_ > b_) { eq = false; } } return not eq; }
// Solve the diophantine system Ax = 0 and return a basis set for solutions // Reference: // Evelyne Contejean, Herve Devie. An Efficient Incremental Algorithm for // Solving // Systems of Linear Diophantine Equations. Information and computation, // 113(1):143-172, // August 1994. void homogeneous_lde(std::vector<DenseMatrix> &basis, const DenseMatrix &A) { unsigned p = A.nrows(); unsigned q = A.ncols(); unsigned n; SYMENGINE_ASSERT(p > 0 and q > 1); DenseMatrix row_zero(1, q); zeros(row_zero); DenseMatrix col_zero(p, 1); zeros(col_zero); std::vector<DenseMatrix> P; P.push_back(row_zero); std::vector<std::vector<bool>> Frozen(q, std::vector<bool>(q, true)); for (unsigned j = 0; j < q; j++) { Frozen[0][j] = false; } std::vector<bool> F(q, false); DenseMatrix t, transpose, product, T; RCP<const Integer> dot; product = DenseMatrix(p, 1); transpose = DenseMatrix(q, 1); while (P.size() > 0) { n = P.size() - 1; t = P[n]; P.pop_back(); t.transpose(transpose); A.mul_matrix(transpose, product); if (product.eq(col_zero) and not t.eq(row_zero)) { basis.push_back(t); } else { for (unsigned i = 0; i < q; i++) { F[i] = Frozen[n][i]; } T = t; for (unsigned i = 0; i < q; i++) { SYMENGINE_ASSERT(is_a<Integer>(*T.get(0, i))); T.set(0, i, rcp_static_cast<const Integer>(T.get(0, i)) ->addint(*one)); if (i > 0) { SYMENGINE_ASSERT(is_a<Integer>(*T.get(0, i - 1))); T.set(0, i - 1, rcp_static_cast<const Integer>(T.get(0, i - 1)) ->subint(*one)); } dot = zero; for (unsigned j = 0; j < p; j++) { SYMENGINE_ASSERT(is_a<Integer>(*product.get(j, 0))); RCP<const Integer> p_j0 = rcp_static_cast<const Integer>(product.get(j, 0)); SYMENGINE_ASSERT(is_a<Integer>(*A.get(j, i))); RCP<const Integer> A_ji = rcp_static_cast<const Integer>(A.get(j, i)); dot = dot->addint(*p_j0->mulint(*A_ji)); } if (F[i] == false and ((dot->is_negative() and is_minimum(T, basis, basis.size())) or t.eq(row_zero))) { P.push_back(T); n = n + 1; for (unsigned j = 0; j < q; j++) { Frozen[n - 1][j] = F[j]; } F[i] = true; } } } } }