synaps/upol/SturmSeq.h

Go to the documentation of this file.
00001 /********************************************************************
00002  *   This file is part of the source code of the SYNAPS kernel.
00003  *   Author(s):
00004  *       Initial version:
00005  *          B. Mourrain, INRIA, GALAAD, <mourrain@sophia.inria.fr>
00006  *       Implementatation of Sturm Habicht by
00007  *         F. Carreras, U. of Santander, <fernando.carreras@unican.es>
00008  *         C. Tansescu, U. of Santander, <claudiu.tanasescu@unican.es>
00009  *         L. Gonzales-Vega, U. of Santander, <laureano.gonzalez@unican.es>
00010  *         O. Ruatta, INRIA, GALAAD, <oruatta@sophia.inria.fr>
00011  *       Extended list of SturmSeq constructors by
00012  *         Elias P. TSIGARIDAS, U. of Athenes,  <et@di.uoa.gr>
00013  *
00014  *   $Id: SturmSeq.h,v 1.1 2005/07/11 08:15:52 mourrain Exp $
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 // /** Construct the Sturm sequence of two polynomials @a@ and @b@.
00070 //  * The Sturm sequence, is actually a signed pseudo remainder sequence
00071 //  * and can be computed by various methods.
00072 //  */
00073 // template<class C, class UPoly, class SEQ>
00074 // SturmSeq<C, UPoly, SEQ>::SturmSeq(const UPoly & a, const UPoly& b, PRSmethod method)
00075 //   : mth(method), tab_(std::min(degree(a), degree(b)) + 3)
00076 // {
00077 //   switch (method) {
00078 //   case PRS_STANDARD:
00079 //     compute_Standard(a, b);
00080 //     break;
00081 //   case PRS_EUCLIDEAN:
00082 //     compute_Euclidean(a, b);
00083 //     break;
00084 //   case PRS_REDUCED:
00085 //     compute_Reduced(a, b);
00086 //     break;
00087 //   case PRS_SUBRESULTANT:
00088 //     compute_Subres(a, b);
00089 //     break;
00090 //   case PRS_STHA:
00091 //     compute_StHa(a,b);
00092 //     break;
00093 //   default:
00094 //     compute_Standard(a, b);
00095 //     break;
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   //  cout << __FUNCTION__ << endl;
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   //  cout << __FUNCTION__ << endl;
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   //  cout << __FUNCTION__ << endl;
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 //  C psi = C(1);
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 //  int sgn = 1;
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 //        h = pow(g, delta) / pow(h, delta - 1);
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         //      int i, k;
00261         Pol S0, S1, NS, Sr;
00262         int c=2;
00263         //m==0;
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 }//sturmseq
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   //SEQ         tab_;
00348   shared_object<SEQ>  data;
00349   SEQ &       rep()       {return (*data);}
00350   const SEQ & rep() const {return (*data);}
00351 
00352 
00353   //definition of the types for iterator on Seq
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   //  void compute_Standard(const UPoly & a, const UPoly& b);
00360   //  void compute_Euclidean(const UPoly & a, const UPoly& b);
00361   //  void compute_Reduced(const UPoly & a, const UPoly& b);
00362   //  void compute_Subres(const UPoly & a, const UPoly& b);
00363   //  void compute_StHa(const UPoly & a, const UPoly& b);
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   //  template<class R>  unsigned var(const R& x);
00377   //  unsigned var(const char * x);
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 

SYNAPS DOCUMENTATION
logo