realroot_doc 0.1.1
|
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