realroot_doc 0.1.1
|
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