4 #include "smod_helpers.h"
9 * Exact polynomial division of a, b \in Z_p[x_0, \ldots, x_n]
10 * It doesn't check whether the inputs are proper polynomials, so be careful
11 * of what you pass in.
13 * @param a first multivariate polynomial (dividend)
14 * @param b second multivariate polynomial (divisor)
15 * @param q quotient (returned)
16 * @param var variables X iterator to first element of vector of symbols
18 * @return "true" when exact division succeeds (the quotient is returned in
19 * q), "false" otherwise.
20 * @note @a p = 0 means the base ring is Z
22 bool divide_in_z_p(const ex &a, const ex &b, ex &q, const exvector& vars, const long p)
24 static const ex _ex1(1);
26 throw(std::overflow_error("divide_in_z: division by zero"));
27 if (b.is_equal(_ex1)) {
31 if (is_exactly_a<numeric>(a)) {
32 if (is_exactly_a<numeric>(b)) {
33 // p == 0 means division in Z
35 const numeric tmp = ex_to<numeric>(a/b);
36 if (tmp.is_integer()) {
42 q = (a*recip(ex_to<numeric>(b), p)).smod(numeric(p));
54 const ex &x = vars.back();
57 int adeg = a.degree(x), bdeg = b.degree(x);
61 // Polynomial long division (recursive)
67 ex blcoeff = eb.coeff(x, bdeg);
69 v.reserve(std::max(rdeg - bdeg + 1, 0));
70 exvector rest_vars(vars);
72 while (rdeg >= bdeg) {
73 ex term, rcoeff = r.coeff(x, rdeg);
74 if (!divide_in_z_p(rcoeff, blcoeff, term, rest_vars, p))
76 term = (term*power(x, rdeg - bdeg)).expand();
78 r = (r - term*eb).expand();
80 r = r.smod(numeric(p));
82 q = (new add(v))->setflag(status_flags::dynallocated);