#include #include #include #include #include "bigint.h" #include "numalgo.h" using namespace std; Bigint Bigint::mone(-1); Bigint Bigint::zero(0); Bigint Bigint::one(1); Bigint Bigint::two(2); Bigint::Bigint() :sign(1){} Bigint::Bigint(slongdigit_t v) :digits(1,abs(v)),sign(v>=0?1:-1){ static_assert(sizeof(longdigit_t)==2*sizeof(digit_t), "longdigit_t should be twice as large as digit_t"); v=abs(v); if(v>digits[0])digits.push_back(v>>digit_bits); else if(v==0){ digits.clear(); sign=1; } checkconsistent(); } Bigint::Bigint(longdigit_t v) :digits(1,(digit_t)v),sign(1){ if(v>digits[0])digits.push_back(v>>digit_bits); else if(v==0)digits.clear(); checkconsistent(); } Bigint::Bigint(sdigit_t v) :digits(1,abs(v)),sign(v>=0?1:-1){ if(v==0){ digits.clear(); sign=1; } checkconsistent(); } Bigint::Bigint(digit_t v) :digits(1,v),sign(1){ if(v==0)digits.clear(); checkconsistent(); } void Bigint::add(Bigint &a,const Bigint &b){ if(a.digits.size()=((longdigit_t)1<>digit_bits; } if(carry)a.digits.push_back(1); a.normalise(); a.checkconsistent(); } void Bigint::subtract(Bigint &a,const Bigint &b){ if(a.digits.size()=b.digits.size()); if(a.digits.size()==0){ a.checkconsistent(); return; } assert(a.digits.size()>0); int sz=a.digits.size(); int carry=0; for(int i=0;i=(int)b.digits.size()&&!carry)break; digit_t adig=a.digits[i]; digit_t bdig=i<(int)b.digits.size()?b.digits[i]:0; digit_t res=adig-(bdig+carry); // cerr<<"carry="<>digit_bits; // cerr<<"carry="<>digit_bits; // cerr<<"(2) carry="<=0?1:-1; v*=sign; digits[0]=v; if(v>digits[0])digits.push_back(v>>digit_bits); checkconsistent(); return *this; } Bigint& Bigint::operator=(longdigit_t v){ digits.clear(); if(v!=0){ digits.push_back((digit_t)v); if(v>digits[0])digits.push_back(v>>digit_bits); } checkconsistent(); return *this; } Bigint& Bigint::operator=(sdigit_t v){ digits.clear(); if(v==0)sign=1; else { sign=v>=0?1:-1; v*=sign; digits.push_back(v); } checkconsistent(); return *this; } Bigint& Bigint::operator=(digit_t v){ digits.clear(); sign=1; if(v!=0)digits.push_back(v); checkconsistent(); return *this; } Bigint& Bigint::operator+=(const Bigint &o){ if(&o==this){ //*this + *this operator<<=(1); return *this; } if(sign==1){ if(o.sign==1)add(*this,o); else subtract(*this,o); } else { if(o.sign==1)subtract(*this,o); else add(*this,o); } checkconsistent(); return *this; } Bigint& Bigint::operator-=(const Bigint &o){ if(&o==this){ // *this - *this sign=1; digits.clear(); return *this; } if(sign==1){ if(o.sign==1)subtract(*this,o); else add(*this,o); } else { if(o.sign==1)add(*this,o); else subtract(*this,o); } checkconsistent(); return *this; } Bigint& Bigint::operator*=(const Bigint &o){ *this=product(*this,o); checkconsistent(); return *this; } //TODO: optimise these functions Bigint& Bigint::operator+=(slongdigit_t n){return *this+=Bigint(n);} Bigint& Bigint::operator-=(slongdigit_t n){return *this-=Bigint(n);} Bigint& Bigint::operator*=(slongdigit_t n){return *this*=Bigint(n);} Bigint& Bigint::operator<<=(int sh){ if(sh==0)return *this; if(digits.size()==0)return *this; if(sh<0)return *this>>=-sh; if(sh/digit_bits>0){ digits.insert(digits.begin(),sh/digit_bits,0); sh%=digit_bits; if(sh==0){ checkconsistent(); return *this; } } digits.push_back(0); for(int i=digits.size()-2;i>=0;i--){ digits[i+1]|=digits[i]>>(digit_bits-sh); digits[i]<<=sh; } shrink(); normalise(); checkconsistent(); return *this; } Bigint& Bigint::operator>>=(int sh){ if(sh==0)return *this; if(digits.size()==0)return *this; if(sh<0)return *this<<=-sh; if(sh/digit_bits>0){ if(sh/digit_bits>=(int)digits.size()){ digits.clear(); sign=1; checkconsistent(); return *this; } digits.erase(digits.begin(),digits.begin()+sh/digit_bits); sh%=digit_bits; if(sh==0){ checkconsistent(); return *this; } } digits[0]>>=sh; int sz=digits.size(); for(int i=1;i>=sh; } shrink(); normalise(); checkconsistent(); return *this; } Bigint& Bigint::negate(){ sign=-sign; return *this; } Bigint Bigint::operator+(const Bigint &o) const { return Bigint(*this)+=o; } Bigint Bigint::operator-(const Bigint &o) const { return Bigint(*this)-=o; } Bigint Bigint::operator*(const Bigint &o) const { return product(*this,o); } //TODO: optimise these functions Bigint Bigint::operator+(slongdigit_t n) const {return *this+Bigint(n);} Bigint Bigint::operator-(slongdigit_t n) const {return *this-Bigint(n);} Bigint Bigint::operator*(slongdigit_t n) const {return *this*Bigint(n);} Bigint Bigint::operator<<(int sh) const { return Bigint(*this)<<=sh; } Bigint Bigint::operator>>(int sh) const { return Bigint(*this)>>=sh; } int depthrecord; pair Bigint::divmod(const Bigint &div) const { pair res=divmod(div,1); //cerr< "< Bigint::divmod(const Bigint &div,int depth) const { if(depth>100)assert(false); //cerr<<"divmod("<=0;i--){ os< outbuf; while(b!=0){ pair dm=b.divmod(div); b=dm.first; Bigint::longdigit_t val=0; assert(dm.second.digits.size()<=2); if(dm.second.digits.size()>=2) val+=((Bigint::longdigit_t)1<=1) val+=dm.second.digits[0]; outbuf.push_back(val); } for(int i=outbuf.size()-1;i>=0;i--){ (i==(int)outbuf.size()-1?os:os<