43#include "polynomial/chinrem_gcd.h"
61#define USE_TRIAL_DIVISION 0
69static int gcd_called = 0;
70static int sr_gcd_called = 0;
71static int heur_gcd_called = 0;
72static int heur_gcd_failed = 0;
75static struct _stat_print {
78 std::cout <<
"gcd() called " << gcd_called <<
" times\n";
79 std::cout <<
"sr_gcd() called " << sr_gcd_called <<
" times\n";
80 std::cout <<
"heur_gcd() called " << heur_gcd_called <<
" times\n";
81 std::cout <<
"heur_gcd() failed " << heur_gcd_failed <<
" times\n";
100 for (
size_t i=0; i<e.
nops(); i++)
165 if (it.sym.is_equal(s))
177 for (
size_t i=0; i<e.
nops(); i++)
200 for (
auto & it : v) {
201 int deg_a = a.
degree(it.sym);
202 int deg_b = b.
degree(it.sym);
205 it.max_deg = std::max(deg_a, deg_b);
210 std::sort(v.begin(), v.end());
213 std::clog <<
"Symbols:\n";
214 auto it = v.begin(), itend = v.end();
215 while (it != itend) {
216 std::clog <<
" " << it->sym <<
": deg_a=" << it->deg_a <<
", deg_b=" << it->deg_b <<
", ldeg_a=" << it->ldeg_a <<
", ldeg_b=" << it->ldeg_b <<
", max_deg=" << it->max_deg <<
", max_lcnops=" << it->max_lcnops << std::endl;
217 std::clog <<
" lcoeff_a=" << a.
lcoeff(it->sym) <<
", lcoeff_b=" << b.
lcoeff(it->sym) << std::endl;
236 for (
size_t i=0; i<e.
nops(); i++)
241 for (
size_t i=0; i<e.
nops(); i++)
278 size_t num = e.
nops();
282 for (
size_t i=0; i<num; i++) {
287 v.push_back(
lcm / lcm_accum);
291 size_t num = e.
nops();
294 for (
size_t i=0; i<num; i++)
319 return bp->integer_content();
335 for (
auto & it :
seq) {
349#ifdef DO_GINAC_ASSERT
350 for (
auto & it :
seq) {
375 throw(std::overflow_error(
"quo: division by zero"));
383 throw(std::invalid_argument(
"quo: arguments must be polynomials over the rationals"));
393 exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
394 while (rdeg >= bdeg) {
395 ex term, rcoeff = r.
coeff(x, rdeg);
396 if (blcoeff_is_numeric)
397 term = rcoeff / blcoeff;
399 if (!
divide(rcoeff, blcoeff, term,
false))
402 term *=
pow(x, rdeg - bdeg);
425 throw(std::overflow_error(
"rem: division by zero"));
437 throw(std::invalid_argument(
"rem: arguments must be polynomials over the rationals"));
447 while (rdeg >= bdeg) {
448 ex term, rcoeff = r.
coeff(x, rdeg);
449 if (blcoeff_is_numeric)
450 term = rcoeff / blcoeff;
452 if (!
divide(rcoeff, blcoeff, term,
false))
455 term *=
pow(x, rdeg - bdeg);
494 throw(std::overflow_error(
"prem: division by zero"));
502 throw(std::invalid_argument(
"prem: arguments must be polynomials over the rationals"));
511 blcoeff = eb.
coeff(x, bdeg);
515 eb -= blcoeff *
pow(x, bdeg);
519 int delta = rdeg - bdeg + 1, i = 0;
520 while (rdeg >= bdeg && !r.
is_zero()) {
522 ex term = (
pow(x, rdeg - bdeg) * eb * rlcoeff).
expand();
526 r -= rlcoeff *
pow(x, rdeg);
527 r = (blcoeff * r).
expand() - term;
531 return pow(blcoeff, delta - i) * r;
546 throw(std::overflow_error(
"prem: division by zero"));
554 throw(std::invalid_argument(
"prem: arguments must be polynomials over the rationals"));
563 blcoeff = eb.
coeff(x, bdeg);
567 eb -= blcoeff *
pow(x, bdeg);
571 while (rdeg >= bdeg && !r.
is_zero()) {
573 ex term = (
pow(x, rdeg - bdeg) * eb * rlcoeff).
expand();
577 r -= rlcoeff *
pow(x, rdeg);
578 r = (blcoeff * r).
expand() - term;
597 throw(std::overflow_error(
"divide: division by zero"));
615 throw(std::invalid_argument(
"divide: arguments must be polynomials over the rationals"));
620 throw(std::invalid_argument(
"invalid expression in divide()"));
625 ex rem_new, rem_old = a;
626 for (
size_t i=0; i < b.
nops(); i++) {
627 if (!
divide(rem_old, b.
op(i), rem_new,
false))
634 const ex& bb(b.
op(0));
636 ex rem_new, rem_old = a;
637 for (
int i=exp_b; i>0; i--) {
638 if (!
divide(rem_old, bb, rem_new,
false))
651 bool divisible_p =
false;
652 for (i=0; i < a.
nops(); ++i) {
653 if (
divide(a.
op(i), b, rem_i,
false)) {
660 resv.reserve(a.
nops());
661 for (
size_t j=0; j < a.
nops(); j++) {
663 resv.push_back(rem_i);
665 resv.push_back(a.
op(j));
673 const ex& ab(a.
op(0));
676 if (
divide(ab, b, rem_i,
false)) {
677 q = rem_i *
pow(ab, a_exp - 1);
699 exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
700 while (rdeg >= bdeg) {
701 ex term, rcoeff = r.
coeff(x, rdeg);
702 if (blcoeff_is_numeric)
703 term = rcoeff / blcoeff;
705 if (!
divide(rcoeff, blcoeff, term,
false))
707 term *=
pow(x, rdeg - bdeg);
725typedef std::pair<ex, ex> ex2;
726typedef std::pair<ex, bool> exbool;
729 bool operator() (
const ex2 &p,
const ex2 &q)
const
731 int cmp = p.first.compare(q.first);
732 return ((cmp<0) || (!(cmp>0) && p.second.compare(q.second)<0));
736typedef std::map<ex2, exbool, ex2_less> ex2_exbool_remember;
760 throw(std::overflow_error(
"divide_in_z: division by zero"));
781 static ex2_exbool_remember dr_remember;
782 ex2_exbool_remember::const_iterator remembered = dr_remember.find(ex2(a, b));
783 if (remembered != dr_remember.end()) {
784 q = remembered->second.first;
785 return remembered->second.second;
790 const ex& bb(b.
op(0));
793 for (
int i=exp_b; i>0; i--) {
803 for (
const auto & it : b) {
815 const ex &x = var->sym;
822#if USE_TRIAL_DIVISION
828 vector<numeric> alpha; alpha.reserve(adeg + 1);
832 for (i=0; i<=adeg; i++) {
840 alpha.push_back(point);
846 vector<numeric> rcp; rcp.reserve(adeg + 1);
848 for (k=1; k<=adeg; k++) {
849 numeric product = alpha[k] - alpha[0];
851 product *= alpha[k] - alpha[i];
852 rcp.push_back(product.
inverse());
858 for (k=1; k<=adeg; k++) {
860 for (i=k-2; i>=0; i--)
861 temp = temp * (alpha[k] - alpha[i]) + v[i];
862 v.push_back((u[k] - temp) * rcp[k]);
867 for (k=adeg-1; k>=0; k--)
868 c = c * (x - alpha[k]) + v[k];
870 if (c.
degree(x) == (adeg - bdeg)) {
884 ex blcoeff = eb.
coeff(x, bdeg);
885 exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
886 while (rdeg >= bdeg) {
887 ex term, rcoeff = r.
coeff(x, rdeg);
890 term = (term *
pow(x, rdeg - bdeg)).
expand();
892 r -= (term * eb).
expand();
896 dr_remember[ex2(a, b)] = exbool(q,
true);
903 dr_remember[ex2(a, b)] = exbool(q,
false);
932 throw(std::invalid_argument(
"invalid expression in unit()"));
967 for (
int i=ldeg; i<=deg; i++)
968 cont =
gcd(r.
coeff(x, i), cont,
nullptr,
nullptr,
false);
1006 return *
this / (c * u);
1008 return quo(*
this, c * u, x,
false);
1061 p = *
this / (c * u);
1063 p =
quo(e, c * u, x,
false);
1080static ex sr_gcd(
const ex &a,
const ex &b, sym_desc_vec::const_iterator var)
1087 const ex &x = var->sym;
1108 ex gamma =
gcd(cont_c, cont_d,
nullptr,
nullptr,
false);
1116 int delta = cdeg - ddeg;
1121 r =
prem(c, d, x,
false);
1128 throw(std::runtime_error(
"invalid expression in sr_gcd(), division failed"));
1143 delta = cdeg - ddeg;
1155 return bp->max_coefficient();
1174 for (
auto & it :
seq) {
1186#ifdef DO_GINAC_ASSERT
1187 for (
auto & it :
seq) {
1215 newseq.reserve(
seq.size()+1);
1216 for (
auto & it :
seq) {
1219 if (!
coeff.is_zero())
1229#ifdef DO_GINAC_ASSERT
1230 for (
auto & it :
seq) {
1246 exvector g; g.reserve(degree_hint);
1249 for (
int i=0; !e.
is_zero(); i++) {
1251 g.push_back(gi *
pow(x, i));
1277 sym_desc_vec::const_iterator var)
1299 const ex &x = var->sym;
1313 xi = mq * (*_num2_p) + (*_num2_p);
1315 xi = mp * (*_num2_p) + (*_num2_p);
1318 for (
int t=0; t<6; t++) {
1371 sym_desc_vec::const_iterator var)
1386 const ex ai = a*ab_lcm;
1387 const ex bi = b*ab_lcm;
1389 throw std::logic_error(
"heur_gcd: not an integer polynomial [1]");
1392 throw std::logic_error(
"heur_gcd: not an integer polynomial [2]");
1396 found =
heur_gcd_z(res, ai, bi, ca, cb, var);
1414static ex
gcd_pf_pow(
const ex& a,
const ex& b, ex* ca, ex* cb);
1418static ex
gcd_pf_mul(
const ex& a,
const ex& b, ex* ca, ex* cb);
1432ex gcd(
const ex &a,
const ex &b,
ex *ca,
ex *cb,
bool check_args,
unsigned options)
1459 throw(std::invalid_argument(
"gcd: arguments must be polynomials over the rationals"));
1552 auto vari = sym_stats.begin();
1553 while ((vari != sym_stats.end()) &&
1554 (((vari->ldeg_b == 0) && (vari->deg_b == 0)) ||
1555 ((vari->ldeg_a == 0) && (vari->deg_a == 0))))
1559 if (vari == sym_stats.end()) {
1568 rotate(sym_stats.begin(), vari, sym_stats.end());
1570 sym_desc_vec::const_iterator var = sym_stats.begin();
1571 const ex &x = var->sym;
1574 int ldeg_a = var->ldeg_a;
1575 int ldeg_b = var->ldeg_b;
1576 int min_ldeg = std::min(ldeg_a,ldeg_b);
1578 ex common =
pow(x, min_ldeg);
1579 return gcd((aex / common).
expand(), (bex / common).
expand(), ca, cb,
false) * common;
1583 if (var->deg_a == 0 && var->deg_b != 0 ) {
1584 ex bex_u, bex_c, bex_p;
1586 ex g =
gcd(aex, bex_c, ca, cb,
false);
1588 *cb *= bex_u * bex_p;
1590 }
else if (var->deg_b == 0 && var->deg_a != 0) {
1591 ex aex_u, aex_c, aex_p;
1593 ex g =
gcd(aex_c, bex, ca, cb,
false);
1595 *ca *= aex_u * aex_p;
1602 bool found =
heur_gcd(g, aex, bex, ca, cb, var);
1621 g =
sr_gcd(aex, bex, var);
1624 for (std::size_t n = sym_stats.size(); n-- != 0; )
1625 vars.push_back(sym_stats[n].sym);
1626 g = chinrem_gcd(aex, bex, vars);
1637 divide(aex, g, *ca,
false);
1639 divide(bex, g, *cb,
false);
1649 const ex& exp_a = a.
op(1);
1651 const ex& exp_b = b.
op(1);
1655 if (exp_a < exp_b) {
1659 *cb =
pow(p, exp_b - exp_a);
1660 return pow(p, exp_a);
1663 *ca =
pow(p, exp_a - exp_b);
1666 return pow(p, exp_b);
1671 ex p_gcd =
gcd(p, pb, &p_co, &pb_co,
false);
1684 if (exp_a < exp_b) {
1685 ex pg =
gcd(
pow(p_co, exp_a),
pow(p_gcd, exp_b-exp_a)*
pow(pb_co, exp_b), ca, cb,
false);
1686 return pow(p_gcd, exp_a)*pg;
1688 ex pg =
gcd(
pow(p_gcd, exp_a - exp_b)*
pow(p_co, exp_a),
pow(pb_co, exp_b), ca, cb,
false);
1689 return pow(p_gcd, exp_b)*pg;
1704 const ex& exp_a = a.
op(1);
1708 *ca =
pow(p, exp_a - 1);
1717 int min_ldeg = std::min(ldeg_a, ldeg_b);
1719 ex common =
pow(p, min_ldeg);
1720 return gcd(
pow(p, ldeg_a - min_ldeg), (b / common).
expand(), ca, cb,
false) * common;
1725 ex p_gcd =
gcd(p, b, &p_co, &bpart_co,
false);
1736 ex rg =
gcd(
pow(p_gcd, exp_a-1)*
pow(p_co, exp_a), bpart_co, ca, cb,
false);
1750 size_t num = a.
nops();
1752 exvector acc_ca; acc_ca.reserve(num);
1754 for (
size_t i=0; i<num; i++) {
1755 ex part_ca, part_cb;
1756 g.push_back(
gcd(a.
op(i), part_b, &part_ca, &part_cb,
false));
1757 acc_ca.push_back(part_ca);
1779 throw(std::invalid_argument(
"lcm: arguments must be polynomials over the rationals"));
1782 ex g =
gcd(a, b, &ca, &cb,
false);
1825 factors.push_back(
expair(w, i));
1830 factors.push_back(
expair(g, i));
1836 const ex lost_factor =
quo(a,
mul{factors}, x);
1841 if (!factors.empty() && factors[0].coeff.is_equal(1)) {
1843 factors[0].rest *= lost_factor;
1848 std::move(factors.begin(), factors.end(), std::back_inserter(results));
1901 for (
auto & it : sdv)
1909 throw (std::runtime_error(
"sqrfree(): invalid factorization variable"));
1918 if (factors.empty()) {
1927 if (args.
nops()>0) {
1928 for (
auto & it : factors)
1929 it.rest =
sqrfree(it.rest, args);
1933 ex result =
mul(factors);
1936 return result *
lcm.inverse();
1962 for (
size_t i=0; i<yun.size(); i++) {
1964 for (
size_t j=0; j<i_exponent; j++) {
1965 factor.push_back(
pow(yun[i].rest, j+1));
1966 dim +=
degree(yun[i].rest, x);
1968 for (
size_t k=0; k<yun.size(); k++) {
1969 if (yun[k].
coeff == i_exponent)
1970 prod *=
pow(yun[k].rest, i_exponent-1-j);
1972 prod *=
pow(yun[k].rest, yun[k].
coeff);
1974 cofac.push_back(prod.
expand());
1984 for (
size_t i=0, n=0, f=0; i<yun.size(); i++) {
1986 for (
size_t j=0; j<i_expo; j++) {
1987 for (
size_t k=0; k<size_t(
degree(yun[i].rest, x)); k++) {
1991 for (
size_t r=0; r+k<dim; r++) {
1992 sys(r+k, n) = cofac[f].
coeff(x, r);
2013 for (
size_t i=0, n=0, f=0; i<yun.size(); i++) {
2015 for (
size_t j=0; j<i_expo; j++) {
2017 for (
size_t k=0; k<size_t(
degree(yun[i].rest, x)); k++) {
2019 frac_numer += sol(n, 0) *
pow(x, k);
2022 sum += frac_numer /
factor[f];
2083 auto it = rev_lookup.
find(e_replaced);
2084 if (it != rev_lookup.end())
2089 for (
auto & it : repl)
2099 for (
auto & it : repl) {
2118 rev_lookup.erase(it.second);
2119 rev_lookup.insert({
exp(e_replaced.
op(0)/Num), es});
2120 repl.erase(it.first);
2121 repl.insert({es,
exp(e_replaced.
op(0)/Num)});
2130 for (
auto & it : repl) {
2135 ratio =
normal(e_replaced.
op(1) / it.second.
op(1));
2137 ratio = e_replaced.
op(1);
2154 rev_lookup.erase(it.second);
2155 rev_lookup.insert({
pow(e_replaced.
op(0), e_replaced.
op(1)/Num), es});
2156 repl.erase(it.first);
2157 repl.insert({es,
pow(e_replaced.
op(0), e_replaced.
op(1)/Num)});
2170 repl.insert({es, e_replaced});
2171 rev_lookup.insert({e_replaced, es});
2180 repl.insert(std::make_pair(es, e_replaced));
2181 rev_lookup.insert(std::make_pair(e_replaced, es));
2196 for (
auto & it : repl)
2197 if (it.second.is_equal(e_replaced))
2204 repl.insert(std::make_pair(es, e_replaced));
2223 size_t nmod = modifier.
nops();
2225 for (
size_t imod = nmod; imod < modifier.
nops(); ++imod) {
2227 this_repl.insert(std::make_pair(modifier.
op(imod).
op(0), modifier.
op(imod).
op(1)));
2291 throw(std::overflow_error(
"frac_cancel: division by zero in frac_cancel"));
2299 pre_factor = den_lcm / num_lcm;
2303 if (
gcd(num, den, &cnum, &cden,
false) !=
_ex1) {
2339 nums.reserve(
seq.size()+1);
2340 dens.reserve(
seq.size()+1);
2341 size_t nmod = modifier.
nops();
2342 for (
auto & it :
seq) {
2344 nums.push_back(n.
op(0));
2345 dens.push_back(n.
op(1));
2348 nums.push_back(n.
op(0));
2349 dens.push_back(n.
op(1));
2357 auto num_it = nums.begin(), num_itend = nums.end();
2358 auto den_it = dens.begin(), den_itend = dens.end();
2360 for (
size_t imod = nmod; imod < modifier.
nops(); ++imod) {
2361 while (num_it != num_itend) {
2368 num_it = nums.begin();
2369 den_it = dens.begin();
2372 ex num = *num_it++, den = *den_it++;
2373 while (num_it != num_itend) {
2375 ex next_num = *num_it++, next_den = *den_it++;
2378 while ((den_it != den_itend) && next_den.is_equal(*den_it)) {
2379 next_num += *num_it;
2385 ex co_den1, co_den2;
2386 ex g =
gcd(den, next_den, &co_den1, &co_den2,
false);
2387 num = ((num * co_den2) + (next_num * co_den1)).
expand();
2406 size_t nmod = modifier.
nops();
2407 for (
auto & it :
seq) {
2409 num.push_back(n.
op(0));
2410 den.push_back(n.
op(1));
2413 num.push_back(n.
op(0));
2414 den.push_back(n.
op(1));
2415 auto num_it = num.begin(), num_itend = num.end();
2416 auto den_it = den.begin();
2417 for (
size_t imod = nmod; imod < modifier.
nops(); ++imod) {
2418 while (num_it != num_itend) {
2424 num_it = num.begin();
2425 den_it = den.begin();
2440 size_t nmod = modifier.
nops();
2442 for (
size_t imod = nmod; imod < modifier.
nops(); ++imod)
2445 nmod = modifier.
nops();
2447 for (
size_t imod = nmod; imod < modifier.
nops(); ++imod)
2449 n_exponent = n_exponent.
op(0) / n_exponent.
op(1);
2497 for (
auto & it :
seq) {
2498 ex restexp = it.rest.normal();
2520 exmap repl, rev_lookup;
2523 ex e =
bp->normal(repl, rev_lookup, modifier);
2527 if (!repl.empty()) {
2528 for(
size_t i=0; i < modifier.
nops(); ++i)
2534 return e.
op(0) / e.
op(1);
2545 exmap repl, rev_lookup;
2548 ex e =
bp->normal(repl, rev_lookup, modifier);
2555 for(
size_t i=0; i < modifier.
nops(); ++i)
2570 exmap repl, rev_lookup;
2573 ex e =
bp->normal(repl, rev_lookup, modifier);
2580 for(
size_t i=0; i < modifier.
nops(); ++i)
2595 exmap repl, rev_lookup;
2598 ex e =
bp->normal(repl, rev_lookup, modifier);
2605 for(
size_t i=0; i < modifier.
nops(); ++i)
2628 return bp->to_rational(repl);
2633 return bp->to_polynomial(repl);
2737 s.reserve(
seq.size());
2738 for (
auto & it :
seq)
2753 s.reserve(
seq.size());
2754 for (
auto & it :
seq)
2773 size_t num = e.
nops();
2774 exvector terms; terms.reserve(num);
2778 for (
size_t i=0; i<num; i++) {
2805 for (
size_t i=0; i<num; i++) {
2811 for (
size_t j=0; j<t.
nops(); j++) {
2814 for (
size_t k=0; k<t.
nops(); k++) {
2818 v.push_back(t.
op(k));
2834 size_t num = e.
nops();
2837 for (
size_t i=0; i<num; i++)
2843 const ex e_exp(e.
op(1));
2849 return pow(pre_res, e_exp);
2883 throw(std::runtime_error(
"resultant(): arguments must be polynomials"));
2885 const int h1 = ee1.
degree(s);
2886 const int l1 = ee1.
ldegree(s);
2887 const int h2 = ee2.
degree(s);
2888 const int l2 = ee2.
ldegree(s);
2890 const int msize = h1 + h2;
2893 for (
int l = h1; l >= l1; --l) {
2895 for (
int k = 0; k < h2; ++k)
2898 for (
int l = h2; l >= l2; --l) {
2900 for (
int k = 0; k < h1; ++k)
2901 m(k+h2, k+h2-l) = e;
Interface to GiNaC's sums of expressions.
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Interface to GiNaC's ABC.
ex coeff(const ex &s, int n=1) const override
Return coefficient of degree n in object s.
numeric integer_content() const override
numeric max_coefficient() const override
Implementation ex::max_coefficient().
ex expand(unsigned options=0) const override
Expand expression, i.e.
ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const override
Implementation of ex::normal() for a sum.
ex recombine_pair_to_ex(const expair &p) const override
Form an ex out of an expair, using the corresponding semantics.
ex smod(const numeric &xi) const override
Apply symmetric modular homomorphism to an expanded multivariate polynomial.
virtual size_t nops() const
Number of operands/members.
const basic & clearflag(unsigned f) const
Clear some status_flags.
virtual numeric integer_content() const
virtual numeric max_coefficient() const
Implementation ex::max_coefficient().
virtual ex to_polynomial(exmap &repl) const
virtual ex to_rational(exmap &repl) const
Default implementation of ex::to_rational().
virtual ex coeff(const ex &s, int n=1) const
Return coefficient of degree n in object s.
virtual ex smod(const numeric &xi) const
Apply symmetric modular homomorphism to an expanded multivariate polynomial.
virtual ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const
Default implementation of ex::normal().
virtual ex map(map_function &f) const
Construct new expression by applying the specified function to all sub-expressions (one level only,...
size_t nops() const override
Number of operands/members.
ex op(size_t i) const override
Return operand/member at position i.
container & remove_first()
Remove first element.
container & append(const ex &b)
Add element at back.
Lightweight wrapper for GiNaC's symbolic objects.
ex to_rational(exmap &repl) const
Rationalization of non-rational functions.
ex unit(const ex &x) const
Compute unit part (= sign of leading coefficient) of a multivariate polynomial in Q[x].
numeric integer_content() const
Compute the integer content (= GCD of all numeric coefficients) of an expanded polynomial.
ex primpart(const ex &x) const
Compute primitive part of a multivariate polynomial in Q[x].
ex lcoeff(const ex &s) const
bool find(const ex &pattern, exset &found) const
Find all occurrences of a pattern.
ex diff(const symbol &s, unsigned nth=1) const
Compute partial derivative of an expression.
ex expand(unsigned options=0) const
Expand an expression.
ex numer_denom() const
Get numerator and denominator of an expression.
bool is_equal(const ex &other) const
ex normal() const
Normalization of rational functions.
int degree(const ex &s) const
ptr< basic > bp
pointer to basic object managed by this
numeric max_coefficient() const
Return maximum (absolute value) coefficient of a polynomial.
ex to_polynomial(exmap &repl) const
void unitcontprim(const ex &x, ex &u, ex &c, ex &p) const
Compute unit part, content part, and primitive part of a multivariate polynomial in Q[x].
friend bool is_exactly_a(const ex &)
Check if ex is a handle to a T, not including base classes.
friend const T & ex_to(const ex &)
Return a reference to the basic-derived class T object embedded in an expression.
ex smod(const numeric &xi) const
ex subs(const exmap &m, unsigned options=0) const
bool info(unsigned inf) const
friend bool is_a(const ex &)
Check if ex is a handle to a T, including base classes.
ex denom() const
Get denominator of an expression.
ex content(const ex &x) const
Compute content part (= unit normal GCD of all coefficients) of a multivariate polynomial in Q[x].
int ldegree(const ex &s) const
ex numer() const
Get numerator of an expression.
ex coeff(const ex &s, int n=1) const
ex to_polynomial(exmap &repl) const override
Implementation of ex::to_polynomial() for expairseqs.
virtual ex default_overall_coeff() const
virtual ex thisexpairseq(const epvector &v, const ex &oc, bool do_index_renaming=false) const
Create an object of this type.
ex to_rational(exmap &repl) const override
Implementation of ex::to_rational() for expairseqs.
virtual ex recombine_pair_to_ex(const expair &p) const
Form an ex out of an expair, using the corresponding semantics.
virtual expair split_ex_to_pair(const ex &e) const
Form an expair from an ex, using the corresponding semantics.
Exception thrown by heur_gcd() to signal failure.
ex determinant(unsigned algo=determinant_algo::automatic) const
Determinant of square matrix.
matrix solve(const matrix &vars, const matrix &rhs, unsigned algo=solve_algo::automatic) const
Solve a linear system consisting of a m x n matrix and a m x p right hand side by applying an elimina...
ex recombine_pair_to_ex(const expair &p) const override
Form an ex out of an expair, using the corresponding semantics.
ex smod(const numeric &xi) const override
Apply symmetric modular homomorphism to an expanded multivariate polynomial.
ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const override
Implementation of ex::normal() for a product.
numeric integer_content() const override
mul(const ex &lh, const ex &rh)
numeric max_coefficient() const override
Implementation ex::max_coefficient().
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
ex to_rational(exmap &repl) const override
Implementation of ex::to_rational() for a numeric.
numeric integer_content() const override
bool is_rational() const
True if object is an exact rational number, may even be complex (denominator may be unity).
const numeric real() const
Real part of a number.
ex to_polynomial(exmap &repl) const override
Implementation of ex::to_polynomial() for a numeric.
bool is_real() const
True if object is a real integer, rational or float (but not complex).
const numeric numer() const
Numerator.
bool is_integer() const
True if object is a non-complex integer.
ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const override
Implementation of ex::normal() for a numeric.
const numeric denom() const
Denominator.
const numeric imag() const
Imaginary part of a number.
numeric max_coefficient() const override
Implementation ex::max_coefficient().
int int_length() const
Size in binary notation.
ex smod(const numeric &xi) const override
Apply symmetric modular homomorphism to an expanded multivariate polynomial.
const numeric inverse() const
Inverse of a number.
bool is_zero() const
True if object is zero.
This class holds a two-component object, a basis and and exponent representing exponentiation.
ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const override
Implementation of ex::normal() for powers.
ex to_rational(exmap &repl) const override
Implementation of ex::to_rational() for powers.
ex to_polynomial(exmap &repl) const override
Implementation of ex::to_polynomial() for powers.
ex var
Series variable (holds a symbol).
pseries(const ex &rel_, const epvector &ops_)
Construct pseries from a vector of coefficients and powers.
epvector seq
Vector of {coefficient, power} pairs.
ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const override
Implementation of ex::normal() for pseries.
This class holds a relation consisting of two expressions and a logical relation between them.
@ evaluated
.eval() has already done its job
@ hash_calculated
.calchash() has already done its job
@ no_pattern
disable pattern matching
ex to_rational(exmap &repl) const override
Implementation of ex::to_rational() for symbols.
ex normal(exmap &repl, exmap &rev_lookup, lst &modifier) const override
Implementation of ex::normal() for symbols.
ex to_polynomial(exmap &repl) const override
Implementation of ex::to_polynomial() for symbols.
Interface to GiNaC's constant types and some special constants.
Interface to GiNaC's light-weight expression handles.
Interface to sequences of expression pairs.
Interface to class signaling failure of operation.
#define is_ex_the_function(OBJ, FUNCNAME)
Interface to GiNaC's initially known functions.
Definition of GiNaC's lst.
Interface to symbolic matrices.
Interface to GiNaC's products of expressions.
const numeric I
Imaginary unit.
ex denom(const ex &thisex)
const numeric pow(const numeric &x, const numeric &y)
static ex replace_with_symbol(const ex &e, exmap &repl, exmap &rev_lookup, lst &modifier)
Create a symbol for replacing the expression "e" (or return a previously assigned symbol).
container< std::list > lst
std::map< ex, ex, ex_is_less > exmap
ex sqrfree(const ex &a, const lst &l)
Compute a square-free factorization of a multivariate polynomial in Q[X].
B & dynallocate(Args &&... args)
Constructs a new (class basic or derived) B object on the heap.
std::vector< expair > epvector
expair-vector
ex resultant(const ex &e1, const ex &e2, const ex &s)
Resultant of two expressions e1,e2 with respect to symbol s.
const numeric abs(const numeric &x)
Absolute value.
static ex interpolate(const ex &gamma, const numeric &xi, const ex &x, int degree_hint=1)
xi-adic polynomial interpolation
static void add_symbol(const ex &s, sym_desc_vec &v)
bool is_negative(const numeric &x)
bool is_rational(const numeric &x)
ex gcd(const ex &a, const ex &b, ex *ca, ex *cb, bool check_args, unsigned options)
Compute GCD (Greatest Common Divisor) of multivariate polynomials a(X) and b(X) in Z[X].
static ex find_common_factor(const ex &e, ex &factor, exmap &repl)
Remove the common factor in the terms of a sum 'e' by calculating the GCD, and multiply it into the e...
function psi(const T1 &p1)
ex prem(const ex &a, const ex &b, const ex &x, bool check_args)
Pseudo-remainder of polynomials a(x) and b(x) in Q[x].
attribute_pure const T & ex_to(const ex &e)
Return a reference to the basic-derived class T object embedded in an expression.
static ex gcd_pf_pow_pow(const ex &a, const ex &b, ex *ca, ex *cb)
static epvector sqrfree_yun(const ex &a, const symbol &x)
Compute square-free factorization of multivariate polynomial a(x) using Yun's algorithm.
const numeric exp(const numeric &x)
Exponential function.
ex quo(const ex &a, const ex &b, const ex &x, bool check_args)
Quotient q(x) of polynomials a(x) and b(x) in Q[x].
static ex sr_gcd(const ex &a, const ex &b, sym_desc_vec::const_iterator var)
Compute GCD of multivariate polynomials using the subresultant PRS algorithm.
static bool get_first_symbol(const ex &e, ex &x)
Return pointer to first symbol found in expression.
const numeric smod(const numeric &a_, const numeric &b_)
Modulus (in symmetric representation).
int degree(const ex &thisex, const ex &s)
static ex gcd_pf_mul(const ex &a, const ex &b, ex *ca, ex *cb)
ex sqrfree_parfrac(const ex &a, const symbol &x)
Compute square-free partial fraction decomposition of rational function a(x).
ex lcm(const ex &a, const ex &b, bool check_args)
Compute LCM (Least Common Multiple) of multivariate polynomials in Z[X].
const numeric iquo(const numeric &a, const numeric &b)
Numeric integer quotient.
bool is_a(const basic &obj)
Check if obj is a T, including base classes.
static bool divide_in_z(const ex &a, const ex &b, ex &q, sym_desc_vec::const_iterator var)
Exact polynomial division of a(X) by b(X) in Z[X].
const numeric isqrt(const numeric &x)
Integer numeric square root.
ex normal(const ex &thisex)
ex decomp_rational(const ex &a, const ex &x)
Decompose rational function a(x)=N(x)/D(x) into P(x)+n(x)/D(x) with degree(n, x) < degree(D,...
static bool heur_gcd(ex &res, const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const_iterator var)
Compute GCD of multivariate polynomials using the heuristic GCD algorithm.
ex coeff(const ex &thisex, const ex &s, int n=1)
static ex multiply_lcm(const ex &e, const numeric &lcm)
Bring polynomial from Q[X] to Z[X] by multiplying in the previously determined LCM of the coefficient...
static bool heur_gcd_z(ex &res, const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const_iterator var)
Compute GCD of multivariate polynomials using the heuristic GCD algorithm.
ex numer(const ex &thisex)
ex factor(const ex &poly, unsigned options)
Interface function to the outside world.
int to_int(const numeric &x)
ex collect_common_factors(const ex &e)
Collect common factors in sums.
static numeric lcm_of_coefficients_denominators(const ex &e)
Compute LCM of denominators of coefficients of a polynomial.
bool is_integer(const numeric &x)
static numeric lcmcoeff(const ex &e, const numeric &l)
static void get_symbol_stats(const ex &a, const ex &b, sym_desc_vec &v)
Collect statistical information about symbols in polynomials.
ex rem(const ex &a, const ex &b, const ex &x, bool check_args)
Remainder r(x) of polynomials a(x) and b(x) in Q[x].
ex sprem(const ex &a, const ex &b, const ex &x, bool check_args)
Sparse pseudo-remainder of polynomials a(x) and b(x) in Q[x].
std::vector< sym_desc > sym_desc_vec
bool is_exactly_a(const basic &obj)
Check if obj is a T, not including base classes.
static ex frac_cancel(const ex &n, const ex &d)
Fraction cancellation.
bool divide(const ex &a, const ex &b, ex &q, bool check_args)
Exact polynomial division of a(X) by b(X) in Q[X].
static void collect_symbols(const ex &e, sym_desc_vec &v)
std::vector< ex > exvector
ex numer_denom(const ex &thisex)
static ex gcd_pf_pow(const ex &a, const ex &b, ex *ca, ex *cb)
ex expand(const ex &thisex, unsigned options=0)
This file defines several functions that work on univariate and multivariate polynomials and rational...
Makes the interface to the underlying bignum package available.
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
Interface to class for extended truncated power series.
Interface to relations between expressions.
@ use_sr_gcd
By default GiNaC uses modular GCD algorithm.
@ no_part_factored
GiNaC tries to avoid expanding expressions when computing GCDs.
@ no_heur_gcd
Usually GiNaC tries heuristic GCD first, because typically it's much faster than anything else.
Function object for map().
Function object to be applied by basic::normal().
ex operator()(const ex &e) override
This structure holds information about the highest and lowest degrees in which a symbol appears in tw...
int max_deg
Maximum of deg_a and deg_b (Used for sorting).
int ldeg_a
Lowest degree of symbol in polynomial "a".
ex sym
Reference to symbol.
int ldeg_b
Lowest degree of symbol in polynomial "b".
bool operator<(const sym_desc &x) const
Comparison operator for sorting.
int deg_b
Highest degree of symbol in polynomial "b".
int deg_a
Highest degree of symbol in polynomial "a".
size_t max_lcnops
Maximum number of terms of leading coefficient of symbol in both polynomials.
sym_desc(const ex &s)
Initialize symbol, leave other variables uninitialized.
Interface to GiNaC's symbolic objects.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...