// References : Cohen H., A course in computational algebraic number theory // (1996), page 21. bool crt(const Ptr<RCP<const Integer>> &R, const std::vector<RCP<const Integer>> &rem, const std::vector<RCP<const Integer>> &mod) { if (mod.size() > rem.size()) throw SymEngineException("Too few remainders"); if (mod.size() == 0) throw SymEngineException("Moduli vector cannot be empty"); integer_class m, r, g, s, t; m = mod[0]->as_integer_class(); r = rem[0]->as_integer_class(); for (unsigned i = 1; i < mod.size(); ++i) { mp_gcdext(g, s, t, m, mod[i]->as_integer_class()); // g = s * m + t * mod[i] t = rem[i]->as_integer_class() - r; if (not mp_divisible_p(t, g)) return false; r += m * s * (t / g); // r += m * (m**-1 mod[i]/g)* (rem[i] - r) / g m *= mod[i]->as_integer_class() / g; mp_fdiv_r(r, r, m); } *R = integer(std::move(r)); return true; }
void prime_factors(std::vector<RCP<const Integer>> &prime_list, const Integer &n) { integer_class sqrtN; integer_class _n = n.as_integer_class(); if (_n == 0) return; if (_n < 0) _n *= -1; sqrtN = mp_sqrt(_n); auto limit = mp_get_ui(sqrtN); if (not mp_fits_ulong_p(sqrtN) or limit > std::numeric_limits<unsigned>::max()) throw SymEngineException("N too large to factor"); Sieve::iterator pi(limit); unsigned p; while ((p = pi.next_prime()) <= limit) { while (_n % p == 0) { prime_list.push_back(integer(p)); _n = _n / p; } if (_n == 1) break; } if (not(_n == 1)) prime_list.push_back(integer(std::move(_n))); }
void prime_factor_multiplicities(map_integer_uint &primes_mul, const Integer &n) { integer_class sqrtN; integer_class _n = n.as_integer_class(); unsigned count; if (_n == 0) return; if (_n < 0) _n *= -1; sqrtN = mp_sqrt(_n); auto limit = mp_get_ui(sqrtN); if (not mp_fits_ulong_p(sqrtN) or limit > std::numeric_limits<unsigned>::max()) throw SymEngineException("N too large to factor"); Sieve::iterator pi(limit); unsigned p; while ((p = pi.next_prime()) <= limit) { count = 0; while (_n % p == 0) { // when a prime factor is found, we divide ++count; // _n by that prime as much as we can _n = _n / p; } if (count > 0) { insert(primes_mul, integer(p), count); if (_n == 1) break; } } if (not(_n == 1)) insert(primes_mul, integer(std::move(_n)), 1); }
void jacobian(const DenseMatrix &A, const DenseMatrix &x, DenseMatrix &result) { SYMENGINE_ASSERT(A.col_ == 1); SYMENGINE_ASSERT(x.col_ == 1); SYMENGINE_ASSERT(A.row_ == result.nrows() and x.row_ == result.ncols()); bool error = false; #pragma omp parallel for for (unsigned i = 0; i < result.row_; i++) { for (unsigned j = 0; j < result.col_; j++) { if (is_a<Symbol>(*(x.m_[j]))) { const RCP<const Symbol> x_ = rcp_static_cast<const Symbol>(x.m_[j]); result.m_[i * result.col_ + j] = A.m_[i]->diff(x_); } else { error = true; break; } } } if (error) { throw SymEngineException( "'x' must contain Symbols only. " "Use sjacobian for SymPy style differentiation"); } }
signed long int Integer::as_int() const { // mp_get_si() returns "signed long int", so that's what we return from // "as_int()" and we leave it to the user to do any possible further integer // conversions. if (not(mp_fits_slong_p(this->i))) { throw SymEngineException("as_int: Integer larger than int"); } return mp_get_si(this->i); }
// Slower, but returns exact (possibly large) integers (as mpz) void multinomial_coefficients_mpz(int m, int n, map_vec_mpz &r) { vec_int t; int j, tj, start, k; integer_class v; if (m < 2) throw SymEngineException("multinomial_coefficients: m >= 2 must hold."); if (n < 0) throw SymEngineException("multinomial_coefficients: n >= 0 must hold."); t.assign(m, 0); t[0] = n; r[t] = 1; if (n == 0) return; j = 0; while (j < m - 1) { tj = t[j]; if (j) { t[j] = 0; t[0] = tj; } if (tj > 1) { t[j + 1] += 1; j = 0; start = 1; v = 0; } else { j += 1; start = j + 1; v = r[t]; t[j] += 1; } for (k = start; k < m; k++) { if (t[k]) { t[k] -= 1; v += r[t]; t[k] += 1; } } t[0] -= 1; r[t] = (v * tj) / (n - t[0]); } }
// 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)); } }
int i_nth_root(const Ptr<RCP<const Integer>> &r, const Integer &a, unsigned long int n) { if (n == 0) throw SymEngineException("i_nth_root: Can not find Zeroth root"); int ret_val; integer_class t; ret_val = mp_root(t, a.as_integer_class(), n); *r = integer(std::move(t)); return ret_val; }
// Factorization int factor(const Ptr<RCP<const Integer>> &f, const Integer &n, double B1) { int ret_val = 0; integer_class _n, _f; _n = n.as_integer_class(); #ifdef HAVE_SYMENGINE_ECM if (mp_perfect_power_p(_n)) { unsigned long int i = 1; integer_class m, rem; rem = 1; // Any non zero number m = 2; // set `m` to 2**i, i = 1 at the begining // calculate log2n, this can be improved for (; m < _n; ++i) m = m * 2; // eventually `rem` = 0 zero as `n` is a perfect power. `f_t` will // be set to a factor of `n` when that happens while (i > 1 and rem != 0) { mp_rootrem(_f, rem, _n, i); --i; } ret_val = 1; } else { if (mp_probab_prime_p(_n, 25) > 0) { // most probably, n is a prime ret_val = 0; _f = _n; } else { for (int i = 0; i < 10 and not ret_val; ++i) ret_val = ecm_factor(get_mpz_t(_f), get_mpz_t(_n), B1, nullptr); mp_demote(_f); if (not ret_val) throw SymEngineException( "ECM failed to factor the given number"); } } #else // B1 is discarded if gmp-ecm is not installed ret_val = _factor_trial_division_sieve(_f, _n); #endif // HAVE_SYMENGINE_ECM *f = integer(std::move(_f)); return ret_val; }
// 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)); }
void LDL_solve(const DenseMatrix &A, const DenseMatrix &b, DenseMatrix &x) { DenseMatrix L = DenseMatrix(A.nrows(), A.ncols()); DenseMatrix D = DenseMatrix(A.nrows(), A.ncols()); DenseMatrix x_ = DenseMatrix(b.nrows(), b.ncols()); if (not is_symmetric_dense(A)) throw SymEngineException("Matrix must be symmetric"); LDL(A, L, D); forward_substitution(L, b, x); diagonal_solve(D, x, x_); transpose_dense(L, D); back_substitution(D, x_, x); }
RCP<const Number> Integer::pow_negint(const Integer &other) const { RCP<const Number> tmp = powint(*other.neg()); if (is_a<Integer>(*tmp)) { const integer_class &j = down_cast<const Integer &>(*tmp).i; #if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP // boost::multiprecision::cpp_rational lacks an (int, cpp_int) // constructor. must use cpp_rational(cpp_int,cpp_int) rational_class q(integer_class(mp_sign(j)), mp_abs(j)); #else rational_class q(mp_sign(j), mp_abs(j)); #endif return Rational::from_mpq(std::move(q)); } else { throw SymEngineException("powint returned non-integer"); } }
// 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); } }
bool divides_upoly(const UIntPoly &a, const UIntPoly &b, const Ptr<RCP<const UIntPoly>> &out) { if (!(a.get_var()->__eq__(*b.get_var()))) throw SymEngineException("Error: variables must agree."); auto a_poly = a.get_poly(); auto b_poly = b.get_poly(); if (a_poly.size() == 0) return false; map_uint_mpz res; UIntDict tmp; integer_class q, r; unsigned int a_deg, b_deg; while (b_poly.size() >= a_poly.size()) { a_deg = a_poly.degree(); b_deg = b_poly.degree(); mp_tdiv_qr(q, r, b_poly.get_lc(), a_poly.get_lc()); if (r != 0) return false; res[b_deg - a_deg] = q; UIntDict tmp = UIntDict({{b_deg - a_deg, q}}); b_poly -= (a_poly * tmp); } if (b_poly.empty()) { *out = UIntPoly::from_dict(a.get_var(), std::move(res)); return true; } else { return false; } }
fqp_t URatPSeriesFlint::convert(const Basic &x) { throw SymEngineException("SeriesFlint::convert not Implemented"); }