synaps/upol/UPOLDAR.m

00001 /*********************************************************************
00002 *      This file is part of the source code of SYNAPS 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 synaps_upol_upoldar_H
00010 #define synaps_upol_upoldar_H
00011 //--------------------------------------------------------------------
00012 #include <iostream>
00013 #include <synaps/init.h>
00014 #include <synaps/arithm/let.h>
00015 #include <synaps/arithm/sign.h>
00016 #include <synaps/linalg/VECTOR.m>
00017 //--------------------------------------------------------------------
00018 __BEGIN_NAMESPACE_SYNAPS
00019 //====================================================================
00020 namespace let {
00021   template<class A,class B> void assign(A&, const B&);
00022 }
00023 namespace VECTOR {}
00024 //====================================================================
00026 
00041 namespace UPOLDAR 
00042 {
00043 
00044   using VECTOR::add;
00045   using VECTOR::sub;
00046   using VECTOR::mul_ext;
00047   using VECTOR::div_ext;
00048 
00049   //-------------------------------------------------------------------
00050   template <class R>
00051   int degree(const R & p)
00052   {
00053     // std::cout <<"(Using default degree) "<<p<<std::endl;
00054     int i = p.size()-1;
00055     while(i>-1 && p[i]==0) i--;
00056     return i;
00057   }
00058   //-------------------------------------------------------------------
00060   template< class R >
00061   inline
00062   typename R::value_type
00063   lcoeff(const R& p)
00064   {
00065     return p;
00066   }
00067   //-------------------------------------------------------------------
00069   template< class R >
00070   inline
00071   typename R::value_type
00072   tcoeff(const R& p)
00073   {
00074     return p;
00075   }
00076   //-------------------------------------------------------------------
00077 //   template <class output, class R>
00078 //   inline output & print(output & os, const R & p)
00079 //   {
00080 //     bool plus=false;
00081 //     if ( degree(p)<0) os << '(' << 0 << ')';
00082 //     else {
00083 //     for(int i= degree(p); i!= -1; i--)
00084 //       {
00085 //         if(p[i]!=0) {
00086 //           if(plus) os<<'+'; else plus=true;
00087 //           print_coeff(os,p[i]);
00088 //           if(i==0);
00089 
00090 //           else  {
00091 //             os<<"*x0"; if(i !=1) os<<'^'<<i;
00092 //           }
00093 //         }
00094 //       }
00095 //       if(!plus) os << '(' << 0 << ')';
00096 //     }
00097 //     return os;
00098 //   }
00099   //-------------------------------------------------------------------
00100   template <class C>
00101   std::ostream & print_as_coeff(std::ostream & os, const C & c)
00102   {
00103     if(with_plus_sign(c)) 
00104       os <<"+";
00105     os<<c;
00106     return os;
00107   }
00108   
00109   template <class R>
00110   inline std::ostream & print(std::ostream & os, const R & p,char* x = "x")
00111   {
00112     typedef typename R::value_type coeff_t;
00113     bool plus=false;
00114     if ( degree(p)<0) os << '(' << 0 << ')';
00115     else {
00116     for(int i= degree(p); i!= -1; i--)
00117       {
00118         if(p[i]!= 0) {
00119           plus=true;
00120           if(i!=degree(p))
00121             print_as_coeff(os,p[i]);
00122           else
00123             os <<p;
00124           if(i!=0)
00125             {
00126               os<<"*"<<x; 
00127               if(i !=1) os<<'^'<<i;
00128             }
00129         }
00130       }
00131       if(!plus) os << '(' << 0 << ')';
00132     }
00133     return os;
00134   }
00135   //--------------------------------------------------------------------
00136   template <class R, class C>
00137   inline void set_monomial(R & x, const C & c, unsigned n)
00138   {
00139 
00140     x.resize(n+1);
00141     VECTOR::init(x,(typename R::value_type)0);
00142     x=c;
00143     checkdegree(x);
00144 
00145   }
00146   //--------------------------------------------------------------------
00147   template <class R, class S>
00148   inline void add_cst( R & r, const R & a, const S & c )
00149   {
00150     
00151   };
00152   
00153   template <class R, class S>
00154   inline void add_cst(R & r, const S & c)
00155   {
00156     r+=c;
00157   }
00158   //-------------------------------------------------------------------
00159   template <class R,class A, class B>
00160   inline void mul_index(R & r, const A & a, const B & b)
00161   {
00162     int da=degree(a),
00163       db=degree(b),i,j;
00164     for (i=0;i<=db;i++) {
00165       typename R::value_type bi = b[i];
00166       if  (bi==0) continue;
00167       for (j=0;j<=da;j++) {r[i+j] += a[j]*bi;}
00168     }
00169   }
00170   //-------------------------------------------------------------------
00171   template <class R> inline
00172   void mul_index_it(R & r, const R & a, const R & b) 
00173   {
00174     typename R::const_iterator ia, ib;
00175     typename R::iterator       ir, it;
00176     ir=r.begin();
00177     for (ib=b.begin();ib !=b.end()&& ir != r.end();++ib) {
00178       typename R::value_type c = *ib;
00179       it=ir;
00180       if  (c==0) {++ir;continue;}
00181       for (ia=a.begin();ia!=a.end();++ia,++it) {
00182         (*it)+=(*ia)*c;
00183       }
00184       ++ir;
00185     }
00186   }
00187   //-------------------------------------------------------------------
00188   template <class R> inline
00189   void mul(R & r, const R & a, const R & b)
00190   {
00191     VECTOR::init(r,0);
00192     mul_index(r,a,b);
00193   }
00194   //-------------------------------------------------------------------
00195 template <class R> inline
00196 void mul(R & a, const R & b)
00197 {
00198   if(degree(a)>=0 && degree(b)>=0)
00199     {
00200       R ta(a);
00201       a.resize(degree(a)+degree(b)+1);
00202       VECTOR::init(a,0);
00203       mul_index(a,ta,b);
00204     }
00205   else
00206     VECTOR::init(a,0);
00207 }
00208 //--------------------------------------------------------------------
00209 template <class R> inline
00210 void mul_index(R & a, const R & b) 
00211 {
00212     R ta(a);
00213     a.resize(degree(a)+degree(b)+1);
00214     VECTOR::init(a,0);
00215     mul(a,ta,b);
00216 }
00217 //--------------------------------------------------------------------
00218 template <class R>  inline
00219 void mul_karatsuba(R& r, const R & a, const R & b)
00220 {
00221      mul_index(r,a,b);
00222 }
00223 //----------------------------------------------------------------------
00224 template <class C, class R>
00225 inline C eval_horner(const R & p, const C & c)
00226 {
00227   using namespace let;
00228   C r,cf;
00229   if(degree(p)>0) {
00230         typedef typename R::const_reverse_iterator const_reverse_iterator;
00231         const_reverse_iterator it=p.rbegin();
00232         assign(r,*it); it++;
00233         for(; it !=p.rend(); ++it) {r*=c; assign(cf,*it); r+=cf;}
00234         return r;
00235   } else if(degree(p)>-1)
00236   {
00237         assign(r,p[0]); return r;
00238   }
00239   else
00240         return C(0);
00241 }
00242 //----------------------------------------------------------------------
00243 template <class C, class R>
00244 inline C eval_horner_idx(const R & p, const C & c)
00245 {
00246   if(degree(p)>0) {
00247     int d=degree(p);
00248     C r=p;
00249     for(int i=d-1; i>-1; --i) {r*=c; r+= p;}
00250     return r;
00251   } else if(degree(p)>-1)
00252     return p[0];
00253   else
00254     return C(0);
00255 }
00256 
00257 //--------------------------------------------------------------------
00258 template<typename POL, typename X> inline
00259 int sign_at(const POL & p, const X& x)
00260 {
00261   X v= eval_horner(p,x);
00262   return sign(v);
00263 }
00264 //--------------------------------------------------------------------
00265 template <class C, class R>
00266 inline C eval(const R & p, const C & c)
00267 {
00268   return eval_horner(p,c);
00269 }
00270 
00271 template<class R>
00272 void div_rem(R & q, R & a, const R & b)
00273 {
00274   typedef typename R::value_type CF;
00275   typedef typename R::iterator iterator;
00276   CF lb = b;
00277   q=0;
00278   while (degree(a)>=degree(b)) {
00279     CF lt(a[degree(a)]/lb);
00280     int s = degree(a)-degree(b);
00281     for ( int i = 0; i < degree(b)+1; i ++ )
00282       a[i+s] -= lt*b[i];
00283     if ( degree(q) < s ) q.resize(s+1);
00284     q = lt;
00285   }
00286 
00287 }
00288 
00289 //----------------------------------------------------------------------
00290 template<class R> inline void checkdegree(R & p) { 
00291   int d = p.size()-1; 
00292   if ( d < 0 ) return;
00293   while ( p[d] == 0 ) d--;
00294   p.resize(d+1);
00295 }
00296 //----------------------------------------------------------------------
00297 template <class R> inline  void diff(R & r, const R & p);
00298 //----------------------------------------------------------------------
00300 template <class R> inline  R diff(const R & p);
00301 //----------------------------------------------------------------------
00302 template<class R> void reciprocal(R & w,const R & p);
00303 //----------------------------------------------------------------------
00304 template<class R> void reverse(R & p, typename R::size_type n);
00305 //----------------------------------------------------------------------
00306 template<class R>
00307 typename R::value_type derive(const R p,typename R::value_type x);
00308 //----------------------------------------------------------------------
00309 template<class R> void reduce(R & p, const typename R::size_type & e);
00310 //----------------------------------------------------------------------
00311 template<class R>
00312   void shift(R & t, const typename R::value_type & x0);
00313 template<class R>
00314   void shift(R & t,const R & p,const typename R::value_type & x0);
00315 //----------------------------------------------------------------------
00316 template<class R, class C> 
00317   void scale(R & t,const R & p,const C & l);
00318 //----------------------------------------------------------------------
00321 template<class R> inline
00322 void diff(R & r, const R & p) // version + simple
00323 {
00324   int n,i;
00325   r.resize(n=degree(p));
00326   for( i = 1; i < n+1; ++i) r[i-1] =p[i]*i;
00327 }
00328   // ancienne version
00329   // template <class R> inline
00330   // void diff(R & r, const R & p)
00331   // {
00332   //   if(degree(p)>0)//  assert(degree(p)>0);
00333   //    {
00334   //      for(unsigned i=1;i<p.size();++i)
00335   //        r[i-1] =p[i]*i;
00336   //      r.resize(degree(p));
00337   //    } else r.resize(0);
00338   // }
00339 
00340 //---------------------------------------------------------------------
00343 template <class R> inline
00344 R diff(const R & p)
00345 {
00346   R r(p); 
00347   diff(r,p);
00348   return r;
00349 }
00350 // ancienne version
00351 // template <class R> inline 
00352 // R diff(const R & p)
00353 // {
00354 //   R r(p);
00355 //   if(degree(p)>0) {
00356 //      for(unsigned i = 1; i < p.size(); ++i)
00357 //        r[i-1] = p[i] * i;
00358 //      r.resize(degree(p));
00359 //   } else r.resize(0);
00360 //   return r;
00361 // }
00362 //---------------------------------------------------------------------
00373 template <class R>
00374 void reciprocal(R & w,const R & p)
00375 {
00376   typedef typename R::size_type size_type;
00377   typedef typename R::value_type C;
00378 
00379   const size_type deg = UPOLDAR::degree(p)+1;
00380   R w0(deg),v(deg),xp(p);
00381   size_type K = (size_type) (log(p.degree()+1)/log(2)),j=1;
00382   C p0 = xp;
00383 
00384   xp /= p0;
00385   w0 =xp/xp;
00386   v = w0;
00387   v *= C(-1.0);
00388   v+=C(2);
00389   w=v/xp;
00390   w0=w;
00391   while (j <= K) {
00392     UPOLDAR::reduce(w0,pow(2,j+1));
00393     w=xp*w0;
00394     v =w;
00395     v*=C(-1.0);
00396     v+=C(2);
00397     UPOLDAR::reduce(v,pow(2,j+1));
00398     w=w0*v;
00399     w0=w;
00400     j++;
00401   }
00402    UPOLDAR::reduce(w,deg);
00403    w/=p0;
00404 }
00405 //-------------------------------------------------------------------------
00409 template <class T> 
00410 inline void reduce(T & p, const typename T::size_type & e)
00411 {
00412   // il me semble que tout ca c'est la meme chose que p.resize(e) 
00413   T temp(e);
00414   for (typename T::size_type i = 0; i < e; i++) temp[i]=p[i];
00415   p.resize(e);
00416   //  p.degree()=e-1;
00417   for (typename T::size_type i = 0; i < e; i++) p[i]=temp[i];
00418 }
00419 //-------------------------------------------------------------------------
00429 template <class T> // version + simple
00430 inline void reverse(T & p, int n)
00431 { for ( int i = 0; i < n/2; i++ ) std::swap(p[i],p[n-i]) ; }
00432 
00433 // template <class T> // ancienne version
00434 // inline void reverse(T & p,typename T::size_type n)
00435 // {
00436 //   for (typename T::size_type i = 0, j=n-1; i<j; i++, j--)
00437 //     {
00438 //       swap(p[i],p[j]);
00439 //     }
00440 // }
00441 
00442 //----------------------------------------------------------------------------
00451 template<class O, class R, class I> inline
00452 void eval( O& p, O& dp, const R& Pol, const I& x )
00453 {
00454   int n = p.size()-1;
00455   p  = Pol;
00456   dp = O(0);
00457   for ( int j = n-1; j >= 0; dp = dp*x + p, p =p*x + Pol, j-- ); 
00458 };
00459 
00468 template <class R> inline // wrap sur eval
00469 typename R::value_type derive( const R& Pol, const typename R::value_type& x )
00470 { 
00471   typename R::value_type p,res;
00472   eval(p,res,Pol,x); 
00473   return res;
00474 };
00475 
00476 // template <class R> // ancienne version
00477 // inline typename R::value_type
00478 // derive(const R p, typename R::value_type x)
00479 // {
00480 //   typename R::size_type degree = p.degree();
00481 //   typename R::value_type  deriv(0);
00482 //   for (typename R::size_type j=1; j<=p.degree();j++)
00483 //     deriv+=p[j]*j*pow(x,j-1);
00484 //   return (typename R::value_type) deriv;
00485 // }
00486 
00487 //--------------------------------------------------------------------
00491 template< class R> // version + simple
00492 void shift( R& p, const typename R::value_type& c )
00493 {
00494   int j,k,s;
00495   for ( s = p.size(), j = 0; j <= s-2; j++ )
00496     for( k = s-2; k >= j; p += c*p, k-- );
00497 };
00498 //--------------------------------------------------------------------
00503 template<class R> 
00504 void shift(R & r,const R & p,const typename R::value_type & x0)
00505 {
00506   r=p; shift(r,x0);
00507 }
00508 
00509 // ancienne version
00510 // {
00511 //   R dp(p);
00512 //   r[0]=eval_horner(dp,x0);
00513 //   for(unsigned i=1; i< p.size();i++){
00514 //     diff(dp,dp);
00515 //     VECTOR::div(dp,i);
00516 //     r[i]=eval_horner(dp,x0);
00517 //   }
00518 // }
00519 //--------------------------------------------------------------------
00520 
00525 template<class R, class C>
00526 void scale(R & r, const R & p, const C & l)
00527 {
00528   r.resize(p.size());
00529   r=p;
00530   typename R::value_type s=l;
00531   for(unsigned i=1; i< p.size();i++){
00532     r[i]=p[i]*s;
00533     s *=l;
00534   }
00535 }
00536 
00537 template<class R>
00538 void coeff_modulo( R & r, const typename R::value_type & x )
00539 {
00540   for ( typename R::iterator i = r.begin(); i != r.end(); *i %= x, ++i );
00541 };
00542 
00543 } //UPOLDAR
00544 /********************************************************************/
00545 __END_NAMESPACE_SYNAPS
00546 /*********************************************************************/
00547 #endif // SYNAPS_UPOL_UPOLDAR_H
00548 

SYNAPS DOCUMENTATION
logo