diff --git a/expansion.cpp b/expansion.cpp index 0302c75a..54ecb566 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -15,164 +15,6 @@ int subtype(cell *c) { return patterns::getpatterninfo(c, patterns::PAT_NONE, 0).id; } -#if HDR -struct bignum { - static const int BASE = 1000000000; - static const long long BASE2 = BASE * (long long)BASE; - vector digits; - bignum() {} - bignum(int i) : digits() { digits.push_back(i); } - void be(int i) { digits.resize(1); digits[0] = i; } - bignum& operator +=(const bignum& b); - void addmul(const bignum& b, int factor); - string get_str(int max_length); - - bool operator < (const bignum&) const; - - ld leading() const { - switch(isize(digits)) { - case 0: - return 0; - case 1: - return digits.back(); - default: - return digits.back() + ld(digits[isize(digits)-2]) / BASE; - } - } - - ld approx() const { - return leading() * pow(BASE, isize(digits) - 1); - } - - ld log_approx() const { - return log(leading()) * log(BASE) * (isize(digits) - 1); - } - - ld operator / (const bignum& b) const { - return leading() / b.leading() * pow(BASE, isize(digits) - isize(b.digits)); - } - - int approx_int() const { - if(isize(digits) > 1) return BASE; - if(digits.empty()) return 0; - return digits[0]; - } - - long long approx_ll() const { - if(isize(digits) > 2) return BASE2; - if(digits.empty()) return 0; - if(isize(digits) == 1) return digits[0]; - return digits[0] + digits[1] * (long long) BASE; - } - - friend inline bignum operator +(bignum a, const bignum& b) { a.addmul(b, 1); return a; } - friend inline bignum operator -(bignum a, const bignum& b) { a.addmul(b, -1); return a; } - }; -#endif - -bignum& bignum::operator +=(const bignum& b) { - int K = isize(b.digits); - if(K > isize(digits)) digits.resize(K); - int carry = 0; - for(int i=0; i= isize(digits)) digits.push_back(0); - digits[i] += carry; - if(i < K) digits[i] += b.digits[i]; - if(digits[i] >= BASE) { - digits[i] -= BASE; - carry = 1; - } - else carry = 0; - } - return *this; - } - -bool bignum::operator < (const bignum& b) const { - if(isize(digits) != isize(b.digits)) - return isize(digits) < isize(b.digits); - for(int i = isize(digits)-1; i>=0; i--) - if(digits[i] != b.digits[i]) - return digits[i] < b.digits[i]; - return false; - } - -void bignum::addmul(const bignum& b, int factor) { - int K = isize(b.digits); - if(K > isize(digits)) digits.resize(K); - int carry = 0; - for(int i=0; i 0 || carry < -1) || (carry == -1 && i < isize(digits)); i++) { - if(i >= isize(digits)) digits.push_back(0); - long long l = digits[i]; - l += carry; - if(i < K) l += b.digits[i] * factor; - carry = 0; - if(l >= BASE) carry = l / BASE; - if(l < 0) carry = -(BASE-1-l) / BASE; - l -= carry * BASE; - digits[i] = l; - } - if(carry < 0) digits.back() -= BASE; - while(isize(digits) && digits.back() == 0) digits.pop_back(); - } - -EX bignum hrand(bignum b) { - bignum res; - int d = isize(b.digits); - while(true) { - res.digits.resize(d); - for(int i=0; i=0; i--) { - if(isize(ret) > max_length && i) { - ret += XLAT(" (%1 more digits)", its(9 * (i+1))); - return ret; - } - - ret += " "; - string val = its(digits[i]); - while(isize(val) < 9) val = "0" + val; - ret += val; - } - return ret; - } - void canonicize(vector& t) { for(int i=2; i digits; + bignum() {} + bignum(int i) : digits() { digits.push_back(i); } + void be(int i) { digits.resize(1); digits[0] = i; } + bignum& operator +=(const bignum& b); + void addmul(const bignum& b, int factor); + string get_str(int max_length) const; + + bool operator < (const bignum&) const; + + ld leading() const { + switch(isize(digits)) { + case 0: + return 0; + case 1: + return digits.back(); + default: + return digits.back() + ld(digits[isize(digits)-2]) / BASE; + } + } + + ld approx() const { + return leading() * pow(BASE, isize(digits) - 1); + } + + ld log_approx() const { + return log(leading()) * log(BASE) * (isize(digits) - 1); + } + + ld approx_div(const bignum& b) const { + return leading() / b.leading() * pow(BASE, isize(digits) - isize(b.digits)); + } + + int approx_int() const { + if(isize(digits) > 1) return BASE; + if(digits.empty()) return 0; + return digits[0]; + } + + bool nonzero() { return approx_ld() != 0; } + + bignum randomized_div(int x) const; + + ld approx_ld() const { + ld res = 0; + for(int i=0; i 2) return BASE2; + if(digits.empty()) return 0; + if(isize(digits) == 1) return digits[0]; + return digits[0] + digits[1] * (long long) BASE; + } + + friend inline bignum operator +(bignum a, const bignum& b) { a.addmul(b, 1); return a; } + friend inline bignum operator -(bignum a, const bignum& b) { a.addmul(b, -1); return a; } + }; +#endif + +bignum& bignum::operator +=(const bignum& b) { + int K = isize(b.digits); + if(K > isize(digits)) digits.resize(K); + int carry = 0; + for(int i=0; i= isize(digits)) digits.push_back(0); + digits[i] += carry; + if(i < K) digits[i] += b.digits[i]; + if(digits[i] >= BASE) { + digits[i] -= BASE; + carry = 1; + } + else carry = 0; + } + return *this; + } + +bool bignum::operator < (const bignum& b) const { + if(isize(digits) != isize(b.digits)) + return isize(digits) < isize(b.digits); + for(int i = isize(digits)-1; i>=0; i--) + if(digits[i] != b.digits[i]) + return digits[i] < b.digits[i]; + return false; + } + +bignum bignum::randomized_div(int x) const { + bignum res = self; + long long carry = 0; + int K = isize(res.digits); + for(int i=K-1; i>=0; i--) { + carry *= BASE; + carry += digits[i]; + tie(carry, res.digits[i]) = make_pair(carry % x, carry / x); + } + while(isize(res.digits) && res.digits.back() == 0) res.digits.pop_back(); + if(rand() % x < carry) res += 1; + println(hlog, get_str(100), " / ", x, " = ", res.get_str(100)); + return res; + } + +void bignum::addmul(const bignum& b, int factor) { + int K = isize(b.digits); + if(K > isize(digits)) digits.resize(K); + int carry = 0; + for(int i=0; i 0 || carry < -1) || (carry == -1 && i < isize(digits)); i++) { + if(i >= isize(digits)) digits.push_back(0); + long long l = digits[i]; + l += carry; + if(i < K) l += b.digits[i] * factor; + carry = 0; + if(l >= BASE) carry = l / BASE; + if(l < 0) carry = -(BASE-1-l) / BASE; + l -= carry * BASE; + digits[i] = l; + } + if(carry < 0) digits.back() -= BASE; + while(isize(digits) && digits.back() == 0) digits.pop_back(); + } + +EX bignum hrand(bignum b) { + bignum res; + int d = isize(b.digits); + while(true) { + res.digits.resize(d); + for(int i=0; i=0; i--) { + if(isize(ret) > max_length && i) { + ret += XLAT(" (%1 more digits)", its(9 * (i+1))); + return ret; + } + + ret += " "; + string val = its(digits[i]); + while(isize(val) < 9) val = "0" + val; + ret += val; + } + return ret; + } + }