From: Jens Vollinga Date: Wed, 27 Aug 2008 15:25:16 +0000 (+0200) Subject: Added internal code for multivariate factorization. X-Git-Tag: release_1-5-0~69 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=55af76071727bd6e2fd540ad58eac26dd961f9c9;ds=sidebyside Added internal code for multivariate factorization. --- diff --git a/ginac/factor.cpp b/ginac/factor.cpp index 9b06e6e1..12405dd6 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 { @@ -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(); @@ -994,6 +1153,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 ) { @@ -1153,6 +1321,481 @@ 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(); + vector sigma = multivar_diophant(anew, x, cnew, Inew, d, p, k); + + ex buf = c; + for ( size_t i=0; i(xnu), m).subs(xnu==alphanu) / factorial(m); + if ( !cm.is_zero() ) { + vector delta_s = multivar_diophant(anew, x, cm, Inew, d, p, k); + 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& I, unsigned int p, const cl_I& l, const UniPolyVec& u, const vector& lcU) +{ + DCOUT(hensel_multivar); + DCOUTVAR(a); + DCOUTVAR(x); + DCOUTVAR(p); + DCOUTVAR(l); + DCOUTVAR(u); + 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; + for ( size_t m=0; m(xj), k); + DCOUTVAR(dif); + 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