00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef SYNAPS_RESULTANT_STURM_H
00017 #define SYNAPS_RESULTANT_STURM_H
00018
00019 #include <synaps/init.h>
00020 #include <synaps/arithm/sign.h>
00021 #include <synaps/arithm/pow.h>
00022 #include <synaps/arithm/Infinity.h>
00023 #include <synaps/upol/UPolDse.h>
00024 #include <synaps/upol/UPOLDAR.m>
00025 #include <synaps/upol/EUCLIDIAN.h>
00026 #include <synaps/upol/SturmNames.h>
00027 #include <synaps/arithm/gmp.h>
00028 #include <vector>
00029
00030 __BEGIN_NAMESPACE_SYNAPS
00031
00035
00036 template<class UPoly> inline
00037 bool isNull(const UPoly& b) {return b==0; }
00038
00039
00040 template<class UPoly> inline
00041 int parity(const UPoly& p)
00042 {
00043 return (p.get_degree() % 2 ? -1 : 1);
00044 }
00045
00046 template <class Pol> inline
00047 Pol Prem(const Pol & a, const Pol & b)
00048 {
00049 Pol r(a),q;
00050 EUCLIDIAN::div_pseudorem0(q,r,b);
00051 return r;
00052 }
00053
00054
00055 namespace sturmseq {};
00056
00057
00061
00062 using UPOLDAR::degree;
00063 using UPOLDAR::lcoeff;
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 template<class C, class UPoly, class SEQ> struct SturmSeq;
00101
00102 namespace sturmseq
00103 {
00108 template<class C, class UPoly, class SEQ>
00109 void init(STD mthd, SturmSeq<C,UPoly,SEQ> & tab,
00110 const UPoly & a, const UPoly& b)
00111 {
00112
00113 tab[0] = a;
00114 tab[1] = b;
00115 unsigned i = 1;
00116 while (i < tab.size()-1 && !isNull(tab[i]) )
00117 {
00118 tab[i+1] = - (tab[i-1] % tab[i]);
00119 i++;
00120 }
00121 if ( isNull(tab[i]) ) tab.resize(i);
00122 }
00123
00124
00125
00130 template< class C, class UPoly, class SEQ >
00131 void init(EUCLIDEAN mth, SturmSeq<C,UPoly,SEQ> & tab,
00132 const UPoly & a, const UPoly& b)
00133 {
00134
00135 tab[0] = a;
00136 tab[1] = b;
00137
00138 unsigned i;
00139 for (i = 1; degree(tab[i]) > 0; ++i) {
00140 tab[i+1] = EUCLIDIAN::prem(tab[i-1], tab[i])
00141 *(-1)*pow( sign(EUCLIDIAN::lcoeff(tab[i])), degree(tab[i-1]) - degree(tab[i]) + 1);
00142 }
00143 tab.resize(i+1);
00144 return;
00145 }
00146
00147
00151 template< class C, class UPoly, class SEQ >
00152 void init(REDUCED mth, SturmSeq<C,UPoly,SEQ> & tab,
00153 const UPoly & a, const UPoly& b)
00154 {
00155
00156 unsigned i = 1;
00157 tab[0] = a;
00158 tab[1] = b;
00159 C alpha = tab[1][tab[1].get_degree()];
00160 int delta = tab[0].get_degree() - tab[1].get_degree();
00161
00162 C beta = C(1);
00163 while ( (i < tab.size()-1) && (tab[i].get_degree() > 0) )
00164 {
00165 tab[i+1] = EUCLIDIAN::prem(tab[i-1], tab[i]);
00166
00167 C aa = pow( sign(lcoeff(tab[i])), tab[i-1].get_degree()-tab[i].get_degree()+1);
00168 int sgn_aa = sign(aa);
00169 int sgn = (sgn_aa == 1
00170 ? (sign(beta) == 1 ? -1 : 1 )
00171 : (sign(beta) == 1 ? 1 : -1 )
00172 );
00173 tab[i+1] /= beta*sgn;
00174
00175 delta = tab[i-1].get_degree() - tab[i].get_degree();
00176 alpha = tab[i-1+1][tab[i-1+1].get_degree()];
00177 beta = pow(alpha, delta + 1);
00178 ++i;
00179 }
00180 if (i+1 < tab.size()) tab.resize(i+1);
00181 }
00182
00183
00187 template< class C, class UPoly, class SEQ >
00188 void init(SUBRES, SturmSeq<C, UPoly, SEQ> & tab,
00189 const UPoly & a, const UPoly& b)
00190 {
00191 int du = a.get_degree();
00192 int dv = b.get_degree();
00193 C g(1);
00194 C h(1);
00195 int i = 1;
00196
00197 tab[0] = a;
00198 tab[1] = b;
00199 if (du < dv) {
00200 std::swap(du, dv);
00201 tab[++i] = -a;
00202 }
00203
00204
00205 C aa = 1;
00206 UPoly r;
00207 while (dv > 0) {
00208 int delta = du - dv;
00209 aa = pow( sign(lcoeff(tab[i])), delta+1 );
00210
00211 tab[i+1] = EUCLIDIAN::prem(tab[i-1], tab[i]);
00212 du = dv;
00213 dv = tab[i+1].get_degree();
00214
00215 C beta = g * pow(h, delta);
00216 int sgn_aa = sign(aa);
00217 int sgn = (sgn_aa == 1
00218 ? (sign(beta) == 1 ? -1 : 1 )
00219 : (sign(beta) == 1 ? 1 : -1 )
00220 );
00221
00222 if (beta != 0) tab[i+1] /= beta*sgn;
00223 else tab[i+1] = tab[i+1] * sgn;
00224
00225 g = lcoeff(tab[i]);
00226 if (delta == 1) {
00227 h = g;
00228 } else {
00229
00230 h = pow( C(g / h), delta)*h;
00231 }
00232 ++i;
00233 }
00234
00235 if (i+1 < tab.size()) tab.resize(i+1);
00236 return;
00237 }
00238
00239
00240
00244 template<class C, class Pol, class TAB_TYPE>
00245 void init(HABICHT mth,SturmSeq<C,Pol,TAB_TYPE> & tab,
00246 const Pol & a, const Pol & b)
00247 {
00248 typedef typename Pol::value_type coeff_type;
00249 assert(degree(a) >=0 && degree(b) >= 0);
00250 Pol p=a,
00251 q=b;
00252 int n1 = degree(p), n2= degree(q);
00253 coeff_type lp = p[n1], lq = q[n2];
00254
00255 tab.resize(n1+n2+3);
00256
00257 tab[0]=p;
00258 tab[1]=q;
00259 int j,n,d,m,nS1,nS0,r;
00260
00261 Pol S0, S1, NS, Sr;
00262 int c=2;
00263
00264 if (n1>n2)
00265 {
00266 n=n1-1; d=n-n2;
00267 if (d!=0)
00268 {
00269 S1=q*pow(-1,d*(d+1)/2)*pow(coeff_type(lp*lq),d);
00270 S0=Prem(p,q)*pow<int>(-1,(d+2)*(d+3)/2)*pow(lp,d);
00271 if (S0!=Pol(0))
00272 {tab[c++]=S1; tab[c++]=S0;}
00273 else
00274 {tab[c++]=S0;}
00275 }
00276 else
00277 {
00278 S1=q;S0=S0-Prem(p,q);
00279 if (S0!=Pol(0)) {tab[c++]=S0;}
00280 }
00281 j=n2-1;
00282 }
00283 else
00284 {
00285 n=n2; S1=q; S0=S0-((p*(lq*lq))%q); j=n-1;
00286 if (S0!=Pol(0)) {tab[c++]=S0;}
00287 }
00288 nS1=degree(S1);
00289 coeff_type R=S1[nS1];
00290 if (S0==Pol(0)) r=-1; else r=degree(S0);
00291
00292 while (r>=0)
00293 {
00294 if (r>0) {
00295 if (r==j)
00296 {
00297 coeff_type denom=pow<coeff_type>(-R,j-r+2);
00298 NS=Prem(S1,S0); NS/= denom;
00299 NS*=pow<coeff_type>(-1,((j-r+2)*(j-r+3))/2);
00300 if (NS!=Pol(0)) {tab[c++] =NS;}
00301 S1=S0; S0=NS; nS1=degree(S1);R=S1[nS1]; j=r-1;
00302 }
00303 else
00304 {
00305 for (m=r+1;m<j;m++)
00306 {
00307 tab[c++]= Pol(0);
00308 }
00309 Sr=Prem(S1,S0); Sr/=pow(R,j-r+2);
00310 nS0=degree(S0);
00311 S1=S0*(pow(S0[nS0],j-r)); S1/=pow(R,j-r);
00312 S1*=coeff_type(pow<int>(-1,((j-r)*(j-r+1)/2)));
00313 S0=Sr*(pow<int>(-1,((j-r+2)*(j-r+3)/2)));
00314 if (S0!=Pol(0)) {
00315 tab[c++]=(S1);
00316 tab[c++]=(S0);}
00317 else {
00318 tab[c++]=(S1);}
00319 nS1=degree(S1);
00320 R=S1[nS1]; j= r-1;
00321 }
00322 }
00323 else
00324 {
00325 if (j>0)
00326 {
00327 nS0=degree(S0); S1=S0*pow(S0[nS0],j); S1 /=pow(R,j);
00328 S1*=coeff_type(pow<int>(-1,(j*(j+1)/2))); tab[c++]=(S1);
00329 }
00330 S0=Pol(0);
00331 }
00332 if (S0!=Pol(0)) r=degree(S0); else r=-1;
00333 }
00334 tab.resize(c);
00335 }
00336
00337 }
00338
00341 template< class C,
00342 class UPoly = UPolDse<C>,
00343 class SEQ = std::vector<UPoly> >
00344 struct SturmSeq
00345 {
00346 typedef UPoly value_type;
00347
00348 shared_object<SEQ> data;
00349 SEQ & rep() {return (*data);}
00350 const SEQ & rep() const {return (*data);}
00351
00352
00353
00354 typedef typename SEQ::iterator iterator;
00355 typedef typename SEQ::const_iterator const_iterator;
00356 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00357 typedef std::reverse_iterator<iterator> reverse_iterator;
00358
00359
00360
00361
00362
00363
00364
00365 SturmSeq(): data() {}
00366 SturmSeq(const SEQ & r):data(r){}
00367 SturmSeq(const shared_object<SEQ> & r):data(r){}
00368
00369 template<class MTH>
00370 SturmSeq(const UPoly & a, const UPoly& b, MTH method =MTH())
00371 {
00372 rep().resize(std::min(degree(a), degree(b)) + 3);
00373 sturmseq::init(method,*this,a,b);
00374 }
00375
00376
00377
00378
00379 const UPoly& operator[](const int& i) const { return rep()[i]; }
00380 UPoly& operator[](const int& i) { return rep()[i]; }
00381
00382 int size() const { return rep().size(); }
00383 void resize (unsigned i) {rep().resize(i);}
00384 void push_back(const UPoly & a) { return rep().push_back(a); }
00385
00386 };
00387
00390 template<class C, class UPoly, class SEQ, class R>
00391 unsigned variation(const SturmSeq<C, UPoly, SEQ> & tab, const R& x)
00392 {
00393 int i = 0, c = 0;
00394 int s0 = 0, s = 0;
00395 while ( i<tab.size() && (s0 = UPOLDAR::sign_at(tab[i],x)) == 0 )
00396 i++;
00397 while ( i < tab.size() ) {
00398 while( i<tab.size() && (s=UPOLDAR::sign_at(tab[i],x))==0)
00399 ++i;
00400 if(s !=0 && s!=s0) {
00401 c++;
00402 s0 = s;
00403 }
00404 ++i;
00405 }
00406 return c;
00407 }
00408
00409
00410
00413 template<class C,class UPoly, class SEQ>
00414 unsigned variation(const SturmSeq<C, UPoly, SEQ> & tab,
00415 const Infinity& x)
00416 {
00417 unsigned i = 0, c = 0;
00418 int s0 = 0, s = 0;
00419
00420 if (x.sign < 0) {
00421 while( (i < tab.size()) && ( (s0 = parity(tab[i])*sign(lcoeff(tab[i]))) == 0) )
00422 i++;
00423 while (i < tab.size()) {
00424 while ( (i < tab.size()) && ((s = parity(tab[i])*sign(lcoeff(tab[i]))) == 0) )
00425 ++i;
00426 if ((s != 0) && (s != s0)) {
00427 c++;
00428 s0 = s;
00429 }
00430 ++i;
00431 }
00432 } else {
00433 while( ( i < tab.size()) && ((s0 = sign(lcoeff(tab[i]))) == 0) )
00434 i++;
00435 while (i < tab.size()) {
00436 while ( (i < tab.size()) && ((s = sign(lcoeff(tab[i]))) == 0) )
00437 ++i;
00438 if ((s != 0) && (s != s0)) {
00439 c++;
00440 s0 = s;
00441 }
00442 ++i;
00443 }
00444 }
00445 return c;
00446 }
00447
00449
00450 template<class RET_TYPE, class C, class Pol, class TAB_TYPE >
00451 RET_TYPE CoeffStHa(const SturmSeq<C,Pol,TAB_TYPE> & StHa)
00452 {
00453 typename SturmSeq<C,Pol,TAB_TYPE>::const_iterator it = StHa.rep().begin();
00454 RET_TYPE RESULT;
00455 it++;
00456
00457 for (; it != StHa.rep().end(); ++it) {
00458 RESULT.push_back(UPOLDAR::lcoeff(*it));
00459 }
00460 return RESULT;
00461 }
00462
00463
00464 template<class C, class UPoly, class SEQ>
00465 std::ostream& operator<<(std::ostream &os, const SturmSeq<C,UPoly,SEQ> & tab)
00466 {
00467 VECTOR::print(os,tab.rep());
00468 return os;
00469 }
00470
00471
00472 __END_NAMESPACE_SYNAPS
00473
00474 #endif // SYNAPS_RESULTANT_STURM_H
00475