realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/scalar_bigunsigned.hpp
Go to the documentation of this file.
00001 #ifndef realroot_BIG_UNSIGNED_H
00002 #define realroot_BIG_UNSIGNED_H
00003 
00004 #include <assert.h>
00005 #include <ostream>
00006 #include <realroot/numerics_hdwi.hpp>
00007 
00008 namespace mmx {
00009 
00010 template <unsigned N>
00011 struct bigunsigned
00012 {
00013   typedef unsigned hi; 
00014   typedef unsigned hdwi_t;
00015   static bool s_overflow;
00016   
00017   hi data[N];    
00018   bigunsigned(){};
00019   
00020   bigunsigned( unsigned n )
00021   {
00022     data[0] = n;
00023     for (unsigned  i = 1; i < N; data[i] = 0, i ++ ) ;
00024   };
00025   
00026   bigunsigned& operator=( unsigned n ) 
00027   { 
00028     new (this) bigunsigned(n); return *this;
00029   };
00030   
00031   bigunsigned& operator=( const bigunsigned& b ) 
00032   { 
00033     new (this) bigunsigned(b);  return *this;
00034   };
00035   
00036   inline bool operator<( const bigunsigned<N>& bi )
00037   {
00038     for ( int i = N-1; i >= 0; i ++ )
00039       if ( bi[i] > data[i] ) return true;
00040     return false;
00041   };
00042   
00043   inline bool operator>( const bigunsigned<N>& bi )
00044   {
00045     for ( int i = N-1; i >= 0; i ++ )
00046       if ( bi[i] < data[i] ) return true;
00047     return false;
00048   };
00049   
00050   inline bool operator==( const bigunsigned<N>& bi )
00051   {
00052     for (unsigned i = 0; i < N; i ++ )
00053       if ( data[i] != bi[i] ) return false;
00054     return true;
00055   };
00056   
00057   inline bigunsigned& operator<<=( unsigned n )
00058   {
00059     if ( n >= numerics::hdwi<hi>::nbit )
00060       {
00061         do
00062           {
00063             for ( unsigned i = N-1; i > 0; i -- )
00064               data[i]  = data[i-1];
00065             data[0] = 0;
00066             n -= numerics::hdwi<hi>::nbit;
00067           }
00068         while ( n >= numerics::hdwi<hi>::nbit );
00069       };
00070     if ( n )
00071       {
00072         data[N-1] <<= n;
00073         for ( int i = N-1; i > 0; i -- )
00074           {
00075             data[i] |= (data[i-1]>>(numerics::hdwi<hi>::nbit-n));
00076             data[i-1] <<= n;
00077           };
00078       };
00079     return *this;
00080   };
00081   
00082   inline bigunsigned& operator>>=( unsigned n )
00083   {
00084     if ( n >= numerics::hdwi<hi>::nbit )
00085       {
00086         do 
00087           {
00088             for ( unsigned i = 0; i < N-1; data[i] = data[i+1], i ++ ) ;
00089             data[N-1] = 0;
00090             n -= numerics::hdwi<hi>::nbit;
00091           }
00092         while ( n >= numerics::hdwi<hi>::nbit );
00093       };
00094     
00095     if ( n )
00096       {
00097         data[0] >>= n; 
00098         for ( int i = 0; i < int(N-1); i ++ )
00099           {
00100             data[i] |= (data[i+1]<<(numerics::hdwi<hi>::nbit-n));
00101             data[i+1] >>= n;
00102           };
00103       };
00104     return *this;
00105   };
00106   
00107   inline bigunsigned& operator|=( unsigned n ) 
00108   { 
00109     data[0] |= n; 
00110     return *this; 
00111   };
00112   
00113   inline bigunsigned& operator|=( const bigunsigned& bu )
00114   {
00115     for ( unsigned i = 0; i < N; data[i] |= bu[i], i ++ ) ;
00116     return *this;
00117   };
00118   
00119   inline       bigunsigned<N-1>& next() 
00120   { 
00121     return *((bigunsigned<N-1>*)(this->data+1)); 
00122   };
00123   
00124   inline const bigunsigned<N-1>& next()  const 
00125   { 
00126     return *((const bigunsigned<N-1>*)(this->data+1)); 
00127   };
00128   
00129   inline bigunsigned& operator+=( unsigned n )           
00130   { 
00131     add(*this,n); 
00132     return *this; 
00133   };
00134   
00135   inline bigunsigned& operator+=( const bigunsigned& a ) 
00136   { 
00137     add(*this,a); 
00138     return *this;
00139   };
00140   
00141   unsigned& operator[]( int i )       
00142   { 
00143     return data[i]; 
00144   };
00145   
00146   unsigned  operator[]( int i ) const 
00147   { 
00148     return data[i]; 
00149   };
00150 
00151 };
00152 
00153 template<unsigned N>
00154 bigunsigned<N> operator<<( const bigunsigned<N>& b, unsigned n )
00155 {
00156   bigunsigned<N> tmp = b;
00157   tmp <<= n;
00158   return tmp;
00159 };
00160 
00161 template<unsigned N>
00162 bigunsigned<N> operator|( const bigunsigned<N>& b, unsigned n )
00163 {
00164   bigunsigned<N> tmp = b;
00165   tmp <<= n;
00166   return tmp;
00167 };
00168 
00169 template<unsigned N> inline
00170 bigunsigned<N> operator+( const bigunsigned<N>& b, unsigned n )
00171 {
00172   bigunsigned<N> tmp;
00173   tmp = b;
00174   add(tmp,n);
00175   return tmp;
00176 };
00177 template<unsigned N>
00178 unsigned operator&( const bigunsigned<N>& b, unsigned n )
00179 {
00180   return b[0] & n;
00181 };
00182 
00183 template< unsigned N> bool bigunsigned<N>::s_overflow = false;
00184 
00185 template<unsigned N> inline
00186 void add( bigunsigned<N>& r, typename bigunsigned<N>::hdwi_t n  )
00187 {
00188   typedef typename bigunsigned<N>::hdwi_t hdwi_t;
00189   unsigned i = 0;
00190   while ( n )
00191     {
00192       hdwi_t delta = numerics::hdwi<hdwi_t>::nmax - r[i];
00193       if ( delta < n ) 
00194         { 
00195           r[i] += n; 
00196           n -= r[i]; 
00197         }
00198       else
00199         {
00200           r[i] += n;
00201           n     = 0;
00202           break;
00203         };
00204       i = i + 1;
00205       if ( i == N ) break;
00206     };
00207   
00208   bigunsigned<N>::s_overflow = (n != 0);
00209   
00210 };
00211 
00212 inline void add( bigunsigned<1>& r, const bigunsigned<1>& a ) { add(r,a[0]); };
00213 
00214 template <unsigned N> inline
00215 void add( bigunsigned<N>& r, const bigunsigned<N>& a )
00216 {
00217   add(r,a[0]);
00218   if ( ! bigunsigned<N>::s_overflow ) 
00219     {
00220       add(r.next(),a.next());
00221       if (  bigunsigned<N-1>::s_overflow ) 
00222         {
00223           bigunsigned<N>::s_overflow   = true;
00224           bigunsigned<N-1>::s_overflow = false;
00225         };
00226     };
00227 };
00228 
00229 template <unsigned N> 
00230 void reverse( bigunsigned<N>& r, const bigunsigned<N>& lu )
00231 {
00232   typedef typename bigunsigned<N>::hdwi_t hdwi_t;
00233   for ( unsigned i = 0; i < N/2; i ++ )
00234     {
00235       r[i] = numerics::hdwi<hdwi_t>::reverse(lu[N-1-i]);
00236       r[N-1-i] = numerics::hdwi<hdwi_t>::reverse(lu[i]);
00237     };
00238   if ( N & 1 ) r[N/2] = numerics::hdwi<hdwi_t>::reverse(lu[N/2]);
00239 };
00240 
00241 inline void rprint( std::ostream& o, unsigned n )
00242 {
00243   for ( unsigned b = 0; b < numerics::hdwi<unsigned>::nbit; b ++ )
00244     {
00245         o << ( n& 1);
00246         n >>= 1;
00247     };
00248 };
00249 
00250 template< unsigned N >
00251 void rprint( std::ostream& o, bigunsigned<N>& bu )
00252 {
00253   for ( unsigned i = 0; i < N; i ++ )
00254     rprint(o,bu[i]);
00255 };
00256 
00257 template< unsigned N >
00258 void print ( std::ostream& o, const bigunsigned<N>& bi )
00259 {
00260   bigunsigned<N> tmp;
00261   reverse(tmp,bi);
00262   rprint(o,tmp);
00263   
00264 };
00265 
00266 template<unsigned N>
00267 std::ostream& operator<<( std::ostream& o, const bigunsigned<N>& bi )
00268 {
00269   print(o,bi);
00270   return o;
00271 };
00272 
00273 } //namespace mmx
00274 
00275 #endif