test.cpp
#include "BigInt.h"
#include <iostream>
using namespace std;
typedef unsigned int uint;
BigInt fib(uint i){
BigInt a(0);
BigInt b(1);
for(uint j = 1; j < i; j++){
BigInt temp(a);
a = b;
b += temp;
}
return b;
}
void main(){
vector<uint> v;
v.push_back(0x0);
v.push_back(0xf);
BigInt s(v);
s /= 100;
BigInt f = fib(1000);
vector<uint> digits;
while(BigInt(0) < f){
BigInt d(f);
digits.push_back(d %= 10);
f /= 10;
}
for(uint i = digits.size(); i > 0; i--)
cout << digits[i-1];
cout << endl;
}
BigInt.h
#include <vector>
struct BigInt{
typedef unsigned int uint;
static uint const UINT_BITS = sizeof(uint) * CHAR_BIT;
static uint const HALF_LO = UINT_MAX >> (UINT_BITS/2);
static uint const HALF_HI = UINT_MAX << (UINT_BITS/2);
BigInt ();
BigInt (uint);
BigInt (std::vector<uint>);
operator uint() const;
BigInt & operator +=(BigInt const & other);
BigInt & operator -=(BigInt const & other);
BigInt & operator ++();
BigInt & operator --();
BigInt & operator ++(int);
BigInt & operator --(int);
BigInt & operator *=(BigInt const & other);
BigInt & operator /=(BigInt const & other);
BigInt & operator <<=(uint bits);
BigInt & operator >>=(uint bits);
BigInt & operator %=(BigInt const & other);
BigInt & complement();
bool operator <(BigInt const & other) const;
bool operator >(BigInt const & other) const;
bool operator !=(BigInt const & other) const;
bool operator ==(BigInt const & other) const;
bool operator >=(BigInt const & other) const;
bool operator <=(BigInt const & other) const;
private:
std::vector<uint> words;
BigInt & multiplyHalf(uint half, uint dbl_offset = 0);
BigInt & addWord(uint word, uint offset = 0);
BigInt & addHalf(uint half, uint dbl_offset = 0);
BigInt & addWordDblOff(uint word, uint dbl_off = 0);
uint getHalf(uint dbl_off = 0) const;
BigInt & clean();
};
BigInt.cpp
#include "BigInt.h"
#include <assert.h>
#include <climits>
using namespace std;
BigInt::BigInt() : words(1) {}
BigInt::BigInt(uint u) : words(1, u) {}
BigInt::BigInt(vector<uint> v) : words(v){
clean();
}
BigInt::operator uint() const{
return words[0];
}
BigInt & BigInt::operator +=(BigInt const & _src){
BigInt other(_src);
uint maxsize = max(words.size(), other.words.size());
words.resize(maxsize);
other.words.resize(maxsize);
bool carry = false;
for(uint i = 0; i < maxsize; i++){
uint a = words[i];
uint b = other.words[i];
if(carry){
if(a != UINT_MAX)
a++;
else if(b != UINT_MAX)
b++;
else{
words[i] = a;
carry = true;
continue;
}
}
carry = UINT_MAX - a < b;
words[i] = a + b;
}
if(carry)
words.push_back(0x1);
return *this;
}
BigInt & BigInt::operator *=(BigInt const & _src){
uint dblsize = _src.words.size() * 2;
BigInt orig(*this);
words.clear();
words.push_back(0);
for(uint i = 0; i < dblsize; i++){
BigInt cpy(orig);
uint half = _src.getHalf(i);
cpy.multiplyHalf(half, i);
(*this) += cpy;
}
return *this;
}
BigInt & BigInt::multiplyHalf(uint half, uint offset){
uint dblsize = words.size()*2;
uint maxdbloff = offset + dblsize;
BigInt orig(*this);
words.clear();
words.resize(maxdbloff/2+1);
for(uint i = 0; i < dblsize; i++){
uint other = orig.getHalf(i);
addWordDblOff(other * half, offset + i);
}
if(words[words.size()-1]==0)
words.pop_back();
return *this;
}
BigInt & BigInt::addWord(uint word, uint index){
bool carry = UINT_MAX - word < words[index];
words[index] += word;
index++;
if(carry){
if(index<words.size())
addWord(1, index);
else
words.push_back(1);
}
return *this;
}
BigInt & BigInt::addHalf(uint half, uint offset){
half &= HALF_LO;
if(offset%2 == 0)
addWord(half, offset / 2);
else
addWord(half << (UINT_BITS/2), offset / 2);
return *this;
}
BigInt & BigInt::addWordDblOff(uint word, uint offset){
addHalf(word & HALF_LO, offset);
addHalf((word & HALF_HI) >> (UINT_BITS/2), offset + 1);
return *this;
}
BigInt::uint BigInt::getHalf(uint offset) const{
uint word = words[offset/2];
if(offset%2 == 0)
return word & HALF_LO;
else
return (word & HALF_HI) >> (UINT_BITS/2);
}
BigInt & BigInt::complement(){
uint size = words.size();
for(uint i = 0; i < size; i++)
words[i] = ~words[i];
return *this;
}
bool BigInt::operator <(BigInt const & other) const{
if(words.size() < other.words.size())
return true;
else if(words.size() > other.words.size())
return false;
BigInt cpy(other);
uint size = words.size();
for(uint i = size; i > 0; i--){
if(words[i-1] < other.words[i-1])
return true;
else if(words[i-1] > other.words[i-1])
return false;
}
return false;
}
BigInt & BigInt::operator -=(BigInt const & other){
BigInt cpy(other);
uint size = std::max(words.size(), other.words.size());
cpy.words.resize(size);
cpy.complement().addWord(1, 0);
*this += cpy;
words.resize(size);
clean();
return (*this);
}
BigInt & BigInt::operator <<=(uint bits){
vector<uint> result(bits/UINT_BITS, 0);
uint remain = bits % UINT_BITS;
uint prev = 0;
uint up_mask = ~(UINT_MAX >> remain);
uint shift_down = UINT_BITS - remain;
words.push_back(0);
for(uint i = 0; i < words.size(); i++){
uint curr = (words[i] & up_mask) >> shift_down;
words[i] <<= remain;
words[i] |= prev;
prev = curr;
}
result.insert(result.end(), words.begin(), words.end());
words = result;
clean();
return *this;
}
BigInt & BigInt::operator >>=(uint bits){
vector<uint> result(words.begin() + bits/UINT_BITS, words.end());
uint prev = 0;
uint remain = bits % UINT_BITS;
uint dn_mask = ~(UINT_MAX << remain);
uint shift_up = UINT_BITS - remain;
for(uint i = result.size(); i > 0; i--){
uint curr = (result[i-1] & dn_mask) << shift_up;
result[i-1] >>= remain;
result[i-1] |= prev;
prev = curr;
}
words = result;
clean();
return *this;
}
BigInt & BigInt::operator /=(BigInt const & other){
uint minsize = std::min(this->words.size(), other.words.size());
uint i = 0;
while(i < minsize && this->words[i]==0 && other.words[i] == 0)
i++;
BigInt n;
BigInt d;
n.words = vector<uint>(this->words.begin()+i, this->words.end());
d.words = vector<uint>(other.words.begin()+i, other.words.end());
BigInt accum;
while(d < n){
uint n_last = *(n.words.end()-1);
uint d_last = *(d.words.end()-1);
uint bits = (n.words.size() - d.words.size()) * UINT_BITS;
if(d.words.size()>1){
if(d_last == UINT_MAX){
d_last = 1;
bits -= UINT_BITS;
}
else
d_last++;
}
while(n_last / d_last == 0){
d_last >>= 1;
bits--;
}
uint div_small = BigInt(n_last / d_last);
BigInt div = BigInt(div_small);
div <<= bits;
BigInt mult = d;
mult *= div;
while(n < mult){
div >>= 1;
mult = d;
mult *= div;
}
accum += div;
n -= mult;
}
words = accum.words;
return *this;
}
BigInt & BigInt::operator %=(BigInt const & other){
BigInt orig(*this);
orig /= other;
orig *= other;
return (*this) -= orig;
}
BigInt & BigInt::clean(){
vector<uint>::iterator itr = words.end();
while(itr != words.begin() && *(itr-1) == 0)
itr--;
words.erase(itr, words.end());
if(words.size()==0)
words.push_back(0);
return *this;
}