44#include "polynomial/chinrem_gcd.h" 
   62#define USE_TRIAL_DIVISION 0 
   70static int gcd_called = 0;
 
   71static int sr_gcd_called = 0;
 
   72static int heur_gcd_called = 0;
 
   73static int heur_gcd_failed = 0;
 
   76static struct _stat_print {
 
   79        std::cout << 
"gcd() called " << gcd_called << 
" times\n";
 
   80        std::cout << 
"sr_gcd() called " << sr_gcd_called << 
" times\n";
 
   81        std::cout << 
"heur_gcd() called " << heur_gcd_called << 
" times\n";
 
   82        std::cout << 
"heur_gcd() failed " << heur_gcd_failed << 
" times\n";
 
   97    if (is_a<symbol>(e)) {
 
  100    } 
else if (is_exactly_a<add>(e) || is_exactly_a<mul>(e)) {
 
  101        for (
size_t i=0; i<e.
nops(); i++)
 
  104    } 
else if (is_exactly_a<power>(e)) {
 
 
  166        if (it.sym.is_equal(s))  
 
 
  175    if (is_a<symbol>(e)) {
 
  177    } 
else if (is_exactly_a<add>(e) || is_exactly_a<mul>(e)) {
 
  178        for (
size_t i=0; i<e.
nops(); i++)
 
  180    } 
else if (is_exactly_a<power>(e)) {
 
 
  201    for (
auto & it : v) {
 
  202        int deg_a = a.
degree(it.sym);
 
  203        int deg_b = b.
degree(it.sym);
 
  206        it.max_deg = std::max(deg_a, deg_b);
 
  211    std::sort(v.begin(), v.end());
 
  214    std::clog << 
"Symbols:\n";
 
  215    auto it = v.begin(), itend = v.end();
 
  216    while (it != itend) {
 
  217        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;
 
  218        std::clog << 
"  lcoeff_a=" << a.
lcoeff(it->sym) << 
", lcoeff_b=" << b.
lcoeff(it->sym) << std::endl;
 
 
  234        return lcm(ex_to<numeric>(e).
denom(), l);
 
  235    else if (is_exactly_a<add>(e)) {
 
  237        for (
size_t i=0; i<e.
nops(); i++)
 
  240    } 
else if (is_exactly_a<mul>(e)) {
 
  242        for (
size_t i=0; i<e.
nops(); i++)
 
  245    } 
else if (is_exactly_a<power>(e)) {
 
  246        if (is_a<symbol>(e.
op(0)))
 
 
  277    if (is_exactly_a<mul>(e)) {
 
  279        size_t num = e.
nops();
 
  283        for (
size_t i=0; i<num; i++) {
 
  288        v.push_back(
lcm / lcm_accum);
 
  289        return dynallocate<mul>(v);
 
  290    } 
else if (is_exactly_a<add>(e)) {
 
  292        size_t num = e.
nops();
 
  295        for (
size_t i=0; i<num; i++)
 
  297        return dynallocate<add>(v);
 
  298    } 
else if (is_exactly_a<power>(e)) {
 
  299        if (!is_a<symbol>(e.
op(0))) {
 
  302            numeric root_of_lcm = 
lcm.power(ex_to<numeric>(e.
op(1)).inverse());
 
  308    return dynallocate<mul>(e, 
lcm);
 
 
  336    for (
auto & it : 
seq) {
 
  339        c = 
gcd(ex_to<numeric>(it.coeff).numer(), 
c);
 
  340        l = 
lcm(ex_to<numeric>(it.coeff).denom(), l);
 
 
  350#ifdef DO_GINAC_ASSERT 
  351    for (
auto & it : 
seq) {
 
 
  376        throw(std::overflow_error(
"quo: division by zero"));
 
  377    if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b))
 
  384        throw(std::invalid_argument(
"quo: arguments must be polynomials over the rationals"));
 
  391    int rdeg = 
r.degree(
x);
 
  393    bool blcoeff_is_numeric = is_exactly_a<numeric>(blcoeff);
 
  394    exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
 
  395    while (rdeg >= bdeg) {
 
  397        if (blcoeff_is_numeric)
 
  398            term = rcoeff / blcoeff;
 
  400            if (!
divide(rcoeff, blcoeff, term, 
false))
 
  401                return dynallocate<fail>();
 
  403        term *= 
pow(
x, rdeg - bdeg);
 
  410    return dynallocate<add>(v);
 
 
  426        throw(std::overflow_error(
"rem: division by zero"));
 
  427    if (is_exactly_a<numeric>(a)) {
 
  428        if  (is_exactly_a<numeric>(b))
 
  438        throw(std::invalid_argument(
"rem: arguments must be polynomials over the rationals"));
 
  445    int rdeg = 
r.degree(
x);
 
  447    bool blcoeff_is_numeric = is_exactly_a<numeric>(blcoeff);
 
  448    while (rdeg >= bdeg) {
 
  450        if (blcoeff_is_numeric)
 
  451            term = rcoeff / blcoeff;
 
  453            if (!
divide(rcoeff, blcoeff, term, 
false))
 
  454                return dynallocate<fail>();
 
  456        term *= 
pow(
x, rdeg - bdeg);
 
 
  477    if (is_exactly_a<fail>(q))
 
 
  495        throw(std::overflow_error(
"prem: division by zero"));
 
  496    if (is_exactly_a<numeric>(a)) {
 
  497        if (is_exactly_a<numeric>(b))
 
  503        throw(std::invalid_argument(
"prem: arguments must be polynomials over the rationals"));
 
  512        blcoeff = eb.
coeff(
x, bdeg);
 
  516            eb -= blcoeff * 
pow(
x, bdeg);
 
  520    int delta = rdeg - bdeg + 1, i = 0;
 
  521    while (rdeg >= bdeg && !
r.is_zero()) {
 
  523        ex term = (
pow(
x, rdeg - bdeg) * eb * rlcoeff).
expand();
 
  527            r -= rlcoeff * 
pow(
x, rdeg);
 
  532    return pow(blcoeff, delta - i) * 
r;
 
 
  547        throw(std::overflow_error(
"prem: division by zero"));
 
  548    if (is_exactly_a<numeric>(a)) {
 
  549        if (is_exactly_a<numeric>(b))
 
  555        throw(std::invalid_argument(
"prem: arguments must be polynomials over the rationals"));
 
  564        blcoeff = eb.
coeff(
x, bdeg);
 
  568            eb -= blcoeff * 
pow(
x, bdeg);
 
  572    while (rdeg >= bdeg && !
r.is_zero()) {
 
  574        ex term = (
pow(
x, rdeg - bdeg) * eb * rlcoeff).
expand();
 
  578            r -= rlcoeff * 
pow(
x, rdeg);
 
 
  598        throw(std::overflow_error(
"divide: division by zero"));
 
  603    if (is_exactly_a<numeric>(b)) {
 
  606    } 
else if (is_exactly_a<numeric>(a))
 
  616        throw(std::invalid_argument(
"divide: arguments must be polynomials over the rationals"));
 
  621        throw(std::invalid_argument(
"invalid expression in divide()"));
 
  624    if (is_exactly_a<mul>(b)) {
 
  626        ex rem_new, rem_old = a;
 
  627        for (
size_t i=0; i < b.
nops(); i++) {
 
  628            if (! 
divide(rem_old, b.
op(i), rem_new, 
false))
 
  634    } 
else if (is_exactly_a<power>(b)) {
 
  635        const ex& bb(b.
op(0));
 
  636        int exp_b = ex_to<numeric>(b.
op(1)).to_int();
 
  637        ex rem_new, rem_old = a;
 
  638        for (
int i=exp_b; i>0; i--) {
 
  639            if (! 
divide(rem_old, bb, rem_new, 
false))
 
  647    if (is_exactly_a<mul>(a)) {
 
  652        bool divisible_p = 
false;
 
  653        for (i=0; i < a.
nops(); ++i) {
 
  654            if (
divide(a.
op(i), b, rem_i, 
false)) {
 
  661            resv.reserve(a.
nops());
 
  662            for (
size_t j=0; j < a.
nops(); j++) {
 
  664                    resv.push_back(rem_i);
 
  666                    resv.push_back(a.
op(j));
 
  668            q = dynallocate<mul>(resv);
 
  671    } 
else if (is_exactly_a<power>(a)) {
 
  674        const ex& ab(a.
op(0));
 
  675        int a_exp = ex_to<numeric>(a.
op(1)).to_int();
 
  677        if (
divide(ab, b, rem_i, 
false)) {
 
  678            q = rem_i * 
pow(ab, a_exp - 1);
 
  697    int rdeg = 
r.degree(
x);
 
  699    bool blcoeff_is_numeric = is_exactly_a<numeric>(blcoeff);
 
  700    exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
 
  701    while (rdeg >= bdeg) {
 
  703        if (blcoeff_is_numeric)
 
  704            term = rcoeff / blcoeff;
 
  706            if (!
divide(rcoeff, blcoeff, term, 
false))
 
  708        term *= 
pow(
x, rdeg - bdeg);
 
  712            q = dynallocate<add>(v);
 
 
  726typedef std::pair<ex, ex> ex2;
 
  727typedef std::pair<ex, bool> exbool;
 
  730    bool operator() (
const ex2 &p, 
const ex2 &q)
 const  
  732        int cmp = p.first.compare(q.first);
 
  733        return ((cmp<0) || (!(cmp>0) && p.second.compare(q.second)<0));
 
  737typedef std::map<ex2, exbool, ex2_less> ex2_exbool_remember;
 
  761        throw(std::overflow_error(
"divide_in_z: division by zero"));
 
  766    if (is_exactly_a<numeric>(a)) {
 
  767        if (is_exactly_a<numeric>(b)) {
 
  782    static ex2_exbool_remember dr_remember;
 
  783    ex2_exbool_remember::const_iterator remembered = dr_remember.
find(ex2(a, b));
 
  784    if (remembered != dr_remember.end()) {
 
  785        q = remembered->second.first;
 
  786        return remembered->second.second;
 
  790    if (is_exactly_a<power>(b)) {
 
  791        const ex& bb(b.
op(0));
 
  793        int exp_b = ex_to<numeric>(b.
op(1)).to_int();
 
  794        for (
int i=exp_b; i>0; i--) {
 
  802    if (is_exactly_a<mul>(b)) {
 
  804        for (
const auto & it : b) {
 
  816    const ex &
x = var->sym;
 
  823#if USE_TRIAL_DIVISION 
  829    vector<numeric> alpha; alpha.reserve(adeg + 1);
 
  833    for (i=0; i<=adeg; i++) {
 
  841        alpha.push_back(point);
 
  847    vector<numeric> rcp; rcp.reserve(adeg + 1);
 
  849    for (
k=1; 
k<=adeg; 
k++) {
 
  850        numeric product = alpha[
k] - alpha[0];
 
  852            product *= alpha[
k] - alpha[i];
 
  853        rcp.push_back(product.
inverse());
 
  859    for (
k=1; 
k<=adeg; 
k++) {
 
  861        for (i=
k-2; i>=0; i--)
 
  862            temp = temp * (alpha[
k] - alpha[i]) + v[i];
 
  863        v.push_back((u[
k] - temp) * rcp[
k]);
 
  868    for (
k=adeg-1; 
k>=0; 
k--)
 
  869        c = 
c * (
x - alpha[
k]) + v[
k];
 
  871    if (
c.degree(
x) == (adeg - bdeg)) {
 
  886    exvector v; v.reserve(std::max(rdeg - bdeg + 1, 0));
 
  887    while (rdeg >= bdeg) {
 
  895            q = dynallocate<add>(v);
 
  897            dr_remember[ex2(a, b)] = exbool(q, 
true);
 
  904    dr_remember[ex2(a, b)] = exbool(q, 
false);
 
 
  926    if (is_exactly_a<numeric>(
c))
 
  933            throw(std::invalid_argument(
"invalid expression in unit()"));
 
 
  947    if (is_exactly_a<numeric>(*
this))
 
  968    for (
int i=ldeg; i<=deg; i++)
 
 
 1001    if (is_exactly_a<numeric>(*
this))
 
 1006    if (is_exactly_a<numeric>(
c))
 
 1007        return *
this / (
c * u);
 
 1009        return quo(*
this, 
c * u, 
x, 
false);
 
 
 1032    if (is_exactly_a<numeric>(*
this)) {
 
 1035            c = 
abs(ex_to<numeric>(*
this));
 
 1061    if (is_exactly_a<numeric>(
c))
 
 1062        p = *
this / (
c * u);
 
 1064        p = 
quo(e, 
c * u, 
x, 
false);
 
 
 1081static ex sr_gcd(
const ex &a, 
const ex &b, sym_desc_vec::const_iterator var)
 
 1088    const ex &
x = var->sym;
 
 1109    ex gamma = 
gcd(cont_c, cont_d, 
nullptr, 
nullptr, 
false);
 
 1117    int delta = cdeg - ddeg;
 
 1129            throw(std::runtime_error(
"invalid expression in sr_gcd(), division failed"));
 
 1132            if (is_exactly_a<numeric>(
r))
 
 1144        delta = cdeg - ddeg;
 
 
 1175    for (
auto & it : 
seq) {
 
 1178        a = 
abs(ex_to<numeric>(it.coeff));
 
 
 1187#ifdef DO_GINAC_ASSERT 
 1188    for (
auto & it : 
seq) {
 
 
 1216    newseq.reserve(
seq.size()+1);
 
 1217    for (
auto & it : 
seq) {
 
 1225    return dynallocate<add>(std::move(newseq), 
coeff);
 
 
 1230#ifdef DO_GINAC_ASSERT 
 1231    for (
auto & it : 
seq) {
 
 1235    mul & mulcopy = dynallocate<mul>(*
this);
 
 
 1247    exvector g; g.reserve(degree_hint);
 
 1250    for (
int i=0; !e.
is_zero(); i++) {
 
 1252        g.push_back(gi * 
pow(
x, i));
 
 1255    return dynallocate<add>(g);
 
 
 1278                   sym_desc_vec::const_iterator var)
 
 1289    if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b)) {
 
 1290        numeric g = 
gcd(ex_to<numeric>(a), ex_to<numeric>(b));
 
 1292            *ca = ex_to<numeric>(a) / g;
 
 1294            *cb = ex_to<numeric>(b) / g;
 
 1300    const ex &
x = var->sym;
 
 1314        xi = mq * (*_num2_p) + (*_num2_p);
 
 1316        xi = mp * (*_num2_p) + (*_num2_p);
 
 1319    for (
int t=0; t<6; t++) {
 
 
 1372                 sym_desc_vec::const_iterator var)
 
 1387    const ex ai = a*ab_lcm;
 
 1388    const ex bi = b*ab_lcm;
 
 1390        throw std::logic_error(
"heur_gcd: not an integer polynomial [1]");
 
 1393        throw std::logic_error(
"heur_gcd: not an integer polynomial [2]");
 
 1397        found = 
heur_gcd_z(res, ai, bi, ca, cb, var);
 
 
 1415static ex 
gcd_pf_pow(
const ex& a, 
const ex& b, ex* ca, ex* cb);
 
 1419static ex 
gcd_pf_mul(
const ex& a, 
const ex& b, ex* ca, ex* cb);
 
 1440    if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b)) {
 
 1441        numeric g = 
gcd(ex_to<numeric>(a), ex_to<numeric>(b));
 
 1450                    *ca = ex_to<numeric>(a) / g;
 
 1452                    *cb = ex_to<numeric>(b) / g;
 
 1460        throw(std::invalid_argument(
"gcd: arguments must be polynomials over the rationals"));
 
 1465        if (is_exactly_a<mul>(a) || is_exactly_a<mul>(b))
 
 1468        if (is_exactly_a<power>(a) || is_exactly_a<power>(b))
 
 1507    if (is_a<symbol>(aex)) {
 
 1517    if (is_a<symbol>(bex)) {
 
 1527    if (is_exactly_a<numeric>(aex)) {
 
 1531            *ca = ex_to<numeric>(aex)/g;
 
 1537    if (is_exactly_a<numeric>(bex)) {
 
 1543            *cb = ex_to<numeric>(bex)/g;
 
 1553    auto vari = sym_stats.begin();
 
 1554    while ((vari != sym_stats.end()) && 
 
 1555           (((vari->ldeg_b == 0) && (vari->deg_b == 0)) ||
 
 1556            ((vari->ldeg_a == 0) && (vari->deg_a == 0))))
 
 1560    if (vari == sym_stats.end()) {
 
 1569    rotate(sym_stats.begin(), vari, sym_stats.end());
 
 1571    sym_desc_vec::const_iterator var = sym_stats.begin();
 
 1572    const ex &
x = var->sym;
 
 1575    int ldeg_a = var->ldeg_a;
 
 1576    int ldeg_b = var->ldeg_b;
 
 1577    int min_ldeg = std::min(ldeg_a,ldeg_b);
 
 1579        ex common = 
pow(
x, min_ldeg);
 
 1580        return gcd((aex / common).
expand(), (bex / common).
expand(), ca, cb, 
false) * common;
 
 1584    if (var->deg_a == 0 && var->deg_b != 0 ) {
 
 1585        ex bex_u, bex_c, bex_p;
 
 1587        ex g = 
gcd(aex, bex_c, ca, cb, 
false);
 
 1589            *cb *= bex_u * bex_p;
 
 1591    } 
else if (var->deg_b == 0 && var->deg_a != 0) {
 
 1592        ex aex_u, aex_c, aex_p;
 
 1594        ex g = 
gcd(aex_c, bex, ca, cb, 
false);
 
 1596            *ca *= aex_u * aex_p;
 
 1603        bool found = 
heur_gcd(g, aex, bex, ca, cb, var);
 
 1622        g = 
sr_gcd(aex, bex, var);
 
 1625        for (std::size_t 
n = sym_stats.size(); 
n-- != 0; )
 
 1626            vars.push_back(sym_stats[
n].sym);
 
 1627        g = chinrem_gcd(aex, bex, vars);
 
 1638            divide(aex, g, *ca, 
false);
 
 1640            divide(bex, g, *cb, 
false);
 
 
 1650    const ex& exp_a = a.
op(1);
 
 1652    const ex& exp_b = b.
op(1);
 
 1656        if (exp_a < exp_b) {
 
 1660                *cb = 
pow(p, exp_b - exp_a);
 
 1661            return pow(p, exp_a);
 
 1664                *ca = 
pow(p, exp_a - exp_b);
 
 1667            return pow(p, exp_b);
 
 1672    ex p_gcd = 
gcd(p, pb, &p_co, &pb_co, 
false);
 
 1685    if (exp_a < exp_b) {
 
 1686        ex pg =  
gcd(
pow(p_co, exp_a), 
pow(p_gcd, exp_b-exp_a)*
pow(pb_co, exp_b), ca, cb, 
false);
 
 1687        return pow(p_gcd, exp_a)*pg;
 
 1689        ex pg = 
gcd(
pow(p_gcd, exp_a - exp_b)*
pow(p_co, exp_a), 
pow(pb_co, exp_b), ca, cb, 
false);
 
 1690        return pow(p_gcd, exp_b)*pg;
 
 
 1696    if (is_exactly_a<power>(a) && is_exactly_a<power>(b))
 
 1699    if (is_exactly_a<power>(b) && (! is_exactly_a<power>(a)))
 
 1705    const ex& exp_a = a.
op(1);
 
 1709            *ca = 
pow(p, exp_a - 1);
 
 1714    if (is_a<symbol>(p)) {
 
 1716        int ldeg_a = ex_to<numeric>(exp_a).to_int();
 
 1718        int min_ldeg = std::min(ldeg_a, ldeg_b);
 
 1720            ex common = 
pow(p, min_ldeg);
 
 1721            return gcd(
pow(p, ldeg_a - min_ldeg), (b / common).
expand(), ca, cb, 
false) * common;
 
 1726    ex p_gcd = 
gcd(p, b, &p_co, &bpart_co, 
false);
 
 1737    ex rg = 
gcd(
pow(p_gcd, exp_a-1)*
pow(p_co, exp_a), bpart_co, ca, cb, 
false);
 
 
 1743    if (is_exactly_a<mul>(a) && is_exactly_a<mul>(b)
 
 1747    if (is_exactly_a<mul>(b) && (!is_exactly_a<mul>(a)))
 
 1751    size_t num = a.
nops();
 
 1753    exvector acc_ca; acc_ca.reserve(num);
 
 1755    for (
size_t i=0; i<num; i++) {
 
 1756        ex part_ca, part_cb;
 
 1757        g.push_back(
gcd(a.
op(i), part_b, &part_ca, &part_cb, 
false));
 
 1758        acc_ca.push_back(part_ca);
 
 1762        *ca = dynallocate<mul>(acc_ca);
 
 1765    return dynallocate<mul>(g);
 
 
 1777    if (is_exactly_a<numeric>(a) && is_exactly_a<numeric>(b))
 
 1778        return lcm(ex_to<numeric>(a), ex_to<numeric>(b));
 
 1780        throw(std::invalid_argument(
"lcm: arguments must be polynomials over the rationals"));
 
 1783    ex g = 
gcd(a, b, &ca, &cb, 
false);
 
 
 1844        factors[0].rest *= lost_factor;
 
 1849    std::move(
factors.begin(), 
factors.end(), std::back_inserter(results));
 
 
 1891    if (is_exactly_a<numeric>(a) ||
 
 1902        for (
auto & it : sdv)
 
 1909    if (!is_a<symbol>(args.
op(0)))
 
 1910        throw (std::runtime_error(
"sqrfree(): invalid factorization variable"));
 
 1911    const symbol &
x = ex_to<symbol>(args.
op(0));
 
 1928    if (args.
nops()>0) {
 
 1930            it.rest = 
sqrfree(it.rest, args);
 
 1937    return result * 
lcm.inverse();
 
 
 1963    for (
size_t i=0; i<yun.size(); i++) {
 
 1965        for (
size_t j=0; j<i_exponent; j++) {
 
 1966            factor.push_back(
pow(yun[i].rest, j+1));
 
 1967            dim += 
degree(yun[i].rest, 
x);
 
 1969            for (
size_t k=0; 
k<yun.size(); 
k++) {
 
 1970                if (yun[
k].
coeff == i_exponent)
 
 1971                    prod *= 
pow(yun[
k].rest, i_exponent-1-j);
 
 1975            cofac.push_back(prod.
expand());
 
 1985    for (
size_t i=0, 
n=0, f=0; i<yun.size(); i++) {
 
 1986        size_t i_expo = 
to_int(ex_to<numeric>(yun[i].
coeff));
 
 1987        for (
size_t j=0; j<i_expo; j++) {
 
 1988            for (
size_t k=0; 
k<size_t(
degree(yun[i].rest, 
x)); 
k++) {
 
 1992                for (
size_t r=0; 
r+
k<dim; 
r++) {
 
 2014    for (
size_t i=0, 
n=0, f=0; i<yun.size(); i++) {
 
 2015        size_t i_expo = 
to_int(ex_to<numeric>(yun[i].
coeff));
 
 2016        for (
size_t j=0; j<i_expo; j++) {
 
 2018            for (
size_t k=0; 
k<size_t(
degree(yun[i].rest, 
x)); 
k++) {
 
 2020                frac_numer += sol(
n, 0) * 
pow(
x, 
k);
 
 2023            sum += frac_numer / 
factor[f];
 
 
 2084    auto it = rev_lookup.
find(e_replaced);
 
 2085    if (it != rev_lookup.end())
 
 2089    if (! is_a<numeric>(e_replaced))
 
 2090        for (
auto & it : repl)
 
 2091            if (is_a<power>(it.second) && e_replaced.
is_equal(it.second.op(0))) {
 
 2100        for (
auto & it : repl) {
 
 2103                if (is_a<numeric>(ratio) && ex_to<numeric>(ratio).
is_rational()) {
 
 2108                        return dynallocate<power>(it.first, ratio);
 
 2112                        ex es = dynallocate<symbol>();
 
 2119                        rev_lookup.erase(it.second);
 
 2120                        rev_lookup.insert({
exp(e_replaced.
op(0)/Num), es});
 
 2121                        repl.erase(it.first);
 
 2122                        repl.insert({es, 
exp(e_replaced.
op(0)/Num)});
 
 2123                        return dynallocate<power>(es, Num);
 
 2128    } 
else if (is_a<power>(e_replaced) && !is_a<numeric>(e_replaced.
op(0)) 
 
 2129               && ! (is_a<symbol>(e_replaced.
op(0))
 
 2130                   && is_a<numeric>(e_replaced.
op(1)) && ex_to<numeric>(e_replaced.
op(1)).is_integer())) {
 
 2131        for (
auto & it : repl) {
 
 2133                || (is_a<power>(it.second) && e_replaced.
op(0).
is_equal(it.second.op(0)))) {
 
 2135                if (is_a<power>(it.second))
 
 2136                    ratio = 
normal(e_replaced.
op(1) / it.second.
op(1));
 
 2138                    ratio = e_replaced.
op(1);
 
 2139                if (is_a<numeric>(ratio) && ex_to<numeric>(ratio).is_rational())  {
 
 2141                    if (ex_to<numeric>(ratio).is_integer()) {
 
 2144                        return dynallocate<power>(it.first, ratio);
 
 2148                        ex es = dynallocate<symbol>();
 
 2155                        rev_lookup.erase(it.second);
 
 2156                        rev_lookup.insert({
pow(e_replaced.
op(0), e_replaced.
op(1)/Num), es});
 
 2157                        repl.erase(it.first);
 
 2158                        repl.insert({es, 
pow(e_replaced.
op(0), e_replaced.
op(1)/Num)});
 
 2159                        return dynallocate<power>(es, Num);
 
 2169            ex es = dynallocate<symbol>();
 
 2171            repl.insert({es, e_replaced});
 
 2172            rev_lookup.insert({e_replaced, es});
 
 2180    ex es = dynallocate<symbol>();
 
 2181    repl.insert(std::make_pair(es, e_replaced));
 
 2182    rev_lookup.insert(std::make_pair(e_replaced, es));
 
 
 2197    for (
auto & it : repl)
 
 2198        if (it.second.is_equal(e_replaced))
 
 2204    ex es = dynallocate<symbol>();
 
 2205    repl.insert(std::make_pair(es, e_replaced));
 
 
 2224    size_t nmod = modifier.
nops(); 
 
 2226    for (
size_t imod = nmod; imod < modifier.
nops(); ++imod) {
 
 2228        this_repl.insert(std::make_pair(modifier.
op(imod).
op(0), modifier.
op(imod).
op(1)));
 
 2234        return dynallocate<lst>({
_ex1, 
power(result.
op(0), -result.
op(1))});
 
 2236        return dynallocate<lst>({result, 
_ex1});
 
 
 2244    return dynallocate<lst>({*
this, 
_ex1});
 
 
 2268    return dynallocate<lst>({numex, 
denom()});
 
 
 2286        return dynallocate<lst>({num, den});
 
 2290        return dynallocate<lst>({num, 
_ex1});
 
 2292        throw(std::overflow_error(
"frac_cancel: division by zero in frac_cancel"));
 
 2300    pre_factor = den_lcm / num_lcm;
 
 2304    if (
gcd(num, den, &cnum, &cden, 
false) != 
_ex1) {
 
 2311    if (is_exactly_a<numeric>(den)) {
 
 2320            if (ex_to<numeric>(den.
unit(
x)).is_negative()) {
 
 2329    return dynallocate<lst>({num * pre_factor.
numer(), den * pre_factor.
denom()});
 
 
 2340    nums.reserve(
seq.size()+1);
 
 2341    dens.reserve(
seq.size()+1);
 
 2342    size_t nmod = modifier.
nops(); 
 
 2343    for (
auto & it : 
seq) {
 
 2345        nums.push_back(
n.op(0));
 
 2346        dens.push_back(
n.op(1));
 
 2349    nums.push_back(
n.op(0));
 
 2350    dens.push_back(
n.op(1));
 
 2358    auto num_it = nums.begin(), num_itend = nums.end();
 
 2359    auto den_it = dens.begin(), den_itend = dens.end();
 
 2361    for (
size_t imod = nmod; imod < modifier.
nops(); ++imod) {
 
 2362        while (num_it != num_itend) {
 
 2369        num_it = nums.begin();
 
 2370        den_it = dens.begin();
 
 2373    ex num = *num_it++, den = *den_it++;
 
 2374    while (num_it != num_itend) {
 
 2376        ex next_num = *num_it++, next_den = *den_it++;
 
 2379        while ((den_it != den_itend) && next_den.is_equal(*den_it)) {
 
 2380            next_num += *num_it;
 
 2386        ex co_den1, co_den2;
 
 2387        ex g = 
gcd(den, next_den, &co_den1, &co_den2, 
false);
 
 2388        num = ((num * co_den2) + (next_num * co_den1)).
expand();
 
 
 2407    size_t nmod = modifier.
nops(); 
 
 2408    for (
auto & it : 
seq) {
 
 2410        num.push_back(
n.op(0));
 
 2411        den.push_back(
n.op(1));
 
 2413    n = ex_to<numeric>(
overall_coeff).normal(repl, rev_lookup, modifier);
 
 2414    num.push_back(
n.op(0));
 
 2415    den.push_back(
n.op(1));
 
 2416    auto num_it = num.begin(), num_itend = num.end();
 
 2417    auto den_it = den.begin();
 
 2418    for (
size_t imod = nmod; imod < modifier.
nops(); ++imod) {
 
 2419        while (num_it != num_itend) {
 
 2425        num_it = num.begin();
 
 2426        den_it = den.begin();
 
 2430    return frac_cancel(dynallocate<mul>(num), dynallocate<mul>(den));
 
 
 2441    size_t nmod = modifier.
nops(); 
 
 2442    ex n_basis = ex_to<basic>(
basis).
normal(repl, rev_lookup, modifier);
 
 2443    for (
size_t imod = nmod; imod < modifier.
nops(); ++imod)
 
 2446    nmod = modifier.
nops();
 
 2448    for (
size_t imod = nmod; imod < modifier.
nops(); ++imod)
 
 2450    n_exponent = n_exponent.
op(0) / n_exponent.
op(1);
 
 2457            return dynallocate<lst>({
pow(n_basis.
op(0), n_exponent), 
pow(n_basis.
op(1), n_exponent)});
 
 2462            return dynallocate<lst>({
pow(n_basis.
op(1), -n_exponent), 
pow(n_basis.
op(0), -n_exponent)});
 
 
 2498    for (
auto & it : 
seq) {
 
 
 2521    exmap repl, rev_lookup;
 
 2524    ex e = 
bp->
normal(repl, rev_lookup, modifier);
 
 2528    if (!repl.empty()) {
 
 2529        for(
size_t i=0; i < modifier.
nops(); ++i)
 
 2535    return e.
op(0) / e.
op(1);
 
 
 2546    exmap repl, rev_lookup;
 
 2549    ex e = 
bp->
normal(repl, rev_lookup, modifier);
 
 2556        for(
size_t i=0; i < modifier.
nops(); ++i)
 
 
 2571    exmap repl, rev_lookup;
 
 2574    ex e = 
bp->
normal(repl, rev_lookup, modifier);
 
 2581        for(
size_t i=0; i < modifier.
nops(); ++i)
 
 
 2596    exmap repl, rev_lookup;
 
 2599    ex e = 
bp->
normal(repl, rev_lookup, modifier);
 
 2606        for(
size_t i=0; i < modifier.
nops(); ++i)
 
 
 2721        if (is_exactly_a<mul>(basis_pref) || is_exactly_a<power>(basis_pref)) {
 
 
 2738    s.reserve(
seq.size());
 
 2739    for (
auto & it : 
seq)
 
 
 2754    s.reserve(
seq.size());
 
 2755    for (
auto & it : 
seq)
 
 
 2772    if (is_exactly_a<add>(e)) {
 
 2774        size_t num = e.
nops();
 
 2775        exvector terms; terms.reserve(num);
 
 2779        for (
size_t i=0; i<num; i++) {
 
 2782            if (is_exactly_a<add>(
x) || is_exactly_a<mul>(
x) || is_a<power>(
x)) {
 
 2806        for (
size_t i=0; i<num; i++) {
 
 2811            if (is_exactly_a<mul>(t)) {
 
 2812                for (
size_t j=0; j<t.
nops(); j++) {
 
 2815                        for (
size_t k=0; 
k<t.
nops(); 
k++) {
 
 2819                                v.push_back(t.
op(
k));
 
 2821                        t = dynallocate<mul>(v);
 
 2831        return dynallocate<add>(terms);
 
 2833    } 
else if (is_exactly_a<mul>(e)) {
 
 2835        size_t num = e.
nops();
 
 2838        for (
size_t i=0; i<num; i++)
 
 2841        return dynallocate<mul>(v);
 
 2843    } 
else if (is_exactly_a<power>(e)) {
 
 2844        const ex e_exp(e.
op(1));
 
 2850            return pow(pre_res, e_exp);
 
 
 2864    if (is_exactly_a<add>(e) || is_exactly_a<mul>(e) || is_exactly_a<power>(e)) {
 
 
 2884        throw(std::runtime_error(
"resultant(): arguments must be polynomials"));
 
 2886    const int h1 = ee1.
degree(s);
 
 2887    const int l1 = ee1.
ldegree(s);
 
 2888    const int h2 = ee2.
degree(s);
 
 2889    const int l2 = ee2.
ldegree(s);
 
 2891    const int msize = h1 + h2;
 
 2894    for (
int l = h1; l >= l1; --l) {
 
 2896        for (
int k = 0; 
k < h2; ++
k)
 
 2899    for (
int l = h2; l >= l2; --l) {
 
 2901        for (
int k = 0; 
k < h1; ++
k)
 
 2902            m(
k+h2, 
k+h2-l) = e;
 
 2905    return m.determinant();
 
 
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,...
 
Wrapper template for making GiNaC classes out of STL containers.
 
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
 
const_iterator begin() const noexcept
 
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].
 
ex smod(const numeric &xi) const
 
ex subs(const exmap &m, unsigned options=0) const
 
bool info(unsigned inf) const
 
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.
 
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
 
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.
 
This class holds a extended truncated power series (positive and negative integer powers).
 
ex var
Series variable (holds a symbol)
 
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).
 
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].
 
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].
 
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.
 
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
 
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...