X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Ffactor.cpp;h=84b96eb8b07ec31612323c9e91425f5bc0d451fb;hp=18e7c04c78bc3ce86dab49e377f7a25de44d0aa3;hb=4ee761760b3db8649b8b616256cd7466fe2cd033;hpb=f3eefbda588318e09dcb3180c6f039dc3fc30f87 diff --git a/ginac/factor.cpp b/ginac/factor.cpp index 18e7c04c..84b96eb8 100644 --- a/ginac/factor.cpp +++ b/ginac/factor.cpp @@ -22,6 +22,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +//#define DEBUGFACTOR + +#ifdef DEBUGFACTOR +#include +#include +using namespace GiNaC; +#else #include "factor.h" #include "ex.h" @@ -34,6 +41,7 @@ #include "mul.h" #include "normal.h" #include "add.h" +#endif #include #include @@ -43,13 +51,21 @@ using namespace std; #include using namespace cln; -//#define DEBUGFACTOR - #ifdef DEBUGFACTOR -#include -#endif // def DEBUGFACTOR - +namespace Factor { +#else namespace GiNaC { +#endif + +#ifdef DEBUGFACTOR +#define DCOUT(str) cout << #str << endl +#define DCOUTVAR(var) cout << #var << ": " << var << endl +#define DCOUT2(str,var) cout << #str << ": " << var << endl +#else +#define DCOUT(str) +#define DCOUTVAR(var) +#define DCOUT2(str,var) +#endif namespace { @@ -108,8 +124,8 @@ struct UniPoly // assert: poly is in Z[x] Term t; for ( int i=poly.degree(x); i>=poly.ldegree(x); --i ) { - int coeff = ex_to(poly.coeff(x,i)).to_int(); - if ( coeff ) { + cl_I coeff = the(ex_to(poly.coeff(x,i)).to_cl_N()); + if ( !zerop(coeff) ) { t.c = R->canonhom(coeff); if ( !zerop(t.c) ) { t.exp = i; @@ -118,6 +134,22 @@ struct UniPoly } } } + UniPoly(const cl_modint_ring& ring, const UniPoly& poly) : R(ring) + { + if ( R->modulus == poly.R->modulus ) { + terms = poly.terms; + } + else { + list::const_iterator i=poly.terms.begin(), end=poly.terms.end(); + for ( ; i!=end; ++i ) { + terms.push_back(*i); + terms.back().c = R->canonhom(poly.R->retract(i->c)); + if ( zerop(terms.back().c) ) { + terms.pop_back(); + } + } + } + } UniPoly(const cl_modint_ring& ring, const Vec& v) : R(ring) { Term t; @@ -231,6 +263,13 @@ struct UniPoly } } } + void divide(const cl_I& x) + { + list::iterator i = terms.begin(), end = terms.end(); + for ( ; i != end; ++i ) { + i->c = cl_MI(R, the(R->retract(i->c) / x)); + } + } void reduce_exponents(unsigned int prime) { list::iterator i = terms.begin(), end = terms.end(); @@ -356,18 +395,68 @@ static UniPoly operator-(const UniPoly& a, const UniPoly& b) return c; } -static UniPoly operator-(const UniPoly& a) +static UniPoly operator*(const UniPoly& a, const cl_MI& fac) +{ + unsigned int n = a.degree(); + UniPoly c(a.R); + Term t; + for ( unsigned int i=0 ; i<=n; ++i ) { + t.c = a[i] * fac; + if ( !zerop(t.c) ) { + t.exp = i; + c.terms.push_front(t); + } + } + return c; +} + +static UniPoly operator+(const UniPoly& a, const UniPoly& b) { list::const_iterator ia = a.terms.begin(), aend = a.terms.end(); + list::const_iterator ib = b.terms.begin(), bend = b.terms.end(); UniPoly c(a.R); + while ( ia != aend && ib != bend ) { + if ( ia->exp > ib->exp ) { + c.terms.push_back(*ia); + ++ia; + } + else if ( ia->exp < ib->exp ) { + c.terms.push_back(*ib); + ++ib; + } + else { + Term t; + t.exp = ia->exp; + t.c = ia->c + ib->c; + if ( !zerop(t.c) ) { + c.terms.push_back(t); + } + ++ia; ++ib; + } + } while ( ia != aend ) { c.terms.push_back(*ia); - c.terms.back().c = -c.terms.back().c; ++ia; } + while ( ib != bend ) { + c.terms.push_back(*ib); + ++ib; + } return c; } +// static UniPoly operator-(const UniPoly& a) +// { +// list::const_iterator ia = a.terms.begin(), aend = a.terms.end(); +// UniPoly c(a.R); +// while ( ia != aend ) { +// c.terms.push_back(*ia); +// c.terms.back().c = -c.terms.back().c; +// ++ia; +// } +// return c; +// } + #ifdef DEBUGFACTOR ostream& operator<<(ostream& o, const UniPoly& t) { @@ -401,6 +490,17 @@ ostream& operator<<(ostream& o, const list& t) typedef vector UniPolyVec; +#ifdef DEBUGFACTOR +ostream& operator<<(ostream& o, const UniPolyVec& v) +{ + UniPolyVec::const_iterator i = v.begin(), end = v.end(); + while ( i != end ) { + o << *i++ << " , " << endl; + } + return o; +} +#endif // def DEBUGFACTOR + struct UniFactor { UniPoly p; @@ -654,6 +754,46 @@ public: i2 += c; } } + void mul_row(size_t row, const cl_MI x) + { + vector::iterator i = m.begin() + row*c; + for ( size_t cc=0; cc::iterator i1 = m.begin() + row1*c; + vector::iterator i2 = m.begin() + row2*c; + for ( size_t cc=0; cc::iterator i1 = m.begin() + row1*c; + vector::iterator i2 = m.begin() + row2*c; + for ( size_t cc=0; cc::const_iterator i = m.m.begin(), end = m.m.end(); @@ -700,19 +859,32 @@ static void q_matrix(const UniPoly& a, Matrix& Q) { unsigned int n = a.degree(); unsigned int q = cl_I_to_uint(a.R->modulus); - vector r(n, a.R->zero()); - r[0] = a.R->one(); - Q.set_row(0, r); - unsigned int max = (n-1) * q; - for ( size_t m=1; m<=max; ++m ) { - cl_MI rn_1 = r.back(); - for ( size_t i=n-1; i>0; --i ) { - r[i] = r[i-1] - rn_1 * a[i]; - } - r[0] = -rn_1 * a[0]; - if ( (m % q) == 0 ) { - Q.set_row(m/q, r); +// fast and buggy +// vector r(n, a.R->zero()); +// r[0] = a.R->one(); +// Q.set_row(0, r); +// unsigned int max = (n-1) * q; +// for ( size_t m=1; m<=max; ++m ) { +// cl_MI rn_1 = r.back(); +// for ( size_t i=n-1; i>0; --i ) { +// r[i] = r[i-1] - rn_1 * a[i]; +// } +// r[0] = -rn_1 * a[0]; +// if ( (m % q) == 0 ) { +// Q.set_row(m/q, r); +// } +// } +// slow and (hopefully) correct + for ( size_t i=0; ione()); + UniPoly r(a.R); + rem(qk, a, r); + Vec rvec; + for ( size_t j=0; j::const_iterator i = factors.begin(), end = factors.end(); + while ( i != end ) { + if ( i->degree() ) ++size; + ++i; + } if ( size == k ) { list::const_iterator i = factors.begin(), end = factors.end(); while ( i != end ) { @@ -803,9 +980,9 @@ static void berlekamp(const UniPoly& a, UniPolyVec& upv) } return; } - if ( u->degree() < nur.degree() ) { - break; - } +// if ( u->degree() < nur.degree() ) { +// break; +// } } } if ( ++r == k ) { @@ -870,9 +1047,9 @@ static ex hensel_univar(const ex& a_, const ex& x, unsigned int p, const UniPoly for ( int i=a.degree(x); i>=a.ldegree(x); --i ) { maxcoeff += pow(abs(a.coeff(x, i)),2); } - cl_I normmc = ceiling1(the(cln::sqrt(ex_to(maxcoeff).to_cl_N()))); - unsigned int maxdegree = (u1_.degree() > w1_.degree()) ? u1_.degree() : w1_.degree(); - unsigned int B = cl_I_to_uint(normmc * expt_pos(cl_I(2), maxdegree)); + cl_I normmc = ceiling1(the(cln::sqrt(ex_to(maxcoeff).to_cl_N()))); + cl_I maxdegree = (u1_.degree() > w1_.degree()) ? u1_.degree() : w1_.degree(); + cl_I B = normmc * expt_pos(cl_I(2), maxdegree); // step 1 ex alpha = a.lcoeff(x); @@ -880,7 +1057,7 @@ static ex hensel_univar(const ex& a_, const ex& x, unsigned int p, const UniPoly if ( gamma == 0 ) { gamma = alpha; } - unsigned int gamma_ui = ex_to(abs(gamma)).to_int(); + numeric gamma_ui = ex_to(abs(gamma)); a = a * gamma; UniPoly nu1 = u1_; nu1.unit_normal(); @@ -900,10 +1077,11 @@ static ex hensel_univar(const ex& a_, const ex& x, unsigned int p, const UniPoly ex u = replace_lc(u1.to_ex(x), x, gamma); ex w = replace_lc(w1.to_ex(x), x, alpha); ex e = expand(a - u * w); - unsigned int modulus = p; + numeric modulus = p; + const numeric maxmodulus = 2*numeric(B)*gamma_ui; // step 4 - while ( !e.is_zero() && modulus < 2*B*gamma_ui ) { + while ( !e.is_zero() && modulus < maxmodulus ) { ex c = e / modulus; phi = expand(s.to_ex(x)*c); UniPoly sigmatilde(R, phi, x); @@ -976,6 +1154,15 @@ public: size_t size() const { return n; } size_t size_first() const { return n-sum; } size_t size_second() const { return sum; } +#ifdef DEBUGFACTOR + void get() const + { + for ( size_t i=0; i=1; --i ) { @@ -1107,6 +1294,7 @@ static ex factor_univariate(const ex& poly, const ex& x) mf.factors = newfactors2; mf.poly = answer.op(1); tocheck.push(mf); + break; } } else { @@ -1134,6 +1322,1001 @@ struct FindSymbolsMap : public map_function { } }; +struct EvalPoint +{ + ex x; + int evalpoint; +}; + +// forward declaration +vector multivar_diophant(const vector& a_, const ex& x, const ex& c, const vector& I, unsigned int d, unsigned int p, unsigned int k); + +UniPolyVec multiterm_eea_lift(const UniPolyVec& a, const ex& x, unsigned int p, unsigned int k) +{ + DCOUT(multiterm_eea_lift); + DCOUTVAR(a); + DCOUTVAR(p); + DCOUTVAR(k); + + const size_t r = a.size(); + DCOUTVAR(r); + cl_modint_ring R = find_modint_ring(expt_pos(cl_I(p),k)); + UniPoly fill(R); + UniPolyVec q(r-1, fill); + q[r-2] = a[r-1]; + for ( size_t j=r-2; j>=1; --j ) { + q[j-1] = a[j] * q[j]; + } + DCOUTVAR(q); + UniPoly beta(R); + beta.set(0, R->one()); + UniPolyVec s; + for ( size_t j=1; j mdarg(2); + mdarg[0] = q[j-1].to_ex(x); + mdarg[1] = a[j-1].to_ex(x); + vector empty; + vector exsigma = multivar_diophant(mdarg, x, beta.to_ex(x), empty, 0, p, k); + UniPoly sigma1(R, exsigma[0], x); + UniPoly sigma2(R, exsigma[1], x); + beta = sigma1; + s.push_back(sigma2); + } + s.push_back(beta); + + DCOUTVAR(s); + DCOUT(END multiterm_eea_lift); + return s; +} + +void eea_lift(const UniPoly& a, const UniPoly& b, const ex& x, unsigned int p, unsigned int k, UniPoly& s_, UniPoly& t_) +{ + DCOUT(eea_lift); + DCOUTVAR(a); + DCOUTVAR(b); + DCOUTVAR(x); + DCOUTVAR(p); + DCOUTVAR(k); + + cl_modint_ring R = find_modint_ring(p); + UniPoly amod(R, a); + UniPoly bmod(R, b); + DCOUTVAR(amod); + DCOUTVAR(bmod); + + UniPoly smod(R), tmod(R), g(R); + exteuclid(amod, bmod, g, smod, tmod); + + DCOUTVAR(smod); + DCOUTVAR(tmod); + DCOUTVAR(g); + + cl_modint_ring Rpk = find_modint_ring(expt_pos(cl_I(p),k)); + UniPoly s(Rpk, smod); + UniPoly t(Rpk, tmod); + DCOUTVAR(s); + DCOUTVAR(t); + + cl_I modulus(p); + + UniPoly one(Rpk); + one.set(0, Rpk->one()); + for ( size_t j=1; j 2 ) { + UniPolyVec s = multiterm_eea_lift(a, x, p, k); + for ( size_t j=0; j(e) || is_a(e) ) { + return e.map(*this); + } + else if ( is_a(e) ) { + numeric mod(R->modulus); + numeric halfmod = (mod-1)/2; + cl_MI emod = R->canonhom(the(ex_to(e).to_cl_N())); + numeric n(R->retract(emod)); + if ( n > halfmod ) { + return n-mod; + } + else { + return n; + } + } + return e; + } +}; + +static ex make_modular(const ex& e, const cl_modint_ring& R) +{ + make_modular_map map(R); + return map(e); +} + +vector multivar_diophant(const vector& a_, const ex& x, const ex& c, const vector& I, unsigned int d, unsigned int p, unsigned int k) +{ + vector a = a_; + + DCOUT(multivar_diophant); +#ifdef DEBUGFACTOR + cout << "a "; + for ( size_t i=0; i sigma; + if ( nu > 1 ) { + ex xnu = I.back().x; + int alphanu = I.back().evalpoint; + + ex A = 1; + for ( size_t i=0; i b(r); + for ( size_t i=0; i anew = a; + for ( size_t i=0; i Inew = I; + Inew.pop_back(); + sigma = multivar_diophant(anew, x, cnew, Inew, d, p, k); + DCOUTVAR(sigma); + + ex buf = c; + for ( size_t i=0; i(xnu), m).subs(xnu==alphanu) / factorial(m); + DCOUTVAR(cm); + if ( !cm.is_zero() ) { + vector delta_s = multivar_diophant(anew, x, cm, Inew, d, p, k); + DCOUTVAR(delta_s); + ex buf = e; + for ( size_t j=0; j(c) ) { + nterms = c.nops(); + z = c.op(0); + } + else { + nterms = 1; + z = c; + } + DCOUTVAR(nterms); + for ( size_t i=0; i(ex_to(z.lcoeff(x)).to_cl_N()); + DCOUTVAR(cm); + UniPolyVec delta_s = univar_diophant(amod, x, m, p, k); + cl_MI modcm; + cl_I poscm = cm; + while ( poscm < 0 ) { + poscm = poscm + expt_pos(cl_I(p),k); + } + modcm = cl_MI(R, poscm); + DCOUTVAR(modcm); + for ( size_t j=0; j 1 ) { + z = c.op(i+1); + } + } + } +#ifdef DEBUGFACTOR + cout << "sigma "; + for ( size_t i=0; i& v) +{ + for ( size_t i=0; i& I, unsigned int p, const cl_I& l, const UniPolyVec& u, const vector& lcU) +{ + DCOUT(hensel_multivar); + DCOUTVAR(a); + DCOUTVAR(x); + DCOUTVAR(I); + DCOUTVAR(p); + DCOUTVAR(l); + DCOUTVAR(u); + DCOUTVAR(lcU); + const size_t nu = I.size() + 1; + const cl_modint_ring R = find_modint_ring(expt_pos(cl_I(p),l)); + + DCOUTVAR(nu); + + vector A(nu); + A[nu-1] = a; + + for ( size_t j=nu; j>=2; --j ) { + ex x = I[j-2].x; + int alpha = I[j-2].evalpoint; + A[j-2] = A[j-1].subs(x==alpha); + A[j-2] = make_modular(A[j-2], R); + } + +#ifdef DEBUGFACTOR + cout << "A "; + for ( size_t i=0; i maxdeg ) maxdeg = maxdeg2; + } + DCOUTVAR(maxdeg); + + const size_t n = u.size(); + DCOUTVAR(n); + vector U(n); + for ( size_t i=0; i U1 = U; + ex monomial = 1; + DCOUTVAR(U); + for ( size_t m=0; m newI; + for ( size_t i=1; i<=j-2; ++i ) { + newI.push_back(I[i-1]); + } + DCOUTVAR(newI); + + ex xj = I[j-2].x; + int alphaj = I[j-2].evalpoint; + size_t deg = A[j-1].degree(xj); + DCOUTVAR(deg); + for ( size_t k=1; k<=deg; ++k ) { + DCOUTVAR(k); + if ( !e.is_zero() ) { + DCOUTVAR(xj); + DCOUTVAR(alphaj); + monomial *= (xj - alphaj); + monomial = expand(monomial); + DCOUTVAR(monomial); + ex dif = e.diff(ex_to(xj), k); + DCOUTVAR(dif); + ex c = dif.subs(xj==alphaj) / factorial(k); + DCOUTVAR(c); + if ( !c.is_zero() ) { + vector deltaU = multivar_diophant(U1, x, c, newI, maxdeg, p, cl_I_to_uint(l)); + for ( size_t i=0; i(e) ) { + result.append(e); + DCOUT(END put_factors_into_lst); + DCOUTVAR(result); + return result; + } + if ( is_a(e) ) { + result.append(1); + result.append(e.op(0)); + result.append(e.op(1)); + DCOUT(END put_factors_into_lst); + DCOUTVAR(result); + return result; + } + if ( is_a(e) || is_a(e) ) { + result.append(1); + result.append(e); + result.append(1); + DCOUT(END put_factors_into_lst); + DCOUTVAR(result); + return result; + } + if ( is_a(e) ) { + ex nfac = 1; + for ( size_t i=0; i(op) ) { + nfac = op; + } + if ( is_a(op) ) { + result.append(op.op(0)); + result.append(op.op(1)); + } + if ( is_a(op) || is_a(op) ) { + result.append(op); + result.append(1); + } + } + result.prepend(nfac); + DCOUT(END put_factors_into_lst); + DCOUTVAR(result); + return result; + } + throw runtime_error("put_factors_into_lst: bad term."); +} + +#ifdef DEBUGFACTOR +ostream& operator<<(ostream& o, const vector& v) +{ + for ( size_t i=0; i& d) +{ + DCOUT(checkdivisors); + const int k = f.nops()-2; + DCOUTVAR(k); + DCOUTVAR(d.size()); + numeric q, r; + d[0] = ex_to(f.op(0) * f.op(f.nops()-1)); + if ( d[0] == 1 && k == 1 && abs(f.op(1)) != 1 ) { + DCOUT(false); + DCOUT(END checkdivisors); + return false; + } + DCOUTVAR(d[0]); + for ( int i=1; i<=k; ++i ) { + DCOUTVAR(i); + DCOUTVAR(abs(f.op(i))); + q = ex_to(abs(f.op(i))); + DCOUTVAR(q); + for ( int j=i-1; j>=0; --j ) { + r = d[j]; + DCOUTVAR(r); + do { + r = gcd(r, q); + DCOUTVAR(r); + q = q/r; + DCOUTVAR(q); + } while ( r != 1 ); + if ( q == 1 ) { + DCOUT(true); + DCOUT(END checkdivisors); + return true; + } + } + d[i] = q; + } + DCOUT(false); + DCOUT(END checkdivisors); + return false; +} + +static bool generate_set(const ex& u, const ex& vn, const exset& syms, const ex& f, const numeric& modulus, vector& a, vector& d) +{ + // computation of d is actually not necessary + DCOUT(generate_set); + DCOUTVAR(u); + DCOUTVAR(vn); + DCOUTVAR(f); + DCOUTVAR(modulus); + const ex& x = *syms.begin(); + bool trying = true; + do { + ex u0 = u; + ex vna = vn; + ex vnatry; + exset::const_iterator s = syms.begin(); + ++s; + for ( size_t i=0; i(x))) != 1 ) { + continue; + } + if ( is_a(vn) ) { + trying = false; + } + else { + DCOUT(do substitution); + lst fnum; + lst::const_iterator i = ex_to(f).begin(); + fnum.append(*i++); + bool problem = false; + while ( i!=ex_to(f).end() ) { + ex fs = *i; + if ( !is_a(fs) ) { + s = syms.begin(); + ++s; + for ( size_t j=0; j=p.ldegree(x); --i ) { + cont = gcd(cont, p.coeff(x,ex_to(i).to_int())); + if ( cont == 1 ) break; + } + DCOUTVAR(cont); + ex pp = expand(normal(p / cont)); + DCOUTVAR(pp); + if ( !is_a(cont) ) { +#ifdef DEBUGFACTOR + return ::factor(cont) * ::factor(pp); +#else + return factor(cont) * factor(pp); +#endif + } + + /* factor leading coefficient */ + pp = pp.collect(x); + ex vn = pp.lcoeff(x); + pp = pp.expand(); + ex vnlst; + if ( is_a(vn) ) { + vnlst = lst(vn); + } + else { +#ifdef DEBUGFACTOR + ex vnfactors = ::factor(vn); +#else + ex vnfactors = factor(vn); +#endif + vnlst = put_factors_into_lst(vnfactors); + } + DCOUTVAR(vnlst); + + const numeric maxtrials = 3; + numeric modulus = (vnlst.nops()-1 > 3) ? vnlst.nops()-1 : 3; + DCOUTVAR(modulus); + numeric minimalr = -1; + vector a(syms.size()-1, 0); + vector d((vnlst.nops()-1)/2+1, 0); + + while ( true ) { + numeric trialcount = 0; + ex u, delta; + unsigned int prime; + size_t factor_count; + ex ufac; + ex ufaclst; + while ( trialcount < maxtrials ) { + bool problem = generate_set(pp, vn, syms, vnlst, modulus, a, d); + DCOUTVAR(problem); + if ( problem ) { + ++modulus; + continue; + } + DCOUTVAR(a); + DCOUTVAR(d); + u = pp; + s = syms.begin(); + ++s; + for ( size_t i=0; i(u.lcoeff(x)), prime) != 0 ) { + UniPoly modpoly(R, u, x); + UniFactorVec sqrfree_ufv; + squarefree(modpoly, sqrfree_ufv); + DCOUTVAR(sqrfree_ufv); + if ( sqrfree_ufv.factors.size() == 1 && sqrfree_ufv.factors.front().exp == 1 ) break; + } + prime = next_prime(prime); + DCOUTVAR(prime); + R = find_modint_ring(prime); + } + +#ifdef DEBUGFACTOR + ufac = ::factor(u); +#else + ufac = factor(u); +#endif + DCOUTVAR(ufac); + ufaclst = put_factors_into_lst(ufac); + DCOUTVAR(ufaclst); + factor_count = (ufaclst.nops()-1)/2; + DCOUTVAR(factor_count); + + if ( factor_count <= 1 ) { + DCOUTVAR(poly); + DCOUT(END factor_multivariate); + return poly; + } + + if ( minimalr < 0 ) { + minimalr = factor_count; + } + else if ( minimalr == factor_count ) { + ++trialcount; + ++modulus; + } + else if ( minimalr > factor_count ) { + minimalr = factor_count; + trialcount = 0; + } + DCOUTVAR(trialcount); + DCOUTVAR(minimalr); + if ( minimalr <= 1 ) { + DCOUTVAR(poly); + DCOUT(END factor_multivariate); + return poly; + } + } + + vector ftilde((vnlst.nops()-1)/2+1); + ftilde[0] = ex_to(vnlst.op(0)); + for ( size_t i=1; i(ft); + } + DCOUTVAR(ftilde); + + vector used_flag((vnlst.nops()-1)/2+1, false); + vector D(factor_count, 1); + for ( size_t i=0; i<=factor_count; ++i ) { + DCOUTVAR(i); + numeric prefac; + if ( i == 0 ) { + prefac = ex_to(ufaclst.op(0)); + ftilde[0] = ftilde[0] / prefac; + vnlst.let_op(0) = vnlst.op(0) / prefac; + continue; + } + else { + prefac = ex_to(ufaclst.op(2*(i-1)+1).lcoeff(x)); + } + DCOUTVAR(prefac); + for ( size_t j=(vnlst.nops()-1)/2+1; j>0; --j ) { + DCOUTVAR(j); + DCOUTVAR(prefac); + DCOUTVAR(ftilde[j-1]); + if ( abs(ftilde[j-1]) == 1 ) { + used_flag[j-1] = true; + continue; + } + numeric g = gcd(prefac, ftilde[j-1]); + DCOUTVAR(g); + if ( g != 1 ) { + DCOUT(has_common_prime); + prefac = prefac / g; + numeric count = abs(iquo(g, ftilde[j-1])); + DCOUTVAR(count); + used_flag[j-1] = true; + if ( i > 0 ) { + if ( j == 1 ) { + D[i-1] = D[i-1] * pow(vnlst.op(0), count); + } + else { + D[i-1] = D[i-1] * pow(vnlst.op(2*(j-2)+1), count); + } + } + else { + ftilde[j-1] = ftilde[j-1] / prefac; + DCOUT(BREAK); + DCOUTVAR(ftilde[j-1]); + break; + } + ++j; + } + } + } + DCOUTVAR(D); + + bool some_factor_unused = false; + for ( size_t i=0; i C(factor_count); + DCOUTVAR(C); + DCOUTVAR(delta); + if ( delta == 1 ) { + for ( size_t i=0; i epv; + s = syms.begin(); + ++s; + for ( size_t i=0; i=u.ldegree(x); --i ) { + maxcoeff += pow(abs(u.coeff(x, i)),2); + } + cl_I normmc = ceiling1(the(cln::sqrt(ex_to(maxcoeff).to_cl_N()))); + unsigned int maxdegree = 0; + for ( size_t i=0; i (int)maxdegree ) { + maxdegree = ufaclst[2*i+1].degree(x); + } + } + cl_I B = normmc * expt_pos(cl_I(2), maxdegree); + cl_I l = 1; + cl_I pl = prime; + while ( pl < B ) { + l = l + 1; + pl = pl * prime; + } + + UniPolyVec uvec; + cl_modint_ring R = find_modint_ring(expt_pos(cl_I(prime),l)); + for ( size_t i=0; i<(ufaclst.nops()-1)/2; ++i ) { + UniPoly newu(R, ufaclst.op(i*2+1), x); + uvec.push_back(newu); + } + DCOUTVAR(uvec); + + ex res = hensel_multivar(ufaclst.op(0)*pp, x, epv, prime, l, uvec, C); + if ( res != lst() ) { + ex result = cont * ufaclst.op(0); + for ( size_t i=0; i 0 ) { int ld = poly.ldegree(x); @@ -1156,8 +2340,9 @@ static ex factor_sqrfree(const ex& poly) } } - // multivariate case not yet implemented! - throw runtime_error("multivariate case not yet implemented!"); + // multivariate case + ex res = factor_multivariate(poly, findsymbols.syms); + return res; } } // anonymous namespace @@ -1214,6 +2399,9 @@ ex factor(const ex& poly) } return res; } + if ( is_a(sfpoly) ) { + return poly; + } // case: (polynomial) ex f = factor_sqrfree(sfpoly); return f;