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 }
00274
00275 #endif