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