synaps/arithm/diadic.h

00001 /********************************************************************
00002  *   This file is part of the source code of the SYNAPS kernel.
00003  *   Author(s): B. Mourrain, GALAAD, INRIA
00004  *   $Id: diadic.h,v 1.1 2005/07/11 10:39:49 mourrain Exp $
00005  *   
00006  ********************************************************************/
00007 #ifndef SYNAPS_ARITHM_DIADIC_H
00008 #define SYNAPS_ARITHM_DIADIC_H
00009 //--------------------------------------------------------------------
00010 #include <cassert>
00011 #include <synaps/init.h>
00012 #include <synaps/base/type.h>
00013 #include <synaps/base/comparison.h>
00014 #include <synaps/arithm/let.h>
00015 #include <synaps/arithm/pow.h>
00016 #include <synaps/arithm/gmp.h>
00017 //--------------------------------------------------------------------
00018 __BEGIN_NAMESPACE_SYNAPS
00019 //--------------------------------------------------------------------
00020 template <class NT_>
00021 NT_ shift_2(const NT_& z, int d)
00022 {
00023   if(d>0)
00024     return z*pow(NT_(2),d);
00025   else
00026     return z/pow(NT_(2),-d);
00027 }
00028 
00029 //--------------------------------------------------------------------
00030 template< typename  NT_ > class diadic;
00031 namespace let 
00032 {
00033    template<typename NT_> void assign(diadic<NT_> & x, int i);
00034 }
00035 //--------------------------------------------------------------------
00040 template < typename  NT_ >
00041 class diadic
00042 {
00043   public:
00044   typedef NT_      NT;
00045   
00046   diadic() : num_(0), exp_(0) { }
00047 
00048   diadic(const NT& n,int d=0) : num_(n), exp_(d) {normalize();}
00049 
00050   template < typename  RT>
00051   diadic(const RT& n,int d=0) 
00052   { 
00053     let::assign(*this,n); 
00054     exp_+=d;
00055   }
00056 
00057   diadic<NT>& operator+= (const diadic<NT>& r);
00058   diadic<NT>& operator-= (const diadic<NT>& r);
00059   diadic<NT>& operator*= (const diadic<NT>& r);
00060   diadic<NT>& operator/= (const diadic<NT>& r);
00061   diadic<NT>& operator/= (int r);
00062   diadic<NT>& operator+= (const NT& r);
00063   diadic<NT>& operator-= (const NT& r);
00064   diadic<NT>& operator*= (const NT& r);
00065   diadic<NT>& operator/= (const NT& r);
00066   
00067   diadic<NT>& normalize();
00068   
00069   const NT&   numerator()   const { return num_; }
00070         NT    denominator() const { return shift_2(1,exp_); }
00071         int   valuation ()  const { return exp_; }
00072   
00073  public:
00074   NT   num_;
00075   int  exp_;
00076 };
00077 //------------------------------------------------------------------------
00078 template < typename NT >  inline
00079 diadic<NT>& diadic<NT>::normalize()
00080 {
00081  if( num_==0)
00082     exp_=0;
00083   else 
00084     while( (num_%2) ==0 ) 
00085       {
00086         exp_++;
00087         num_/=2;
00088       }
00089   return *this;
00090 }
00091 //--------------------------------------------------------------------
00092 // Arithmetic operators
00093 //--------------------------------------------------------------------
00095 template < typename NT >  inline
00096 diadic<NT>&
00097 diadic<NT>::operator+= (const diadic<NT>& r)
00098 {
00099   if(r.exp_<exp_)
00100     {
00101       int d=exp_-r.exp_;
00102       num_ =  shift_2(num_ ,d);
00103       num_ += r.num_;
00104       exp_ = r.exp_;
00105     }
00106   else if(r.exp_>exp_)
00107     {
00108       num_  += shift_2(r.num_,r.exp_-exp_);
00109     }
00110   else
00111     {
00112       num_ += r.num_;
00113       normalize();
00114     }
00115   return *this;
00116 }
00117 //------------------------------------------------------------------------
00119 template < typename NT >  inline
00120 diadic<NT>&
00121 diadic<NT>::operator-= (const diadic<NT>& r)
00122 {
00123   if(r.exp_<exp_)
00124     {
00125       num_  = shift_2(num_,exp_-r.exp_);
00126       num_ -= r.num_;
00127       exp_  = r.exp_;
00128     }
00129   else if(r.exp_>exp_)
00130     {
00131       num_ -=  shift_2(r.num_ ,r.exp_-exp_);
00132     }
00133   else
00134     {
00135       num_ -= r.num_;
00136       normalize();
00137     }
00138   return *this;
00139 }
00140 //------------------------------------------------------------------------
00142 template < typename NT >  inline
00143 diadic<NT>&
00144 diadic<NT>::operator*= (const diadic<NT>& r)
00145 {
00146   num_ *= r.num_;
00147   exp_ += r.exp_;
00148   return *this;
00149 }
00150 //------------------------------------------------------------------------
00155 template < typename NT >  inline
00156 diadic<NT>&
00157 diadic<NT>::operator/= (const diadic<NT>& r)
00158 {
00159   assert( r.num_ != 0 );
00160   exp_ -= r.exp_;
00161   num_ /= r.num_;
00162   normalize();
00163   return *this;
00164 }
00165 //------------------------------------------------------------------------
00169 template < typename NT >  inline
00170 diadic<NT>&
00171 diadic<NT>::operator/= (const NT& r)
00172 {
00173     assert( r != 0 );
00174     NT d=r;
00175     while( (d%2) ==0 ) 
00176       {
00177         exp_--;
00178         d/=2;
00179       }
00180     num_/=d;
00181     return *this;
00182 }
00183 //------------------------------------------------------------------------
00187 template < typename NT >  inline
00188 diadic<NT>&
00189 diadic<NT>::operator/= (int r)
00190 {
00191     assert( r != 0 );
00192     int d=r;
00193     while( d%2==0 ) { exp_--; d/=2; }
00194     num_/=d;
00195     return *this;
00196 }
00197 //------------------------------------------------------------------------
00199 template < typename NT >  inline
00200 diadic<NT>&
00201 diadic<NT>::operator+= (const NT& r)
00202 {
00203   if(exp_<0)
00204     num_ += shift_2(r,exp_);
00205   else if(exp_>0)
00206     {
00207       num_ = shift_2(num_,exp_);
00208       num_+=r;
00209     }
00210   else
00211     num_+=r;
00212   normalize();
00213   return *this;
00214 }
00215 //------------------------------------------------------------------------
00217 template < typename NT >  inline
00218 diadic<NT>&
00219 diadic<NT>::operator-= (const NT& r)
00220 {
00221   if(exp_<0)
00222     num_ -= shift_2(r,exp_);
00223   else if(exp_>0)
00224     {
00225       num_ = shift_2(num_,exp_);
00226       num_-= r;
00227     }
00228   else
00229     num_-= r;
00230   normalize();
00231   return *this;
00232 }
00233 //------------------------------------------------------------------------
00235 template < typename NT >  inline
00236 diadic<NT>&
00237 diadic<NT>::operator*= (const NT& r)
00238 {
00239   num_ *= r;
00240   normalize();
00241   return *this;
00242 }
00243 //------------------------------------------------------------------------
00244 // Help function. Do not use it :-)
00245 template < typename NT >  inline
00246 int
00247 quotient_cmp(const diadic<NT>& a, const diadic<NT>& b)
00248 {
00249   int asign = sign(a.num_);
00250   int bsign = sign(b.num_);
00251   
00252   if ((asign == 0) && (bsign == 0)) return EQUAL;
00253   if (asign < bsign) return SMALLER;
00254   if (asign > bsign) return LARGER;
00255 
00256   // now a and b have the same sign
00257   NT ta=a.num_, tb=b.num_;
00258   int d=a.exp_-b.exp_;
00259 
00260   if(d>0)
00261     ta = shift_2(ta,d);
00262   else
00263     tb = shift_2(tb,-d);
00264 
00265   if(ta<tb)
00266     return SMALLER;
00267   else if(tb<ta)
00268     return LARGER;
00269   else 
00270     return EQUAL;
00271 }
00272 //--------------------------------------------------------------------
00273 template < typename NT >
00274 inline
00275 int
00276 compare(const diadic<NT>& x, const diadic<NT>& y)
00277 { return quotient_cmp(x, y); }
00278 //--------------------------------------------------------------------
00279 template < typename NT >
00280 std::ostream&
00281 operator<<(std::ostream& s, const diadic<NT>& r)
00282 {
00283   s << r.numerator();
00284   if(r.valuation()) s<< "*2^(" << r.valuation()<<")";
00285   return s;
00286 }
00287 //--------------------------------------------------------------------
00288 // Arithmetic with diadics
00289 //--------------------------------------------------------------------
00291 template < typename NT >  inline
00292 diadic<NT>
00293 operator+(const diadic<NT>& x, const diadic<NT>& y)
00294 {
00295   diadic<NT> z = x;
00296   return z += y;
00297 }
00298 //--------------------------------------------------------------------
00300 template < typename NT >  inline
00301 diadic<NT>
00302 operator-(const diadic<NT>& x, const diadic<NT>& y)
00303 { return (diadic<NT>(x) -= y); }
00304 
00305 //--------------------------------------------------------------------
00307 template < typename NT >  inline
00308 diadic<NT>
00309 operator*(const diadic<NT>& x, const diadic<NT>& y)
00310 {
00311   diadic<NT> z = x;
00312   return z *= y;
00313 }
00314 //--------------------------------------------------------------------
00316 template < typename NT >  inline
00317 diadic<NT>
00318 operator/(const diadic<NT>& x, const diadic<NT>& y)
00319 {
00320   diadic<NT> z = x;
00321   return z /= y;
00322 }
00323 //--------------------------------------------------------------------
00325 template < typename NT >  inline
00326 diadic<NT>
00327 operator/(const diadic<NT>& x, int d)
00328 {
00329   diadic<NT> z(x);
00330   return z /= d;
00331 }
00332 //--------------------------------------------------------------------
00334 template < typename NT >  inline
00335 diadic<NT>
00336 operator-(const diadic<NT>& x)
00337 { 
00338   return diadic<NT>(-x.num_,x.exp_); 
00339 }
00340 //--------------------------------------------------------------------
00342 template < typename NT >  inline
00343 diadic<NT>
00344 operator+(const NT& x, const diadic<NT>& y)
00345 {
00346   diadic<NT> z(x);
00347   return z += y;
00348 }
00349 //--------------------------------------------------------------------
00351 template < typename NT >  inline
00352 diadic<NT>
00353 operator+(const diadic<NT>& x, const NT& y)
00354 {
00355   diadic<NT> z = x;
00356   return z += y;
00357 }
00358 //--------------------------------------------------------------------
00360 template < typename NT >  inline
00361 diadic<NT>
00362 operator-(const NT& x, const diadic<NT>& y)
00363 {
00364   diadic<NT> z(x);
00365   return z -= y;
00366 }
00367 //--------------------------------------------------------------------
00369 template < typename NT >  inline
00370 diadic<NT>
00371 operator-(const diadic<NT>& x, const NT& y)
00372 {
00373   diadic<NT> z = x;
00374   return z -= y;
00375 }
00376 //--------------------------------------------------------------------
00378 template < typename NT >  inline
00379 diadic<NT>
00380 operator*(const NT& x, const diadic<NT>& y)
00381 {
00382   diadic<NT> z(x);
00383   return z *= y;
00384 }
00385 //--------------------------------------------------------------------
00386 template < typename NT >  inline
00387 diadic<NT>
00388 operator*(const diadic<NT>& x, const NT& y)
00389 {
00390   diadic<NT> z = x;
00391   return z *= y;
00392 }
00393 
00394 //--------------------------------------------------------------------
00395 #ifdef SYNAPS_WITH_GMP
00396 QQ operator*(const diadic<ZZ>& x, const QQ& y)
00397 {
00398   return (y*x.numerator()/shift_2(QQ(1),x.valuation()));
00399 }
00400 //--------------------------------------------------------------------
00401 QQ& operator*=(QQ& y, const diadic<ZZ>& x)
00402 {
00403   y *=x.numerator();
00404   y /=shift_2(QQ(1),x.valuation());
00405   return y;
00406 }
00407 #endif //SYNAPS_WITH_GMP
00408 //--------------------------------------------------------------------
00410 template < typename NT >  inline
00411 diadic<NT>
00412 operator/(const NT& x, const diadic<NT>& y)
00413 {
00414   diadic<NT> z(x) ;
00415   return z /= y;
00416 }
00417 //--------------------------------------------------------------------
00418 template < typename NT >  inline
00419 diadic<NT>
00420 operator/(const diadic<NT>& x, const NT& y)
00421 {
00422   diadic<NT> z = x;
00423   return z /= y;
00424 }
00425 //--------------------------------------------------------------------
00427 template < typename NT >  inline
00428 int
00429 sign(const diadic<NT>& x) 
00430 { 
00431   return  sign(x.num_); 
00432 }
00433 //--------------------------------------------------------------------
00434 // Booleans operations
00435 //--------------------------------------------------------------------
00437 template < typename NT >  inline
00438 bool
00439 operator==(const diadic<NT>& x, const diadic<NT>& y)
00440 { 
00441   return shift_2(x.num_ ,y.exp_) == shift_2(y.num_,x.exp_); 
00442 }
00443 //--------------------------------------------------------------------
00445 template < typename NT >  inline
00446 bool operator==(const diadic<NT>& x, const NT& y)
00447 { return shift_2(y, x.exp_) == x.num_; }
00448 //--------------------------------------------------------------------
00450 template < typename NT >  inline
00451 bool
00452 operator==(const NT& x, const diadic<NT>& y)
00453 { return y == x; }
00454 //--------------------------------------------------------------------
00456 template < typename NT >  inline
00457 bool
00458 operator!=(const diadic<NT>& x, const diadic<NT>& y)
00459 { return ! (x == y); }
00460 //--------------------------------------------------------------------
00462 template < typename NT >  inline
00463 bool
00464 operator!=(const diadic<NT>& x, const NT& y)
00465 { return ! (x == y); }
00466 //--------------------------------------------------------------------
00468 template < typename NT >  inline
00469 bool
00470 operator!=(const NT& x, const diadic<NT>& y)
00471 { return ! (x == y); }
00472 //--------------------------------------------------------------------
00474 template < typename NT >  inline
00475 bool
00476 operator<(const diadic<NT>& x, const diadic<NT>& y)
00477 {
00478   return quotient_cmp(x,y) == SMALLER;
00479 }
00480 //--------------------------------------------------------------------
00482 template < typename NT >  inline
00483 bool
00484 operator<(const diadic<NT>& x, const NT& y)
00485 {
00486   return quotient_cmp(x,diadic<NT>(y)) == SMALLER;
00487 }
00488 //--------------------------------------------------------------------
00490 template < typename NT >  inline
00491 bool
00492 operator<(const NT& x, const diadic<NT>& y)
00493 {
00494   return quotient_cmp(diadic<NT>(x),y) == SMALLER;
00495 }
00496 //--------------------------------------------------------------------
00498 template < typename NT >  inline
00499 bool
00500 operator>(const diadic<NT>& x, const diadic<NT>& y)
00501 { 
00502   return(y < x); 
00503 }
00504 //--------------------------------------------------------------------
00506 template < typename NT >  inline
00507 bool
00508 operator>(const diadic<NT>& x, const NT& y)
00509 { 
00510   return y < x; 
00511 }
00512 //--------------------------------------------------------------------
00514 template < typename NT >  inline
00515 bool
00516 operator>(const NT& x, const diadic<NT>& y)
00517 { return y < x; }
00518 //--------------------------------------------------------------------
00520 template < typename NT >  inline
00521 bool
00522 operator<=(const diadic<NT>& x, const diadic<NT>& y)
00523 { return ! (y < x); }
00524 //--------------------------------------------------------------------
00526 template < typename NT >  inline
00527 bool
00528 operator<=(const diadic<NT>& x, const NT& y)
00529 { return ! (y < x); }
00530 //------------------------------------------------------------------------------------------
00531 template < typename NT >  inline
00532 bool
00533 operator<=(const NT& x, const diadic<NT>& y)
00534 { return ! (y < x); }
00535 //--------------------------------------------------------------------
00537 template < typename NT >  inline
00538 bool
00539 operator>=(const diadic<NT>& x, const diadic<NT>& y)
00540 { return ! (x < y); }
00541 //--------------------------------------------------------------------
00543 template < typename NT >  inline
00544 bool
00545 operator>=(const diadic<NT>& x, const NT& y)
00546 { return ! (x < y); }
00547 //--------------------------------------------------------------------
00549 template < typename NT >  inline
00550 bool
00551 operator>=(const NT& x, const diadic<NT>& y)
00552 { return ! (x < y); }
00553 //-------------------------------------------------------------------
00555 template < typename NT >  inline
00556 NT denominator(const diadic<NT>& q)
00557 { return q.denominator(); }
00558 //--------------------------------------------------------------------
00560 template < typename NT >  inline
00561 const NT&
00562 numerator(const diadic<NT>& q)
00563 { 
00564   return q.numerator(); 
00565 }
00566 //--------------------------------------------------------------------
00567 template<class NT,class X>
00568 bool operator< (const diadic<NT>& d, const X& q)
00569 {
00570   NT r;
00571   if(d.valuation()>=0)
00572     {
00573       r= shift_2(d.numerator(),d.valuation());
00574       return (r<q);
00575     }
00576   else
00577     {
00578       r=NT(q);
00579       r= shift_2(r,-d.valuation());
00580       return (d.numerator()<r);
00581     }
00582 }
00583 //--------------------------------------------------------------------
00584 template<class NT,class X>
00585 bool operator> (const diadic<NT>& d, const X& q)
00586 {
00587   NT r;
00588   if(d.valuation()>=0)
00589     {
00590       r= shift_2(d.numerator(),d.valuation());
00591       return (r>q);
00592     }
00593   else
00594     {
00595       r=NT(q);
00596       r= shift_2(r,-d.valuation());
00597       return (d.numerator()>r);
00598     }
00599 }
00600 //--------------------------------------------------------------------
00601 template<class NT,class X>
00602 bool operator> (const X& q, const diadic<NT>& d)
00603 {
00604   return (d<q);
00605 }
00606 //--------------------------------------------------------------------
00607 template<class NT,class X>
00608 bool operator< (const X& q, const diadic<NT>& d)
00609 {
00610   return (d>q);
00611 }
00612 //--------------------------------------------------------------------
00613 //typedef QQ;
00614 //typedef ZZ;
00615 //--------------------------------------------------------------------
00616 namespace let {
00618   template < typename NT >
00619   double
00620     convert(const diadic<NT>& q, type::As<double> )
00621   {
00622     return (convert(q.numerator(),type::As<double>())/shift_2(1.0,q.valuation()));
00623   }
00625  //  template < typename T, typename S >
00626 //   void assign(T & a, const diadic<S>& x)
00627 //   {
00628 //     a = x.numerator()/x.denominator();
00629 //   }
00630 //   ///
00631 //   template < typename T >
00632 //   void assign(diadic<T>& a, const T& x)
00633 //   {
00634 //      a = diadic<T>(x);
00635 //   }
00636 
00637 #ifdef SYNAPS_WITH_GMP 
00638   void assign(QQ& r, const diadic<ZZ> & x)
00639   {
00640     assign(r,x.numerator());
00641     for(unsigned i=0;i<x.exp_;i++) r/=2;
00642   }
00643 
00644   template<> 
00645   void assign(diadic<ZZ> & x, int n)
00646   {
00647     assign(x.num_,n);
00648     x.exp_=0;
00649     x.normalize();
00650   }
00651 #endif //SYNAPS_WITH_GMP
00652 
00653 }
00654 //--------------------------------------------------------------------
00655 __END_NAMESPACE_SYNAPS
00656 #endif // SYNAPS_ARITHM_DIADIC_H
00657 

SYNAPS DOCUMENTATION
logo