synaps/arithm/BigUnsigned.h

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

SYNAPS DOCUMENTATION
logo