realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/subresultant.hpp
Go to the documentation of this file.
00001 #ifndef subdivix_subresultant_hpp
00002 #define subdivix_subresultant_hpp
00003 /********************************************************************/
00004 #include <realroot/Seq.hpp>
00005 #include <realroot/polynomial_univariate.hpp>
00006 namespace mmx {
00007 struct euclidean {
00008 
00009 
00010   template<class R> static
00011   void pseudo_div(R& q, R& a, const R& b)
00012   {
00013     typedef typename R::iterator iterator;
00014     R t;//(degree(b)+1, AsSize());
00015     typename R::value_type lb=b[degree(b)];
00016     q=R(0);
00017     int c=0, da = degree(a), db = degree(b), dab =da-db+1;
00018     while (da>=db) {
00019       R m(a[da],da-db);
00020       shift(t,b,da-db); t*=a[da];   // t=b*m;
00021       c++;
00022       a*=lb;
00023       t[da]=a[da];
00024       a-=t;
00025       q+=m;
00026       da=degree(a);
00027     }
00028     a *= pow(lb, dab-c);
00029   }
00030 
00031   template<class Polynomial> static inline 
00032   Polynomial prem(const Polynomial& a, const Polynomial& b)
00033   {
00034     Polynomial r=a,q;
00035     pseudo_div(q, r, b);
00036     return r;
00037   }
00038 
00039   template<class Polynomial> static inline 
00040   Polynomial pquo(const Polynomial& a, const Polynomial& b)
00041   {
00042     Polynomial r=a, q;
00043     pseudo_div(q, r, b);
00044     return q;
00045   }
00046 
00047 };
00048 
00049 
00050 
00051 template<class PREM>
00052 struct subresultant {
00053 
00054   template<class Pol> 
00055   static Seq<Pol> sequence(const Pol & p, const Pol & q) {
00056 
00057     typedef typename Pol::value_type coeff_type;
00058     assert(degree(p) >=0 && degree(q) >= 0);
00059     int n1 = degree(p), n2= degree(q);
00060     coeff_type lp = p[n1], lq = q[n2];
00061     
00062     Seq<Pol> tab;
00063     unsigned N = std::min(n1,n2);
00064     tab.resize(N);
00065     for(unsigned i=0;i<N;i++) tab[i]=Pol(0);
00066     int d,da,db;
00067     coeff_type la;
00068     Pol a, b, Sr;
00069     
00070     if (n1>=n2) {
00071         a=q;
00072         b=PREM::prem(p,q);
00073         d=n1-n2-1;
00074         la=pow(lq,n1-n2);
00075     } else {
00076       a=p;
00077       b=PREM::prem(q,p);
00078       d=n2-n1-1;
00079       la=pow(lp,n2-n1);
00080     }
00081     
00082     if (d!=0) {
00083       a*=(coeff_type)pow<int>(-1,d*(d+1)/2);
00084       b*=(coeff_type)pow<int>(-1,(d+2)*(d+3)/2);
00085     }
00086     da=degree(a);
00087     db=degree(b);
00088     if(db>=0) tab[db]=b;
00089     
00090     while (db>=0) {
00091       Sr =PREM::prem(a,b);
00092       Sr/=(coeff_type)(pow(la,da-db)*a[da]);
00093       Sr*=(coeff_type)pow<int>(-1,((da-db+1)*(da-db+2))/2);
00094       a  = b;
00095       a *=(coeff_type)pow(b[db],da-db-1);
00096       a /=(coeff_type)pow(la,da-db-1); 
00097       da=degree(a); 
00098       b=Sr; 
00099       la=a[da]; 
00100       db=degree(b);
00101       if (db>=0) tab[db]=b;
00102     }
00103     return tab;
00104   }
00105 
00106   template<class Polynomial> 
00107   static Seq<Seq<Polynomial> > sequence(const Polynomial & p, const Polynomial & q, int v) {
00108 
00109     Seq<Polynomial> 
00110       sp= coefficients(p,v),
00111       sq= coefficients(q,v);
00112 
00113     typedef polynomial< Polynomial, with<Univariate> > upolmpol_t;
00114     upolmpol_t 
00115       P(1,sp.size()-1),
00116       Q(1,sq.size()-1);
00117 
00118     for (unsigned i=0;i<sp.size();i++) P[i]= sp[i];
00119     for (unsigned i=0;i<sq.size();i++) Q[i]= sq[i];
00120 
00121     Seq< upolmpol_t > s = subresultant<euclidean>::sequence(P,Q);
00122     
00123     Seq< Seq<Polynomial> > res(s.size());
00124     for(unsigned i=0;i<s.size();i++)
00125       for(int j=0; j<=degree(s[i]);j++)
00126         res[i]<<s[i][j];
00127 
00128     return res;
00129   }
00130 
00131   template<class Pol> static typename Pol::value_type 
00132   resultant(const Pol & p, const Pol & q) {
00133     Seq<Pol> s= sequence(p,q);
00134     if(s.size()>0) 
00135       return s[0][0];
00136     else return 0;
00137   }
00138     
00139   template<class Pol> static Pol 
00140   resultant(const Pol & p, const Pol & q, int v) {
00141     Seq< Seq<Pol> > s = sequence(p,q,v);
00142     if(s.size()>0) return s[0][0];
00143     else return 0;
00144   }
00145 
00146   template<class Pol> static bool 
00147   is_zero_seq(const Seq<Pol> & s) {
00148     for (unsigned i=0;i<s.size() ;i++) 
00149       if(s[i]!=0) return false;
00150     return true;
00151   }
00152     
00153   template<class Polynomial> static Polynomial 
00154   subres_gcd(const Polynomial & p, const Polynomial & q, int v) {
00155     typedef typename Polynomial::Monomial Monomial;    
00156     if(p==0) return q;
00157     if(q==0) return p;
00158     if(v==-1) return gcd(content(p),content(q));
00159 
00160     if(nbvar(p)==v+1 && nbvar(q)<= v) {
00161       Seq< Polynomial > s = coefficients(p,v);
00162       Polynomial d=q;
00163       for (unsigned i=0;i<s.size();i++) 
00164         d = subres_gcd(d,s[i]);
00165       return d;
00166     }
00167 
00168     if(nbvar(p)<=v && nbvar(q)== v+1) {
00169       Seq< Polynomial > s = coefficients(q,v);
00170       Polynomial d=p;
00171       for (unsigned i=0;i<s.size();i++) 
00172         d = subres_gcd(d,s[i]);
00173       return d;
00174     }
00175 
00176 
00177     // Remove content of p
00178     Polynomial dp=0;
00179     Seq<Polynomial> sp = coefficients(p,v);
00180     for(unsigned i=0;i< sp.size();i++) dp= subres_gcd(dp,sp[i]);
00181     Polynomial P= p/dp;
00182 
00183     // Remove content of q
00184     Polynomial dq=0;
00185     Seq<Polynomial> sq = coefficients(q,v);
00186     for(unsigned i=0;i< sq.size();i++) dq= subres_gcd(dq,sq[i]);
00187     Polynomial Q= q/dq;
00188 
00189     // Take gcd of contents
00190     Polynomial C= subres_gcd(dp,dq);
00191 
00192     // Subresultant sequence
00193     Seq< Seq<Polynomial> > s 
00194       = (degree(P)>=degree(Q)?sequence(P,Q,v):sequence(Q,P,v));
00195 
00196     unsigned i;
00197     for (i=0;i<s.size() && is_zero_seq(s[i]);i++) ;
00198 
00199     if(i==s.size()) return (degree(P)>=degree(Q)?Q*C:P*C);
00200 
00201     // Take last non-zero term
00202     Seq<Polynomial> D = s[i];
00203 
00204     // Remove content of last non-zero term.
00205     Polynomial d=0;
00206     for (i=0;i<D.size();i++) d = subres_gcd(d,D[i]);
00207     //    d/=content(d);
00208     for (i=0;i<D.size();i++) D[i]/=d;
00209 
00210     // Reconstruct the multivariate polynomial
00211     Polynomial r=0;
00212     for (i=0;i<D.size();i++) 
00213       r+= D[i]*Polynomial(Monomial(1,i,v));
00214     r/=content(r);
00215     r *= C;
00216     return r;
00217   }
00218 
00219   template<class Polynomial> static Polynomial 
00220   subres_gcd(const Polynomial & p, const Polynomial & q) {
00221     int v = std::max(nbvar(p)-1,nbvar(q)-1);
00222     return subres_gcd(p,q,v);
00223   }
00224 };
00225 
00226   template<class C, class V> inline polynomial<C,V>
00227   gcd (const polynomial<C,V> & p, const polynomial<C,V> & q) {
00228     return subresultant<euclidean>::subres_gcd(p,q);
00229   }
00230 }// namespace mmx
00231 #endif //subdivix_subresultant_hpp