X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Ffactor.cpp;h=84b96eb8b07ec31612323c9e91425f5bc0d451fb;hp=12405dd696e870fa4f0e001e860ac764f1866095;hb=4ee761760b3db8649b8b616256cd7466fe2cd033;hpb=55af76071727bd6e2fd540ad58eac26dd961f9c9 diff --git a/ginac/factor.cpp b/ginac/factor.cpp index 12405dd6..84b96eb8 100644 --- a/ginac/factor.cpp +++ b/ginac/factor.cpp @@ -124,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; @@ -1048,8 +1048,8 @@ static ex hensel_univar(const ex& a_, const ex& x, unsigned int p, const UniPoly 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 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); @@ -1057,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(); @@ -1077,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); @@ -1553,12 +1554,13 @@ vector multivar_diophant(const vector& a_, const ex& x, const ex& c, con vector anew = a; for ( size_t i=0; i Inew = I; Inew.pop_back(); - vector sigma = multivar_diophant(anew, x, cnew, Inew, d, p, k); + sigma = multivar_diophant(anew, x, cnew, Inew, d, p, k); + DCOUTVAR(sigma); ex buf = c; for ( size_t i=0; i multivar_diophant(const vector& a_, const ex& x, const ex& c, con ex e = buf; e = make_modular(e, R); + e = e.expand(); + DCOUTVAR(e); + DCOUTVAR(d); ex monomial = 1; for ( size_t m=1; m<=d; ++m ) { - while ( !e.is_zero() ) { + DCOUTVAR(m); + while ( !e.is_zero() && e.has(xnu) ) { monomial *= (xnu - alphanu); monomial = expand(monomial); + DCOUTVAR(xnu); + DCOUTVAR(alphanu); ex cm = e.diff(ex_to(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 multivar_diophant(const vector& a_, const ex& x, const ex& c, con return sigma; } +#ifdef DEBUGFACTOR +ostream& operator<<(ostream& o, const vector& 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)); @@ -1712,6 +1736,7 @@ ex hensel_multivar(const ex& a, const ex& x, const vector& I, unsigne DCOUTVAR(j); vector U1 = U; ex monomial = 1; + DCOUTVAR(U); for ( size_t m=0; m& I, unsigne U[m] = U[m] - U[m].lcoeff(x) * pow(x,deg) + coef * pow(x,deg); } } + DCOUTVAR(U); ex Uprod = 1; for ( size_t i=0; i& I, unsigne ex e = expand(A[j-1] - Uprod); DCOUTVAR(e); + vector 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); @@ -1748,8 +1780,6 @@ ex hensel_multivar(const ex& a, const ex& x, const vector& I, unsigne ex c = dif.subs(xj==alphaj) / factorial(k); DCOUTVAR(c); if ( !c.is_zero() ) { - vector newI = I; - newI.pop_back(); vector deltaU = multivar_diophant(U1, x, c, newI, maxdeg, p, cl_I_to_uint(l)); for ( size_t i=0; i& I, unsigne deltaU[i] *= monomial; U[i] += deltaU[i]; U[i] = make_modular(U[i], R); + U[i] = U[i].expand(); + DCOUTVAR(U[i]); } ex Uprod = 1; for ( size_t i=0; i& I, unsigne 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); @@ -1818,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