bignum bignum_popzeroes(bignum& c) { if (c.size() > 1) { while (c.size() > 1 && c.back() == 0) c.pop_back(); } return c; }
void bignum_print(ostream& print, bignum& c) { c = bignum_popzeroes(c); cout << c.back(); if (c.size() - 2 >= 0) { for (unsigned int i = c.size()-2; i + 1 > 0; i--) cout << setfill('0') << setw(3) << c[i]; } }
bignum bignum_subtract(bignum& a, bignum& b) { bignum c; if (b.size() > a.size()) c.push_back(0); else if (a.size() == b.size() && b.back() > a.back()) c.push_back(0); else { int k; for (unsigned int i = 0; i < a.size() + b.size(); i++) { k = 0; if (i < a.size()) k += a[i]; if (i < b.size()) k -= b[i]; c.push_back(k); } for (unsigned int i = 0; i < c.size() - 1; i++) { while (c[i] < 0) { c[i + 1] -= 1; c[i] += BASE; } } } c = bignum_popzeroes(c); return c; }
bignum bignum_multiply(bignum& a, bignum& b) { bignum c(a.size() + b.size() + 1); for (unsigned int i = 0; i < a.size(); i++) { for (unsigned int j = 0; j < b.size(); j++) { c[i + j] += a[i] * b[j]; } c = bignum_carry(c); } c = bignum_popzeroes(c); return c; }
bool operator<(const bignum& a, const bignum& b) { if (a.sign and !b.sign) return true; if (!a.sign and b.sign) return false; // same sign if (a.size() != b.size()) // a is shorter XOR a is negative return (a.size() < b.size()) != a.sign; // also same length pair<b_crit, b_crit> m = mismatch(a.rbegin(), a.rend(), b.rbegin()); if (m.first == a.rend()) return false; // a == b return (*m.first < *m.second) != a.sign; }
bignum operator*(const bignum& a, const bignum& b) { if (a.empty() or b.empty()) return bignum(); if (a.size() + b.size() < 19) { long long x = a; long long y = b; return x*y; } const unsigned n = max(a.size(), b.size()); const unsigned h = n/2; bignum w, x; // a = 10^h * w + x bignum y, z; // b = 10^h * y + z b_cit ha, hb; ha = (h > a.size()) ? a.end() : a.begin()+h; hb = (h > b.size()) ? b.end() : b.begin()+h; x.assign(a.begin(), ha); w.assign(ha, a.end()); x.clean(); w.clean(); z.assign(b.begin(), hb); y.assign(hb, b.end()); z.clean(); y.clean(); bignum p = w*y; bignum q = x*z; bignum r = (w+x) * (y+z); // result = 10^(2*h) * p + 10^h * (r-p-q) + q bignum result; result.resize(a.size() + b.size()); fill(result.begin(), result.begin()+2*h, 0); copy(p.begin(), p.end(), result.begin() + 2*h); result.clean(); r -= p+q; // p = 10^h * r p.resize(r.size() + h); fill(p.begin(), p.begin()+h, 0); copy(r.begin(), r.end(), p.begin()+h); p.clean(); result += q; result += p; result.sign = a.sign != b.sign; return result; }
// a += b, ignoring signal void add_inplace(bignum& a, const bignum& b) { a.resize( 1 + max(a.size(), b.size()) ); b_it i; b_cit j; Digit carry = 0; for (i=a.begin(), j=b.begin(); i!=a.end(); ++i) { *i += (j!=b.end() ? *j++ : 0) + carry; if (*i >= bignum::base) { *i -= bignum::base; carry = 1; } else carry = 0; } assert(carry == 0); a.clean(); }
bool bignum::operator<(bignum a) { if(this->sign() != a.sign()) { if(this->sign()=='-') return true; else return false; } if(this->size()>a.size()) return false; if(this->size()<a.size()) return true; for(int i=0;i<a.size();i++) { if(this->x.num[i]<a.x.num[i]) return true; } return false; }
bignum bignum_add(bignum& a, bignum& b) { bignum c; int k; for (unsigned int i = 0; i < a.size() + b.size(); i++) { k = 0; if (i < a.size()) k += a[i]; if (i < b.size()) k += b[i]; c.push_back(k); } c = bignum_carry(c); c = bignum_popzeroes(c); return c; }
bignum bignum_carry(bignum& c) { for (unsigned int i = 0; i < c.size() - 1; i++) { if (c[i] >= BASE) { c[i + 1] += c[i] / BASE; c[i] = c[i] % BASE; } } return c; }
bool operator==(const bignum& a, const bignum& b) { return a.sign == b.sign and a.size() == b.size() and equal(a.begin(), a.end(), b.begin()); }