|
@@ -50,6 +50,8 @@ struct BigInt{
|
|
inline BigInt(std::initializer_list<uint64_t>&& l) : data(std::move(l)), signum(1){}
|
|
inline BigInt(std::initializer_list<uint64_t>&& l) : data(std::move(l)), signum(1){}
|
|
template<typename InputIterator>
|
|
template<typename InputIterator>
|
|
inline BigInt(InputIterator begin, InputIterator end) : data(begin, end), signum(1){}
|
|
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 begin(){return data.begin();}
|
|
std::deque<uint64_t>::iterator end(){return data.end();}
|
|
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 rbegin(){return data.rbegin();}
|
|
@@ -77,14 +79,18 @@ struct BigInt{
|
|
if(size() > o.size()){
|
|
if(size() > o.size()){
|
|
it1 += size() - o.size();
|
|
it1 += size() - o.size();
|
|
auto _t = begin();
|
|
auto _t = begin();
|
|
- while(_t != it1)
|
|
|
|
|
|
+ while(_t != it1){
|
|
if(*_t)return false;
|
|
if(*_t)return false;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else if(size() < o.size()){
|
|
else if(size() < o.size()){
|
|
it2 += o.size() - size();
|
|
it2 += o.size() - size();
|
|
auto _t = o.begin();
|
|
auto _t = o.begin();
|
|
- while(_t != it2)
|
|
|
|
|
|
+ while(_t != it2){
|
|
if(*_t)return true;
|
|
if(*_t)return true;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
while(it1 != end() && it2 != o.end()){
|
|
while(it1 != end() && it2 != o.end()){
|
|
if(*(it1) < *(it2))return true;
|
|
if(*(it1) < *(it2))return true;
|
|
@@ -105,14 +111,18 @@ struct BigInt{
|
|
if(size() > o.size()){
|
|
if(size() > o.size()){
|
|
it1 += size() - o.size();
|
|
it1 += size() - o.size();
|
|
auto _t = begin();
|
|
auto _t = begin();
|
|
- while(_t != it1)
|
|
|
|
|
|
+ while(_t != it1){
|
|
if(*_t)return true;
|
|
if(*_t)return true;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else if(size() < o.size()){
|
|
else if(size() < o.size()){
|
|
it2 += o.size() - size();
|
|
it2 += o.size() - size();
|
|
auto _t = o.begin();
|
|
auto _t = o.begin();
|
|
- while(_t != it2)
|
|
|
|
|
|
+ while(_t != it2){
|
|
if(*_t)return false;
|
|
if(*_t)return false;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
while(it1 != end() && it2 != o.end()){
|
|
while(it1 != end() && it2 != o.end()){
|
|
if(*(it1) > *(it2))return true;
|
|
if(*(it1) > *(it2))return true;
|
|
@@ -133,14 +143,18 @@ struct BigInt{
|
|
if(size() > o.size()){
|
|
if(size() > o.size()){
|
|
it1 += size() - o.size();
|
|
it1 += size() - o.size();
|
|
auto _t = begin();
|
|
auto _t = begin();
|
|
- while(_t != it1)
|
|
|
|
|
|
+ while(_t != it1){
|
|
if(*_t)return true;
|
|
if(*_t)return true;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else if(size() < o.size()){
|
|
else if(size() < o.size()){
|
|
it2 += o.size() - size();
|
|
it2 += o.size() - size();
|
|
auto _t = o.begin();
|
|
auto _t = o.begin();
|
|
- while(_t != it2)
|
|
|
|
|
|
+ while(_t != it2){
|
|
if(*_t)return false;
|
|
if(*_t)return false;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
while(it1 != end() && it2 != o.end()){
|
|
while(it1 != end() && it2 != o.end()){
|
|
if(*(it1) < *(it2))return true;
|
|
if(*(it1) < *(it2))return true;
|
|
@@ -161,14 +175,18 @@ struct BigInt{
|
|
if(size() > o.size()){
|
|
if(size() > o.size()){
|
|
it1 += size() - o.size();
|
|
it1 += size() - o.size();
|
|
auto _t = begin();
|
|
auto _t = begin();
|
|
- while(_t != it1)
|
|
|
|
|
|
+ while(_t != it1){
|
|
if(*_t)return true;
|
|
if(*_t)return true;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else if(size() < o.size()){
|
|
else if(size() < o.size()){
|
|
it2 += o.size() - size();
|
|
it2 += o.size() - size();
|
|
auto _t = o.begin();
|
|
auto _t = o.begin();
|
|
- while(_t != it2)
|
|
|
|
|
|
+ while(_t != it2){
|
|
if(*_t)return false;
|
|
if(*_t)return false;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
while(it1 != end() && it2 != o.end()){
|
|
while(it1 != end() && it2 != o.end()){
|
|
if(*(it1) > *(it2))return true;
|
|
if(*(it1) > *(it2))return true;
|
|
@@ -189,14 +207,18 @@ struct BigInt{
|
|
if(size() > o.size()){
|
|
if(size() > o.size()){
|
|
it1 += size() - o.size();
|
|
it1 += size() - o.size();
|
|
auto _t = begin();
|
|
auto _t = begin();
|
|
- while(_t != it1)
|
|
|
|
|
|
+ while(_t != it1){
|
|
if(*_t)return false;
|
|
if(*_t)return false;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else if(size() < o.size()){
|
|
else if(size() < o.size()){
|
|
it2 += o.size() - size();
|
|
it2 += o.size() - size();
|
|
auto _t = o.begin();
|
|
auto _t = o.begin();
|
|
- while(_t != it2)
|
|
|
|
|
|
+ while(_t != it2){
|
|
if(*_t)return false;
|
|
if(*_t)return false;
|
|
|
|
+ ++_t;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
while(it1 != end() && it2 != o.end()){
|
|
while(it1 != end() && it2 != o.end()){
|
|
if(*(it1) != *(it2))return false;
|
|
if(*(it1) != *(it2))return false;
|
|
@@ -213,11 +235,13 @@ struct BigInt{
|
|
inline void setZero(){
|
|
inline void setZero(){
|
|
for(auto it = begin();it != end();it++)*it = 0;
|
|
for(auto it = begin();it != end();it++)*it = 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
inline void trim(){
|
|
inline void trim(){
|
|
while(data[0] == 0 && data.size() != 0){
|
|
while(data[0] == 0 && data.size() != 0){
|
|
data.pop_front();
|
|
data.pop_front();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
inline BigInt div(uint64_t d)const{
|
|
inline BigInt div(uint64_t d)const{
|
|
BigInt ret = *this;
|
|
BigInt ret = *this;
|
|
lui carry = 0;
|
|
lui carry = 0;
|
|
@@ -249,6 +273,51 @@ struct BigInt{
|
|
}
|
|
}
|
|
return carry;
|
|
return carry;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ inline BigInt& bitshiftLeft(int c){
|
|
|
|
+ if(c < 0)return bitshiftRight(-c);
|
|
|
|
+ if((unsigned int)c >= size() * sizeof(uint64_t)){std::fill(begin(),end(),0);return *this;}
|
|
|
|
+ unsigned int sh = c % 64;
|
|
|
|
+ unsigned int jmp = c / 64;
|
|
|
|
+ auto it1 = begin();
|
|
|
|
+ auto it2 = it1 + jmp;
|
|
|
|
+ auto beforeEnd = end() - 1;
|
|
|
|
+ while(it2 != beforeEnd){
|
|
|
|
+ *it1 = (*it2 << sh);
|
|
|
|
+ *it1 |= (*(it2 + 1) >> (64 - sh));
|
|
|
|
+ ++it1;++it2;
|
|
|
|
+ }
|
|
|
|
+ ++it1;++it2;
|
|
|
|
+ *it1 = (*it2 << sh);
|
|
|
|
+ while(it1 != end()){
|
|
|
|
+ *it1 = 0;
|
|
|
|
+ ++it1;
|
|
|
|
+ }
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ inline BigInt& bitshiftRight(int c){
|
|
|
|
+ if(c < 0)return bitshiftLeft(-c);
|
|
|
|
+ if((unsigned int)c >= size() * sizeof(uint64_t)){std::fill(begin(),end(),0);return *this;}
|
|
|
|
+ unsigned int sh = c % 64;
|
|
|
|
+ unsigned int jmp = c / 64;
|
|
|
|
+ auto it1 = rbegin();
|
|
|
|
+ auto it2 = it1 + jmp;
|
|
|
|
+ auto beforeRend = rend() - 1;
|
|
|
|
+ while(it2 != beforeRend){
|
|
|
|
+ *it1 = (*it2 >> sh);
|
|
|
|
+ *it1 |= (*(it2 + 1) << (64 - sh));
|
|
|
|
+ ++it1;++it2;
|
|
|
|
+ }
|
|
|
|
+ ++it1;++it2;
|
|
|
|
+ *it1 = (*it2 << sh);
|
|
|
|
+ while(it1 != rend()){
|
|
|
|
+ *it1 = 0;
|
|
|
|
+ ++it1;
|
|
|
|
+ }
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
inline BigInt& chunkshiftLeft(int c){
|
|
inline BigInt& chunkshiftLeft(int c){
|
|
if(c < 0)return chunkshiftRight(-c);
|
|
if(c < 0)return chunkshiftRight(-c);
|
|
if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
@@ -258,6 +327,7 @@ struct BigInt{
|
|
while(it1 != data.end())*(it1++) = 0;
|
|
while(it1 != data.end())*(it1++) = 0;
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
|
|
+
|
|
inline BigInt& chunkshiftRight(int c){
|
|
inline BigInt& chunkshiftRight(int c){
|
|
if(c < 0)return chunkshiftLeft(-c);
|
|
if(c < 0)return chunkshiftLeft(-c);
|
|
if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
@@ -267,11 +337,36 @@ struct BigInt{
|
|
while(it1 != data.rend())*(it1++) = 0;
|
|
while(it1 != data.rend())*(it1++) = 0;
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
|
|
+ inline BigInt bitshiftLeft(int c)const{
|
|
|
|
+ if(c < 0)return bitshiftRight(-c);
|
|
|
|
+ BigInt _this = *this;
|
|
|
|
+ _this.bitshiftLeft(c);
|
|
|
|
+ return _this;
|
|
|
|
+ }
|
|
|
|
+ inline BigInt bitshiftRight(int c)const{
|
|
|
|
+ if(c < 0)return bitshiftLeft(-c);
|
|
|
|
+ BigInt _this = *this;
|
|
|
|
+ _this.bitshiftRight(c);
|
|
|
|
+ return _this;
|
|
|
|
+ }
|
|
|
|
+ inline BigInt chunkshiftLeft(int c)const{
|
|
|
|
+ if(c < 0)return chunkshiftRight(-c);
|
|
|
|
+ BigInt _this = *this;
|
|
|
|
+ _this.chunkshiftLeft(c);
|
|
|
|
+ return _this;
|
|
|
|
+ }
|
|
|
|
+ inline BigInt chunkshiftRight(int c)const{
|
|
|
|
+ if(c < 0)return chunkshiftLeft(-c);
|
|
|
|
+ BigInt _this = *this;
|
|
|
|
+ _this.chunkshiftRight(c);
|
|
|
|
+ return _this;
|
|
|
|
+ }
|
|
inline BigInt add(const BigInt& o){
|
|
inline BigInt add(const BigInt& o){
|
|
BigInt ret = *this;
|
|
BigInt ret = *this;
|
|
ret.adda(o);
|
|
ret.adda(o);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+
|
|
inline BigInt& adda(const BigInt& o){
|
|
inline BigInt& adda(const BigInt& o){
|
|
while(size() < o.size())data.push_front(0);
|
|
while(size() < o.size())data.push_front(0);
|
|
bool carry = 0;
|
|
bool carry = 0;
|
|
@@ -285,6 +380,7 @@ struct BigInt{
|
|
}
|
|
}
|
|
while(it1 != rend() && carry){
|
|
while(it1 != rend() && carry){
|
|
carry = __builtin_uaddll_overflow(*it1, carry, (unsigned long long*)(&(*it1)));
|
|
carry = __builtin_uaddll_overflow(*it1, carry, (unsigned long long*)(&(*it1)));
|
|
|
|
+ ++it1;
|
|
}
|
|
}
|
|
if(carry)data.push_front(1);
|
|
if(carry)data.push_front(1);
|
|
return *this;
|
|
return *this;
|
|
@@ -302,6 +398,7 @@ struct BigInt{
|
|
}
|
|
}
|
|
while(it1 != rend() && carry){
|
|
while(it1 != rend() && carry){
|
|
carry = __builtin_usubll_overflow(*it1, carry, (unsigned long long*)(&(*it1)));
|
|
carry = __builtin_usubll_overflow(*it1, carry, (unsigned long long*)(&(*it1)));
|
|
|
|
+ ++it1;
|
|
}
|
|
}
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
@@ -373,4 +470,14 @@ struct BigInt{
|
|
return std::string(c_str.rbegin(), c_str.rend());
|
|
return std::string(c_str.rbegin(), c_str.rend());
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
+namespace std{
|
|
|
|
+ template<>
|
|
|
|
+ struct hash<BigInt>{
|
|
|
|
+ size_t operator()(const BigInt& o){
|
|
|
|
+ size_t ret = 0;
|
|
|
|
+ std::for_each(o.begin(), o.end(), [&ret](const uint64_t& ui){ret ^= ui;});
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+}
|
|
#endif //BIGINT64_HPP
|
|
#endif //BIGINT64_HPP
|