00001 #ifndef subdivix_subresultant_hpp
00002 #define subdivix_subresultant_hpp
00003
00004 #include <realroot/Seq.hpp>
00005 #include <realroot/ring_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;
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];
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 sub_resultant {
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 = sub_resultant<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
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
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
00190 Polynomial C= subres_gcd(dp,dq);
00191
00192
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
00202 Seq<Polynomial> D = s[i];
00203
00204
00205 Polynomial d=0;
00206 for (i=0;i<D.size();i++) d = subres_gcd(d,D[i]);
00207
00208 for (i=0;i<D.size();i++) D[i]/=d;
00209
00210
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 sr_gcd (const polynomial<C,V> & p, const polynomial<C,V> & q) {
00228 return sub_resultant<euclidean>::subres_gcd(p,q);
00229 }
00230 }
00231 #endif //subdivix_subresultant_hpp