|
@@ -55,31 +55,44 @@ struct BigInt{
|
|
|
inline BigInt(InputIterator begin, InputIterator end) : data(begin, end), signum(1){}
|
|
|
template<typename RNG>
|
|
|
inline BigInt(RNG& rng, size_t length) : data(length, 0), signum(1){std::generate(data.begin(),data.end(), [&rng](){return rng();});}
|
|
|
- std::deque<uint64_t>::iterator begin(){return data.begin();}
|
|
|
- std::deque<uint64_t>::iterator end(){return data.end();}
|
|
|
- std::deque<uint64_t>::reverse_iterator rbegin(){return data.rbegin();}
|
|
|
- std::deque<uint64_t>::reverse_iterator rend(){return data.rend();}
|
|
|
- std::deque<uint64_t>::const_iterator begin()const{return data.begin();}
|
|
|
- std::deque<uint64_t>::const_iterator end()const{return data.end();}
|
|
|
- std::deque<uint64_t>::const_reverse_iterator rbegin()const{return data.rbegin();}
|
|
|
- std::deque<uint64_t>::const_reverse_iterator rend()const{return data.rend();}
|
|
|
- BigInt& operator=(const BigInt& o){
|
|
|
- data = o.data;
|
|
|
- signum = o.signum;
|
|
|
- return *this;
|
|
|
+ inline std::deque<uint64_t>::iterator begin(){return data.begin();}
|
|
|
+ inline std::deque<uint64_t>::iterator end(){return data.end();}
|
|
|
+ inline std::deque<uint64_t>::reverse_iterator rbegin(){return data.rbegin();}
|
|
|
+ inline std::deque<uint64_t>::reverse_iterator rend(){return data.rend();}
|
|
|
+ inline std::deque<uint64_t>::const_iterator begin()const{return data.begin();}
|
|
|
+ inline std::deque<uint64_t>::const_iterator end()const{return data.end();}
|
|
|
+ inline std::deque<uint64_t>::const_reverse_iterator rbegin()const{return data.rbegin();}
|
|
|
+ inline std::deque<uint64_t>::const_reverse_iterator rend()const{return data.rend();}
|
|
|
+ inline uint64_t& operator[](size_t i){return data[i];}
|
|
|
+ inline const uint64_t& operator[](size_t i)const{return data[i];}
|
|
|
+ inline size_t size()const{return data.size();}
|
|
|
+ inline auto cbegin()const{return data.cbegin();}
|
|
|
+ inline auto cend()const{return data.cend();}
|
|
|
+ inline auto crbegin()const{return data.crbegin();}
|
|
|
+ inline auto crend()const{return data.crend();}
|
|
|
+ inline BigInt& operator=(const BigInt& o){signum = o.signum;std::fill(std::copy(o.rbegin(),o.rend(),rbegin()),rend(),0);return *this;}
|
|
|
+ inline BigInt& operator=(BigInt&& o){data = std::move(o.data);signum = o.signum;return *this;}
|
|
|
+ inline size_t bitscanForward()const{
|
|
|
+ auto it = begin();
|
|
|
+ size_t s = 0;
|
|
|
+ while(*it == 0 && it != end()){
|
|
|
+ ++it;
|
|
|
+ s += 64;
|
|
|
+ }
|
|
|
+ if(it == end())return s + 64;
|
|
|
+ return s + __builtin_clzll(*it);
|
|
|
}
|
|
|
- BigInt& operator=(BigInt&& o){
|
|
|
- data = std::move(o.data);
|
|
|
- signum = o.signum;
|
|
|
- return *this;
|
|
|
+ inline size_t bitscanReverse()const{
|
|
|
+ auto it = rbegin();
|
|
|
+ size_t s = 0;
|
|
|
+ while(*it == 0 && it != rend()){
|
|
|
+ ++it;
|
|
|
+ s += 64;
|
|
|
+ }
|
|
|
+ if(it == rend())return s + 64;
|
|
|
+ return s + __builtin_ctzll(*it);
|
|
|
}
|
|
|
- uint64_t& operator[](size_t i){return data[i];}
|
|
|
- const uint64_t& operator[](size_t i)const{return data[i];}
|
|
|
- size_t size()const{return data.size();}
|
|
|
- auto cbegin()const{return data.cbegin();}
|
|
|
- auto cend()const{return data.cend();}
|
|
|
- auto crbegin()const{return data.crbegin();}
|
|
|
- auto crend()const{return data.crend();}
|
|
|
+
|
|
|
inline bool operator<(const BigInt& o)const{
|
|
|
if(signum > o.signum){
|
|
|
return false;
|
|
@@ -239,6 +252,9 @@ struct BigInt{
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
+ inline bool operator==(uint64_t o){
|
|
|
+ return size() == 1 && *rbegin() == o;
|
|
|
+ }
|
|
|
inline bool isZero()const{
|
|
|
for(auto it = data.begin();it != data.end();it++){
|
|
|
if(*it)return false;
|
|
@@ -311,6 +327,31 @@ struct BigInt{
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
+ inline BigInt& bitshiftLeft_expand(int c){
|
|
|
+ if(c < 0)return bitshiftRight(-c);
|
|
|
+ unsigned int sh = c % 64;
|
|
|
+ unsigned int jmp = c / 64;
|
|
|
+ int insert_count = std::max((size_t)0, jmp - bitscanForward() / 64 + 1);
|
|
|
+ while(insert_count --> 0)
|
|
|
+ data.push_front(0);
|
|
|
+ auto it1 = begin();
|
|
|
+ auto it2 = it1 + jmp;
|
|
|
+ auto beforeEnd = end() - 1;
|
|
|
+ while(it2 != beforeEnd){
|
|
|
+ *it1 = (*it2 << sh);
|
|
|
+ if(sh)
|
|
|
+ *it1 |= (*(it2 + 1) >> (64 - sh));
|
|
|
+ ++it1;++it2;
|
|
|
+ }
|
|
|
+ *it1 = (*it2 << sh);
|
|
|
+ ++it1;++it2;
|
|
|
+ while(it1 != end()){
|
|
|
+ *it1 = 0;
|
|
|
+ ++it1;
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
inline BigInt& bitshiftRight(int c){
|
|
|
if(c < 0)return bitshiftLeft(-c);
|
|
|
unsigned int sh = c % 64;
|
|
@@ -333,63 +374,63 @@ struct BigInt{
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
|
- BigInt operator<<(int c)const{
|
|
|
+ inline BigInt operator<<(int c)const{
|
|
|
BigInt ret = *this;
|
|
|
ret.bitshiftLeft(c);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- BigInt operator>>(int c)const{
|
|
|
+ inline BigInt operator>>(int c)const{
|
|
|
BigInt ret = *this;
|
|
|
ret.bitshiftRight(c);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- BigInt& operator<<=(int c){
|
|
|
+ inline BigInt& operator<<=(int c){
|
|
|
return bitshiftLeft(c);
|
|
|
}
|
|
|
|
|
|
- BigInt& operator>>=(int c){
|
|
|
+ inline BigInt& operator>>=(int c){
|
|
|
return bitshiftRight(c);
|
|
|
}
|
|
|
|
|
|
- BigInt& operator&=(const BigInt& o){
|
|
|
+ inline BigInt& operator&=(const BigInt& o){
|
|
|
auto it1 = rbegin();
|
|
|
auto it2 = o.rbegin();
|
|
|
while(it1 != rend() && it2 != o.rend())
|
|
|
*(it1++) &= *(it2++);
|
|
|
return *this;
|
|
|
}
|
|
|
- BigInt& operator|=(const BigInt& o){
|
|
|
+ inline BigInt& operator|=(const BigInt& o){
|
|
|
auto it1 = rbegin();
|
|
|
auto it2 = o.rbegin();
|
|
|
while(it1 != rend() && it2 != o.rend())
|
|
|
*(it1++) |= *(it2++);
|
|
|
return *this;
|
|
|
}
|
|
|
- BigInt& operator^=(const BigInt& o){
|
|
|
+ inline BigInt& operator^=(const BigInt& o){
|
|
|
auto it1 = rbegin();
|
|
|
auto it2 = o.rbegin();
|
|
|
while(it1 != rend() && it2 != o.rend())
|
|
|
*(it1++) ^= *(it2++);
|
|
|
return *this;
|
|
|
}
|
|
|
- BigInt operator&(const BigInt& o)const{
|
|
|
+ inline BigInt operator&(const BigInt& o)const{
|
|
|
BigInt ret(*this);
|
|
|
ret &= o;
|
|
|
return ret;
|
|
|
}
|
|
|
- BigInt operator|(const BigInt& o)const{
|
|
|
+ inline BigInt operator|(const BigInt& o)const{
|
|
|
BigInt ret(*this);
|
|
|
ret |= o;
|
|
|
return ret;
|
|
|
}
|
|
|
- BigInt operator^(const BigInt& o)const{
|
|
|
+ inline BigInt operator^(const BigInt& o)const{
|
|
|
BigInt ret(*this);
|
|
|
ret ^= o;
|
|
|
return ret;
|
|
|
}
|
|
|
- int bitDifference(const BigInt& o){
|
|
|
+ inline int bitDifference(const BigInt& o){
|
|
|
int pos1(0),pos2(0);
|
|
|
auto it1 = begin();
|
|
|
auto it2 = o.begin();
|
|
@@ -504,17 +545,51 @@ struct BigInt{
|
|
|
return *this;
|
|
|
}
|
|
|
inline BigInt& moda(const BigInt& o){
|
|
|
+ assert(!o.isZero());
|
|
|
if(o > *this)return *this;
|
|
|
+ BigInt mo = o;
|
|
|
+ mo = o;
|
|
|
+ int bd = bitDifference(o);
|
|
|
+ mo.bitshiftLeft_expand(bd);
|
|
|
+ if(mo > *this)mo.bitshiftRight(1);
|
|
|
+ this->suba(mo);
|
|
|
+ if(*this < o)return *this;
|
|
|
while(true){
|
|
|
- BigInt mo = o;
|
|
|
- int bd = bitDifference(o);
|
|
|
- mo.bitshiftLeft(bd);
|
|
|
- if(mo > *this)mo.bitshiftRight(1);
|
|
|
+ bd = mo.bitDifference(*this);
|
|
|
+ mo >>= bd;
|
|
|
+ mo.trim();
|
|
|
+ if(mo > *this)mo >>= 1;
|
|
|
this->suba(mo);
|
|
|
- if(*this < o)break;
|
|
|
+ if(*this < o)return *this;
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
|
+ inline bool even(){
|
|
|
+ return !(*rbegin() & 1);
|
|
|
+ }
|
|
|
+ inline BigInt modPow(BigInt o, const BigInt& mod)const{
|
|
|
+ BigInt t = *this;
|
|
|
+ BigInt odd(1);
|
|
|
+ while(true){
|
|
|
+ if(o.even()){
|
|
|
+ t = t.mult(t);
|
|
|
+ t.trim();
|
|
|
+ t.moda(mod);
|
|
|
+ o.div(2);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ odd = odd.mult(t);
|
|
|
+ odd.moda(mod);
|
|
|
+ odd.trim();
|
|
|
+ t.trim();
|
|
|
+ t.moda(mod);
|
|
|
+ o.suba(BigInt(1));
|
|
|
+ }
|
|
|
+ std::cout << "Reduced" << std::endl;
|
|
|
+ o.trim();
|
|
|
+ if(o == 1){t = t.mult(odd);t.moda(mod);return t;}
|
|
|
+ }
|
|
|
+ }
|
|
|
inline BigInt mult(const BigInt& o)const{
|
|
|
BigInt result(size() + o.size() + 1,0);
|
|
|
BigInt temp(size() + o.size() + 1,0);
|
|
@@ -534,10 +609,16 @@ struct BigInt{
|
|
|
temp.setZero();
|
|
|
}
|
|
|
result.trim();
|
|
|
+ BigInt krep = result;
|
|
|
+ krep.moda(*this);
|
|
|
+ assert(krep.isZero());
|
|
|
+ krep = result;
|
|
|
+ krep.moda(o);
|
|
|
+ assert(krep.isZero());
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- inline std::string rawString(){
|
|
|
+ inline std::string rawString()const{
|
|
|
std::string s = "";
|
|
|
bool flag;
|
|
|
for(unsigned int i = 0;i < size();i++){
|
|
@@ -548,10 +629,10 @@ struct BigInt{
|
|
|
}
|
|
|
return s;
|
|
|
}
|
|
|
- inline std::string bitString(){
|
|
|
+ inline std::string bitString()const{
|
|
|
auto it = begin();
|
|
|
std::string ret = "";
|
|
|
- std::cout << size() << "; " << std::flush;
|
|
|
+ //std::cout << size() << "; " << std::flush;
|
|
|
while(it != end()){
|
|
|
std::bitset<64> bits(*it);
|
|
|
for(unsigned int i = 0;i < 64;i++){
|
|
@@ -561,10 +642,10 @@ struct BigInt{
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
|
- inline std::string toString(){
|
|
|
+ inline std::string toString()const{
|
|
|
+ if(isZero())return std::to_string(0);
|
|
|
std::deque<char> c_str;
|
|
|
const uint64_t q = 1000000000000000000ULL;
|
|
|
- //c_str.reserve(size() * 19);
|
|
|
BigInt diver = *this;
|
|
|
while(!diver.isZero()){
|
|
|
std::string frac = std::to_string(diver.mod(q));
|
|
@@ -584,8 +665,10 @@ struct BigInt{
|
|
|
return std::string(it, c_str.end());
|
|
|
}
|
|
|
|
|
|
- inline std::string toString(unsigned int base){
|
|
|
- if(isZero())return std::string("0");
|
|
|
+ inline std::string toString(unsigned int base)const{
|
|
|
+ if(isZero())return std::to_string(0);
|
|
|
+ if(base == 2)return bitString();
|
|
|
+ if(base == 10)return toString();
|
|
|
std::vector<char> c_str;
|
|
|
c_str.reserve(size() * (unsigned int)(64.0 * std::log(2) / std::log((double)base)));
|
|
|
BigInt diver = *this;
|
|
@@ -599,7 +682,7 @@ struct BigInt{
|
|
|
namespace std{
|
|
|
template<>
|
|
|
struct hash<BigInt>{
|
|
|
- size_t operator()(const BigInt& o){
|
|
|
+ inline size_t operator()(const BigInt& o)const{
|
|
|
size_t ret = 0;
|
|
|
std::for_each(o.begin(), o.end(), [&ret](const uint64_t& ui){ret ^= ui;});
|
|
|
return ret;
|