/****************************************************** Sean Heber (sean@fifthace.com) http://www.bigzaphod.org/fibonacci/ September, 2006 License: public domain ******************************************************/ #include #include #include #include #include #include using namespace std; template string to_string( const T& val ) { ostringstream buffer; buffer << val; return buffer.str(); } //#define USE_64BIT_MATH #ifdef USE_64BIT_MATH typedef uint64_t uint_t; typedef uint32_t digit_t; const uint_t BASE = 0xffffffffL; const uint_t STRBASE10 = 1000000000; #else typedef uint32_t uint_t; typedef uint16_t digit_t; const uint_t BASE = 65535; const uint_t STRBASE10 = 10000; #endif class Number { typedef vector dvt; dvt p; bool neg; void zero() { neg = false; p.clear(); } bool is_zero() const { return p.empty() || (p.size() == 1 && p.back() == 0); } void trim( dvt& p ) const { while( !p.empty() && p.back() == 0 ) p.pop_back(); } uint_t add( const dvt& v, dvt& u, const dvt::size_type lsd=0, dvt::size_type len=0 ) const { uint_t k = 0; if( len == 0 ) len = u.size(); for( dvt::size_type j = 0; j < max(v.size(),len); j++ ) { const dvt::size_type uindex = lsd + j; const uint_t d = (uint_t)(j= v.size() ) { // D2 for( dvt::size_type j = m; ; j-- ) { // D3 - calc qh const uint_t t = (uint_t)u[j+n] * BASE + (uint_t)u[j+n-1]; uint_t qh = t / (uint_t)v[n-1]; uint_t rh = t % (uint_t)v[n-1]; rh--; while( (qh == BASE) || ((qh*(uint_t)v[n-2]) > (BASE*rh + (uint_t)u[j+n-2])) ) { qh--; rh += (uint_t)v[n-1]; if( rh > BASE ) continue; break; } // D4 - mult and subtract dvt temp = v; single_mult( temp, qh ); bool wasneg = subtract(temp, u, j, n+1); // D5 q[j] = qh; // D6 if( wasneg ) { q[j]--; add( v, u, j, n+j+1 ); } // D7 if( j == 0 ) break; } } p = q; // D8 - unnormalize Number rem; rem.p.resize( n, 0 ); for( dvt::size_type i=0; i in.p.size()? p: in.p ); const dvt::size_type m = u.size(); const dvt::size_type n = v.size(); w.p.resize( m+n, 0 ); for( dvt::size_type j = 0; j < n; j++ ) { // M6 if( v[j] == 0 ) { // M2 w.p[j+m] = 0; } else { // M3 uint_t k = 0; for( dvt::size_type i = 0; i < m; i++ ) { // M4 const uint_t t = (uint_t)u[i] * (uint_t)v[j] + (uint_t)w.p[i+j] + k; k = t / BASE; w.p[i+j] = t % BASE; } w.p[j+m] = k; } } trim(w.p); } return w; } Number& operator/=( const Number& n ) { div(n); return *this; } Number operator/( const Number& n ) const { Number a = *this; a.div(n); return a; } Number& operator%=( const Number& n ) { return (*this = *this % n); } Number operator%( const Number& n ) const { Number a = *this; return a.div(n); } operator bool() const { return is_zero(); } operator string() const { return str(); } string str() const { if( is_zero() ) return "0"; string str; dvt c = p; const string::size_type digits = to_string( STRBASE10 ).length() - 1; while( !c.empty() ) { string r = to_string( single_div(c,STRBASE10) ); trim( c ); if( !c.empty() ) { for( string::size_type z=0; z