realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/univariate.hpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *      This file is part of the source code of realroot kernel.
00003 *      Author(s): B. Mourrain, GALAAD, INRIA
00004 *
00005 *      Modification: et@di.uoa.gr
00006 *                    Add lcoeff, tcoeff functions
00007 *                    Add diff function that returns the derivative
00008 **********************************************************************/
00009 #ifndef realroot_univariate_hpp
00010 #define realroot_univariate_hpp
00011 //--------------------------------------------------------------------
00012 #include <iostream>
00013 #include <math.h>
00014 #include <realroot/assign.hpp>
00015 #include <realroot/array.hpp>
00016 # define TMPL  template<class C>
00017 # define TMPLX template<class C, class X>
00018 # define Polynomial monomials<C>
00019 
00020 //====================================================================
00021 namespace mmx {
00022 //--------------------------------------------------------------------
00023 #ifndef MMX_WITH_PLUS_SIGN
00024 #define MMX_WITH_PLUS_SIGN
00025   template<class X> bool with_plus_sign(const X& x) {return x>0;}
00026 #endif  //MMX_WITH_PLUS_SIGN
00027 //--------------------------------------------------------------------
00028   struct AsSize;
00029 
00030   //====================================================================
00032 
00047 namespace univariate {
00048 
00053   template <class C>
00054   struct monomials {
00055 
00056     typedef C            value_type;
00057     typedef unsigned int size_type;
00058     typedef C*           iterator;
00059     typedef iterator     const_iterator;
00060     typedef std::reverse_iterator<const_iterator>  const_reverse_iterator;
00061     typedef std::reverse_iterator<iterator>        reverse_iterator;
00062     typedef C coeff_t;
00063 
00064     C * tab_;
00065     size_type size_;
00066     int degree_;
00067 
00068     monomials(): tab_(0), size_(0), degree_(-1) {}
00069     monomials(const C& c);
00070     monomials(const C& c, size_type d, int v=0);
00071     monomials(const size_type& s, C *t);
00072     monomials(const size_type& s, const char* t);
00073     monomials(C* b, C *e);
00074     //    {degree_=this->size_-1;checkdegree(*this);}
00075     monomials(const monomials<C> & p);
00076     //    {}//{cout <<"copy rep"<<endl;}
00077     ~monomials () { delete[] tab_;}
00078 
00079     iterator        begin()       {return iterator(tab_); }
00080     const_iterator  begin() const {return const_iterator(tab_); }
00081     iterator        end()         {return iterator(this->tab_+degree_+1); }
00082     const_iterator  end()   const {return const_iterator(this->tab_+degree_+1); }
00083     
00084     reverse_iterator       rend()         {return reverse_iterator(tab_); }
00085     const_reverse_iterator rend()   const {return reverse_iterator(tab_); }
00086     
00087     reverse_iterator       rbegin() {
00088       return reverse_iterator(this->tab_+degree_+1); 
00089     }
00090     const_reverse_iterator rbegin() const {
00091       return const_reverse_iterator(this->tab_+degree_+1); 
00092     }
00093 
00094     unsigned size()   const { return size_;}
00095     unsigned degree() const { return degree_;}
00096 
00097     monomials& operator= (const monomials<C> & v);
00098 
00099     inline       C & operator[] (size_type i)       {return tab_[i];}
00100     inline const C & operator[] (size_type i) const {return tab_[i];}
00101     // No test {if(i<size_) return tab_[i]; else return C(0);}
00102 
00103     bool operator==( const C& c ) const;
00104 
00105     void resize(const size_type& n);
00106 
00107   };
00108 
00109   TMPL
00110   Polynomial::monomials(const Polynomial & v) : size_(v.size_), degree_(v.degree_) {
00111     tab_ = new C[v.size_]; 
00112     for(size_type i=0;i<v.size_;i++) {tab_[i] = v[i];}
00113   }
00114 
00115   TMPL
00116   Polynomial::monomials(const C& c): size_(1), degree_(0) {
00117     tab_ = new C[1];
00118     tab_[0]=c;
00119   }
00120   TMPL
00121   Polynomial::monomials(const C& c, size_type l, int v): size_(l+1), degree_(l) {
00122     tab_ = new C[l+1];
00123     for (size_type i = 0; i < l; i++) tab_[i]=C(0);
00124     tab_[l]=c;
00125   }
00126   
00127   TMPL
00128   Polynomial::monomials(const size_type& i, C* t): size_(i), degree_(i-1) {
00129     tab_ = new C[i];
00130     for(size_type l=0;l<i;l++) tab_[l] = t[l];
00131     check_degree(*this);
00132   }
00133 
00134   TMPL 
00135   Polynomial::monomials(C* b, C* e) {
00136     size_=0; C* p;
00137     for(p=b;p!=e;p++,size_++) ;
00138     tab_ = new C[size_];
00139     degree_=0;
00140     for(p=b; p!=e; p++,degree_++) {tab_[degree_]=(*p);}
00141     check_degree(*this);
00142   }
00143 
00144 
00145   TMPL
00146   Polynomial::monomials(const size_type& l, const char * nm) {
00147     std::istringstream ins(nm);
00148     size_=l;
00149     tab_ = new C[size_];
00150     for(size_type i=0; i< size_; i++) ins >>tab_[i];
00151     degree_=l-1;
00152     check_degree(*this);
00153   }
00154   //----------------------------------------------------------------------
00155   TMPL void 
00156   Polynomial::resize(const size_type & i) {
00157     if(size_!=i){
00158       if (size_ != 0) {
00159         C* tmp = tab_;
00160         tab_ = new C[i];
00161         for(size_type j=0;j<std::min(i,size_);j++) tab_[j]=tmp[j];
00162         for(size_type j=std::min(i,size_);j<i;j++) tab_[j]=value_type();
00163         size_=i;
00164         delete [] tmp;      
00165       } else {
00166         size_=i; tab_= new C[i];
00167         for(size_type j=0;j<size_;j++) tab_[j]=value_type();
00168       }
00169     }
00170     degree_=i-1;
00171   }
00172 
00173   TMPL Polynomial& 
00174   Polynomial::operator=(const Polynomial & v) {
00175     if (size_ != v.size_) {
00176       if (size_ !=0) delete [] tab_;
00177       tab_ = new C[v.size_];
00178       size_ = v.size_;
00179     }
00180     degree_=v.degree_;
00181     for(size_type i=0;i<size_;i++) tab_[i] = v[i];
00182     return *this;
00183   }
00184 
00185   TMPL bool 
00186   Polynomial::operator== (const C& c) const {
00187     if(c==0)
00188       return (this->degree()<0);
00189     else
00190       return (this->degree()==0 && tab_[0]== c);
00191   }
00192   //--------------------------------------------------------------------
00193   template <class R>
00194   int degree(const R & p) {
00195     // std::cout <<"(Using default degree) "<<p<<std::endl;
00196     int i = p.size()-1;
00197     while(i>-1 && p[i]==(typename R::value_type)0) i--;
00198     return i;
00199   }
00200 
00201   TMPL inline int degree(const Polynomial& a) { return a.degree_;}
00202 
00203 
00204   //-------------------------------------------------------------------
00205 
00206   TMPL inline int 
00207   check_degree(Polynomial& a) {
00208     int l = a.degree_;
00209     while(l >=0 && (a.tab_[l]==0)) {l--;}
00210     a.degree_=l;
00211     return a.degree_;
00212   }
00213     
00214   //----------------------------------------------------------------------
00215   TMPL void inline
00216   add(Polynomial &r, const Polynomial& a, const Polynomial & b) {
00217     array::add(r,a,b);
00218     check_degree(r);
00219   }
00220 
00221   //----------------------------------------------------------------------
00222   TMPL void inline
00223   add(Polynomial &r, const Polynomial& a, const C& c) {
00224     if(degree(a)>-1) {
00225       r=a; r[0]+=c;
00226     }
00227     else
00228       r= Polynomial(c,0);
00229     check_degree(r);
00230   }
00231 
00232   //----------------------------------------------------------------------
00233   TMPL void inline
00234   add(Polynomial &r, const C& c) {
00235     if(degree(r)>-1) {
00236      r[0]+=c;
00237     }
00238     else
00239       r= Polynomial(c,0);
00240     check_degree(r);
00241   }
00242   //----------------------------------------------------------------------
00243   TMPL void inline
00244   add(Polynomial &r, const Polynomial& a) {
00245     array::add(r,a);
00246     check_degree(r);
00247   }
00248   //----------------------------------------------------------------------
00249   TMPL void inline
00250   sub(Polynomial &r, const Polynomial& a, const Polynomial & b) {
00251     array::sub(r,a,b);
00252     check_degree(r);
00253   }
00254   //----------------------------------------------------------------------
00255   TMPL void inline
00256   sub(Polynomial &r, const Polynomial& a) {
00257     array::sub(r,a);
00258     check_degree(r);
00259   }
00260   //----------------------------------------------------------------------
00261   TMPL void inline
00262   sub(Polynomial &r, const Polynomial& a, const C& c) {
00263     if(degree(a)>-1) {
00264       r=a; r[0]-=c;
00265     }
00266     else
00267       r= Polynomial(-c,0);
00268     check_degree(r);
00269   }
00270   //----------------------------------------------------------------------
00271   TMPLX void inline
00272   sub(Polynomial &r, const Polynomial& a, const X& x) {
00273     sub(r,a,(C)x);
00274   }
00275   //--------------------------------------------------------------------
00276   TMPL void inline
00277   sub(Polynomial &r, const C& c) {
00278     if(degree(r)>-1) {
00279      r[0]-=c;
00280     }
00281     else
00282       r= Polynomial(-c,0);
00283     check_degree(r);
00284   }
00285   //----------------------------------------------------------------------
00286   TMPL void inline
00287   mul(Polynomial &r, const Polynomial& a, const Polynomial & b) {
00288     assert(&r!=&a);
00289     
00290     r.resize(std::max(degree(a)+degree(b)+1,0));
00291     array::set_cst(r,(C)0);
00292     mul_index(r,a,b);
00293     check_degree(r);
00294   }
00295 
00296   //--------------------------------------------------------------------
00298   TMPL void inline 
00299   mul(Polynomial &r, const C & c) {
00300     array::mul_ext(r,c);
00301   }
00302 
00303   //--------------------------------------------------------------------
00305   TMPL void inline 
00306   mul(Polynomial &a, const Polynomial & b) {
00307     Polynomial r; mul(r,a,b); a=r;
00308   }
00309   //----------------------------------------------------------------------
00310   TMPL void inline
00311   mul(Polynomial &r, const Polynomial& p, const C & c) {
00312     r=p; mul(r,c); check_degree(r);
00313   }
00314 
00315 
00316   //----------------------------------------------------------------------
00317   TMPL void inline
00318   shift(Polynomial &r, const Polynomial& p, int d, int v=0) {
00319     if(d>=0) {
00320       r.resize(degree(p)+d+1);
00321       for(int i=0; i<d;i++) 
00322         r[i]= (typename Polynomial::coeff_t)0;
00323       for(int i=0; i<=degree(p);i++) 
00324         r[i+d]=p[i];
00325     }
00326   }
00327 
00328   //----------------------------------------------------------------------
00329   TMPL void inline
00330   div(Polynomial &r, const Polynomial& a, const Polynomial & b) {
00331     assert(&r!=&a);
00332     Polynomial tmp(a);
00333     r = Polynomial(0);
00334     div_rem(r,tmp,b);
00335     check_degree(r);
00336   }
00337 
00338   //----------------------------------------------------------------------
00339   TMPL void inline
00340   div(Polynomial &r, const Polynomial& b) {
00341     Polynomial tmp(r);
00342     r = Polynomial(0);
00343     div_rem(r,tmp,b);
00344     check_degree(r);
00345   }
00346 
00347   //--------------------------------------------------------------------
00348   TMPL void inline 
00349   div(Polynomial &r, const C & c) {
00350     array::div_ext(r,c);
00351     check_degree(r);
00352   }
00353 
00354   //-------------------------------------------------------------------
00356   template< class R > inline typename R::value_type
00357   lcoeff(const R& p) {
00358     return p[degree(p)];
00359   }
00360   //-------------------------------------------------------------------
00362   template< class R > inline typename R::value_type    
00363   tcoeff(const R& p)     { return p[0]; }
00364 
00365   //-------------------------------------------------------------------
00366   template <class OSTREAM, class C> OSTREAM& 
00367   print_as_coeff(OSTREAM & os, const C & c, bool plus)
00368   {
00369     if(plus) 
00370       os <<"+";
00371     os<<"("<<c<<")";
00372     return os;
00373   }
00374   
00375   template <class OSTREAM, class C, class VAR>  inline OSTREAM& 
00376   print(OSTREAM& os, const Polynomial& p, const VAR& var)
00377   {
00378     typedef typename Polynomial::value_type coeff_t;
00379     bool plus=false, not_one;
00380     if ( degree(p)<0) 
00381       os << coeff_t(0) ;
00382     else {
00383       for(int i= 0; i<=degree(p); i++)
00384       {
00385         if(p[i]!= (coeff_t)0) 
00386         {
00387           not_one = (p[i] != (coeff_t)1);
00388           if(not_one || i==0)
00389             print_as_coeff(os,p[i],plus);
00390           plus=true;
00391           //      if(i != degree(p) && with_plus_sign(p[i])) os<<"+"; 
00392           if(i>0)
00393             {
00394               //              if(p[i] == (coeff_t)(-1)) os<<"-";
00395               //              else 
00396               if(not_one) 
00397                 os<<"*";
00398               os<<"x";
00399               if(i !=1) 
00400                 {os<<'^'; os<<i;}
00401             }
00402 //        else
00403 //            os<<p[0];
00404         }
00405       }
00406       if(!plus) os << 0 ;
00407     }
00408     return os;
00409   }
00410 
00411   template <class OSTREAM, class C>  inline OSTREAM& 
00412   print(OSTREAM& os, const Polynomial& p) {
00413     return print(os,p, "x");
00414   }
00415  
00416   //--------------------------------------------------------------------
00417   template <class R, class C>
00418   inline void set_monomial(R & x, const C & c, unsigned n)
00419   {
00420 
00421     x.resize(n+1);
00422     array::set_cst(x,(typename R::value_type)0);
00423     x[n]=c;
00424     checkdegree(x);
00425 
00426   }
00427   //--------------------------------------------------------------------
00428   template <class R, class S>
00429   inline void add_cst(R & r, const S & c)  { r[0]+=c; }
00430 
00431   template <class R, class S>
00432   inline void sub_cst(R & r, const S & c)  { r[0]-=c;}
00433   //-------------------------------------------------------------------
00434   template <class R>
00435   inline void mul_index(R & r, const R & a, const R & b)
00436   {
00437     typedef typename R::coeff_t Scalar;
00438     int da=degree(a), db=degree(b),i,j;
00439     for (i=0;i<=db;i++) {
00440       if  (b[i] == 0) continue;
00441       for (j=0;j<=da;j++) r[i+j] += a[j]*b[i];
00442     }
00443   }
00444   //-------------------------------------------------------------------
00445   template <class R> inline
00446   void mul_index_it(R & r, const R & a, const R & b) 
00447   {
00448     typename R::const_iterator ia, ib;
00449     typename R::iterator       ir, it;
00450     ir=r.begin();
00451     for (ib=b.begin();ib !=b.end()&& ir != r.end();++ib) {
00452       typename R::value_type c = *ib;
00453       it=ir;
00454       if  (c==0) {++ir;continue;}
00455       for (ia=a.begin();ia!=a.end();++ia,++it) {
00456         (*it)+=(*ia)*c;
00457       }
00458       ++ir;
00459     }
00460   }
00461   //-------------------------------------------------------------------
00462   template <class R> inline
00463   void mul(R & a, const R & b)
00464   {
00465     if(degree(a)>=0 && degree(b)>=0)
00466       {
00467         R ta(a);
00468         a.resize(degree(a)+degree(b)+1);
00469         array::set_cst(a,0);
00470         mul_index(a,ta,b);
00471       }
00472     else
00473       array::set_cst(a,0);
00474   }
00475   //--------------------------------------------------------------------
00476   template <class R> inline
00477   void mul_index(R & a, const R & b) 
00478   {
00479     R ta(a);
00480     a.resize(degree(a)+degree(b)+1);
00481     array::set_cst(a,0);
00482     mul_index(a,ta,b);
00483   }
00484   //----------------------------------------------------------------------
00485   template <class C, class R>
00486   inline C eval_horner(const R & p, const C & c)
00487   {
00488     using namespace let;
00489     C r,cf;
00490     if(degree(p)>0) {
00491       typedef typename R::const_reverse_iterator const_reverse_iterator;
00492       const_reverse_iterator it=p.rbegin();
00493         assign(r,*it); it++;
00494         //      for(; it !=p.rend(); ++it) {r*=c; assign(cf,*it); r+=cf;}
00495         for(; it !=p.rend(); ++it) {r=r*c; assign(cf,*it); r=r+cf;}
00496         return r;
00497     } else if(degree(p)>-1)
00498       {
00499         assign(r,p[0]); return r;
00500       }
00501     else
00502       return C(0);
00503   }
00504   //----------------------------------------------------------------------
00505   template <class C, class R>
00506   inline C eval_horner_idx(const R & p, const C & c)
00507   {
00508     if(degree(p)>0) {
00509       int d=degree(p);
00510       C r=p[d];
00511       for(int i=d-1; i>-1; --i) {r*=c; r+= p[i];}
00512       return r;
00513     } else if(degree(p)>-1)
00514       return p[0];
00515     else
00516       return C(0);
00517   }
00518   //--------------------------------------------------------------------
00519   template <class C, class R>
00520   inline C eval(const R & p, const C & c)
00521   {
00522     return eval_horner(p,c);
00523   }
00524   //----------------------------------------------------------------------
00525   template <class C, class R>
00526   inline C eval_homogeneous(const R & p, const C & a, const C& b)
00527   {
00528     using namespace let;
00529     C r,y=1,cf;
00530     if(degree(p)>0) {
00531       typedef typename R::const_reverse_iterator const_reverse_iterator;
00532       const_reverse_iterator it=p.rbegin();
00533       assign(r,*it); it++;
00534       //        for(; it !=p.rend(); ++it) {r*=c; assign(cf,*it); r+=cf;}
00535       for(; it !=p.rend(); ++it) {r*=a; y *=b; assign(cf,*it); r=r+cf*y;}
00536       return r;
00537     } else if(degree(p)==0)
00538       {
00539         assign(r,p[0]); return r;
00540       }
00541     else
00542       return C(0);
00543   }
00544 
00545   //--------------------------------------------------------------------
00546   template<typename POL, typename X> inline
00547   int sign_at(const POL & p, const X& x)
00548   {
00549     X v= eval_horner(p,x);
00550     return sign(v);
00551   }
00552 
00558   template<class R>
00559   void div_rem(R & q, R & a, const R & b) 
00560   {
00561     typedef typename R::iterator iterator;
00562     int da = degree(a), db=degree(b);
00563     typename R::value_type lb=b[db];
00564     R t;
00565     q=(R)0;
00566     while (da>=db) {
00567       while(a[da]==0 && da>=db) da--;
00568       if(da>=db) {
00569         R m( a[da]/lb, da-db );
00570         mul(t,b,m);
00571         t[da]=a[da];
00572         sub(a,t);
00573         add(q,m);
00574       }
00575     }
00576   } 
00577 
00578 //----------------------------------------------------------------------
00579 template<class R> inline void checkdegree(R & p) { 
00580   int d = p.size()-1; 
00581   if ( d < 0 ) return;
00582   while ( p[d] == 0 ) d--;
00583   p.resize(d+1);
00584 }
00585 //----------------------------------------------------------------------
00586 template <class R> inline  R diff(const R & p);
00587 //----------------------------------------------------------------------
00588 template<class R> void reciprocal(R & w,const R & p);
00589 //----------------------------------------------------------------------
00590 template<class R> void reverse(R & p, typename R::size_type n)
00591 {
00592   int l=n-1;
00593   for(typename R::size_type i=0;i<n/2;i++) 
00594     std::swap(p[i],p[l-i]);
00595 }
00596 //----------------------------------------------------------------------
00597 template<class R>
00598 typename R::value_type derive(const R p,typename R::value_type x);
00599 //----------------------------------------------------------------------
00600 template<class R> void reduce(R & p, const typename R::size_type & e);
00601 //----------------------------------------------------------------------
00602 template<class R, class C> 
00603   void scale(R & t,const R & p,const C & l);
00604 //----------------------------------------------------------------------
00607 template<class R> inline
00608 void diff(R & r, const R & p) // version + simple
00609 {
00610   int n,i;
00611   r.resize(n=degree(p));
00612   for( i = 1; i < n+1; ++i) r[i-1] =p[i]*i;
00613 }
00614   // ancienne version
00615   // template <class R> inline
00616   // void diff(R & r, const R & p)
00617   // {
00618   //   if(degree(p)>0)//  assert(degree(p)>0);
00619   //    {
00620   //      for(unsigned i=1;i<p.size();++i)
00621   //        r[i-1] =p[i]*i;
00622   //      r.resize(degree(p));
00623   //    } else r.resize(0);
00624   // }
00625 
00626 //---------------------------------------------------------------------
00629 template <class R> inline
00630 R diff(const R & p)
00631 {
00632   R r(p); 
00633   diff(r,p);
00634   return r;
00635 }
00636 // ancienne version
00637 // template <class R> inline 
00638 // R diff(const R & p)
00639 // {
00640 //   R r(p);
00641 //   if(degree(p)>0) {
00642 //      for(unsigned i = 1; i < p.size(); ++i)
00643 //        r[i-1] = p[i] * i;
00644 //      r.resize(degree(p));
00645 //   } else r.resize(0);
00646 //   return r;
00647 // }
00648 //---------------------------------------------------------------------
00659 template <class R>
00660 void reciprocal(R & w, const R & p)
00661 {
00662   typedef typename R::size_type size_type;
00663   typedef typename R::value_type C;
00664 
00665   const size_type deg = univariate::degree(p)+1;
00666   R w0(deg),v(deg),xp(p);
00667   size_type K = (size_type) (std::log(p.degree()+1)/std::log(2)),j=1;
00668   C p0 = xp[deg-1];
00669 
00670   xp /= p0;
00671   w0 =xp/xp[0];
00672   v = w0;
00673   v *= C(-1.0);
00674   v[0]+=C(2);
00675   w=v/xp[0];
00676   w0=w;
00677   while (j <= K) {
00678     univariate::reduce(w0,pow(2,j+1));
00679     w=xp*w0;
00680     v =w;
00681     v*=C(-1.0);
00682     v[0]+=C(2);
00683     univariate::reduce(v,pow(2,j+1));
00684     w=w0*v;
00685     w0=w;
00686     j++;
00687   }
00688    univariate::reduce(w,deg);
00689    w/=p0;
00690 }
00691 //-------------------------------------------------------------------------
00695 template <class T> 
00696 inline void reduce(T & p, const typename T::size_type & e)
00697 {
00698   // il me semble que tout ca c'est la meme chose que p.resize(e) 
00699   T temp(e);
00700   for (typename T::size_type i = 0; i < e; i++) temp[i]=p[i];
00701   p.resize(e);
00702   //  p.degree()=e-1;
00703   for (typename T::size_type i = 0; i < e; i++) p[i]=temp[i];
00704 }
00705 //-------------------------------------------------------------------------
00715 template <class T> // version + simple
00716 inline void reverse(T & p, int n)
00717 { for ( int i = 0; i < n/2; i++ ) std::swap(p[i],p[n-i]) ; }
00718 
00719 // template <class T> // ancienne version
00720 // inline void reverse(T & p,typename T::size_type n)
00721 // {
00722 //   for (typename T::size_type i = 0, j=n-1; i<j; i++, j--)
00723 //     {
00724 //       swap(p[i],p[j]);
00725 //     }
00726 // }
00727 
00728 //----------------------------------------------------------------------------
00737 template<class O, class R, class I> inline
00738 void eval( O& p, O& dp, const R& Pol, const I& x )
00739 {
00740   int n = p.size()-1;
00741   p  = Pol[n];
00742   dp = O(0);
00743   for ( int j = n-1; j >= 0; dp = dp*x + p, p =p*x + Pol[j], j-- ) ; 
00744 };
00745 
00754 template <class R> inline // wrap sur eval
00755 typename R::value_type derive( const R& Pol, const typename R::value_type& x )
00756 { 
00757   typename R::value_type p,res;
00758   eval(p,res,Pol,x); 
00759   return res;
00760 };
00761 
00762 // template <class R> // ancienne version
00763 // inline typename R::value_type
00764 // derive(const R p, typename R::value_type x)
00765 // {
00766 //   typename R::size_type degree = p.degree();
00767 //   typename R::value_type  deriv(0);
00768 //   for (typename R::size_type j=1; j<=p.degree();j++)
00769 //     deriv+=p[j]*j*pow(x,j-1);
00770 //   return (typename R::value_type) deriv;
00771 // }
00772 
00773 //--------------------------------------------------------------------
00777 template< class R,class C> // version + simple
00778 void shift( R& p, const C& c )
00779 {
00780   int j,k,s;
00781   for ( s = p.size(), j = 0; j <= s-2; j++ )
00782     for( k = s-2; k >= j; p[k] += c*p[k+1], k-- ) ;
00783 };
00784 //--------------------------------------------------------------------
00789 template<class R, class C> 
00790 void shift(R & r,const R & p,const C& x0)
00791 {
00792   r=p; shift(r,x0);
00793 }
00794 
00795 // ancienne version
00796 // {
00797 //   R dp(p);
00798 //   r[0]=eval_horner(dp,x0);
00799 //   for(unsigned i=1; i< p.size();i++){
00800 //     diff(dp,dp);
00801 //     array::div(dp,i);
00802 //     r[i]=eval_horner(dp,x0);
00803 //   }
00804 // }
00805 //--------------------------------------------------------------------
00806 
00811 template<class R, class C>
00812 void scale(R & r, const R & p, const C & l)
00813 {
00814   r=p;
00815   C s(l);
00816   for(unsigned i=1; i< p.size();i++){
00817     r[i]*=s;
00818     s *=l;
00819   }
00820 }
00821 //--------------------------------------------------------------------
00822 
00827 template<class R, class C>
00828 void inv_scale(R & r, const R & p, const C & l)
00829 {
00830   int sz=p.size();
00831   r.resize(sz);
00832   sz--;
00833   r[sz]=p[sz];
00834   typename R::value_type s=l;
00835   for(int i=sz-1; i>=0;i--){
00836     r[i]=p[i]*s;
00837     s *=l;
00838   }
00839 }
00840 
00841 //--------------------------------------------------------------------
00846 template<class T,class P, class C> void  
00847 convertm2b(T& bz, const P& p, unsigned size, const C& a, const C& b) {
00848   typedef typename T::value_type coeff_t;
00849   T pps(p.size());
00850   array::assign(pps,p);
00851   
00852   if(a !=0)
00853     shift(pps,pps,a);
00854   
00855   scale(pps, pps, C(b-a));
00856   
00857   array::set_cst(bz,pps[0]);
00858   int dn=1, nm=1;
00859   
00860   for(unsigned j=1; j<size; j++) {
00861     dn *= (size-j); dn/= j;
00862     nm=1;
00863     bz[j] += pps[j]/dn;
00864     for(unsigned i=j+1; i<size; i++) {
00865       nm *= i; nm/= (i-j);
00866       bz[i] += pps[j]*nm/dn;
00867     }
00868   }
00869 }
00870 //--------------------------------------------------------------------
00871 
00872 template<class R>
00873 void coeff_modulo( R & r, const typename R::value_type & x ) {
00874   for ( typename R::iterator i = r.begin(); i != r.end(); *i %= x, ++i ) ;
00875 };
00876 //--------------------------------------------------------------------
00877 template<class S, class R>
00878 S numer(const R & f) {
00879   S p(0,degree(f));
00880   typename S::value_type d=1;
00881   for(int i=0;i<degree(f)+1;i++) {
00882     if (f[i] !=0) d=lcm(d,denominator(f[i]));
00883   }
00884   for(int i=0;i<degree(f)+1;i++) 
00885     p[i]=numerator(f[i])* (d/denominator(f[i]));
00886   return p;
00887 }
00888 //--------------------------------------------------------------------
00889 } //namespace univariate
00890 //======================================================================
00891 # undef  Polynomial
00892 # define Polynomial univariate::monomials<C>
00893 # define TMPL template<class C>
00894 
00895 template<class A, class B> struct use;
00896 struct operators_of;
00897 
00898 TMPL struct use<operators_of,Polynomial> {
00899 
00900     static inline void 
00901     add (Polynomial &r, const Polynomial &a ) { 
00902       univariate::add (r, a); 
00903     }
00904     static inline void 
00905     add (Polynomial &r, const Polynomial &a, const Polynomial &b) {
00906       univariate::add (r, a, b); 
00907     }
00908     static inline void
00909     add (Polynomial &r, const Polynomial &a, const C & b) {
00910       univariate::add (r, a, b); 
00911     }
00912     static inline void
00913     add (Polynomial &r, const C & a, const Polynomial &b) {
00914       univariate::add (r, b, a); 
00915     }
00916     static inline void
00917     sub (Polynomial &r, const Polynomial &a ) {
00918       univariate::sub (r, a ); 
00919     }
00920     static inline void
00921     sub (Polynomial &r, const Polynomial &a, const Polynomial &b) {
00922       univariate::sub (r, a, b); 
00923     }
00924     static inline void
00925     sub (Polynomial &r, const C & a, const Polynomial &b) {
00926       univariate::sub (r, a, b); 
00927     }
00928     static inline void
00929     sub (Polynomial &r, const Polynomial &a, const C & b) {
00930       univariate::sub (r, a, b); 
00931     }
00932     static inline void
00933     mul (Polynomial &r, const Polynomial &a ) {
00934       univariate::mul (r, a ); 
00935     }
00936     static inline void
00937     mul (Polynomial &r, const Polynomial &a, const Polynomial &b) {
00938       univariate::mul (r, a, b); 
00939 }
00940     static inline void
00941     mul (Polynomial &r, const Polynomial &a, const C & b) {
00942       univariate::mul (r, a, b); }
00943     static inline void
00944     mul (Polynomial &r, const C & a, const Polynomial &b) {
00945       univariate::mul (r, b, a); 
00946     }
00947     static inline void
00948     div (Polynomial &r, const Polynomial &a, const Polynomial &b) {
00949       univariate::div (r, a, b); 
00950     }
00951     static inline void
00952     div (Polynomial &r, const Polynomial &a, const C & b) {
00953       univariate::div (r, a, b); 
00954     } 
00955     static inline void
00956     div (Polynomial &a, const C & c) {
00957       univariate::div (a, c); 
00958     }
00959 //     static inline void
00960 //     rem (Polynomial &r, const Polynomial &a, const Polynomial &b) {
00961 //       univariate::rem (r, b, a); 
00962 //     }
00963 };
00964 # undef Polynomial
00965 # undef TMPL
00966 //====================================================================
00967 } //namespace mmx 
00968 //======================================================================
00969 # undef TMPL
00970 # undef TMPLX
00971 # undef Polynomial
00972 #endif // realroot_univariate_hpp
00973