mawinkle 6 anos atrás
pai
commit
7674a017a9
2 arquivos alterados com 223 adições e 26 exclusões
  1. 218 20
      BigInt64.hpp
  2. 5 6
      test.cpp

+ 218 - 20
BigInt64.hpp

@@ -2,16 +2,18 @@
 #define BIGINT64_HPP
 #include <cstdint>
 #include <cstdlib>
+#include <cmath>
+#include <cassert>
 #include <algorithm>
 #include <iterator>
+#include <limits>
 #include <initializer_list>
 #include <deque>
 #include <vector>
 #include <string>
-#include <cmath>
 #include <bitset>
 #include <iostream>
-const std::vector<char> chars = {'0','1','2','3','4','5','6','7','8','9'};
+const std::vector<char> chars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
 const __uint128_t _m = ((__uint128_t)1) << 64;
 template<typename T>
 inline int signum(T t){
@@ -32,14 +34,18 @@ struct BigInt{
 	using uint64_t = std::uint64_t;
 	using uint32_t = std::uint32_t;
 	using lui = ::__uint128_t;
+	using iterator = std::deque<uint64_t>::iterator;
+	using const_iterator = std::deque<uint64_t>::const_iterator;
+	using reverse_iterator = std::deque<uint64_t>::reverse_iterator;
+	using const_reverse_iterator = std::deque<uint64_t>::const_reverse_iterator;
 	std::deque<uint64_t> data;
 	int signum;
 	inline BigInt() : data(1,0),signum(1){}
 	inline BigInt(size_t _s, uint64_t fill) : data(_s,fill), signum(1){}
-	inline BigInt(int a) : signum(::signum(a)), data(1, std::abs(a)){}
-	inline BigInt(unsigned int a) : signum(1), data(1, a){}
-	inline BigInt(unsigned long long a) : signum(1), data(1, a){}
-	inline BigInt(long long a) : signum(::signum(a)), data(1, std::abs(a)){}
+	inline BigInt(int a) :  data(1, std::abs(a)),signum(::signum(a)){}
+	inline BigInt(unsigned int a) : data(1, a),signum(1){}
+	inline BigInt(unsigned long long a) : data(1, a), signum(1){}
+	inline BigInt(long long a) : data(1, std::abs(a)),signum(::signum(a)){}
 	inline BigInt(const std::initializer_list<uint64_t>& l) : data(l), signum(1){}
 	inline BigInt(std::initializer_list<uint64_t>&& l) : data(std::move(l)), signum(1){}
 	template<typename InputIterator>
@@ -52,15 +58,152 @@ struct BigInt{
 	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();}
+	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(){return data.cbegin();}
-	auto cend(){return data.cend();}
-	auto crbegin(){return data.crbegin();}
-	auto crend(){return data.crend();}
 	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;
+		}
+		if(signum < o.signum){
+			return true;
+		}
+		const_iterator it1 = begin();
+		const_iterator it2 = o.begin();
+		if(size() > o.size()){
+			it1 += size() - o.size();
+			auto _t = begin();
+			while(_t != it1)
+				if(*_t)return false;
+		}
+		else if(size() < o.size()){
+			it2 += o.size() - size();
+			auto _t = o.begin();
+			while(_t != it2)
+				if(*_t)return true;
+		}
+		while(it1 != end() && it2 != o.end()){
+			if(*(it1) < *(it2))return true;
+			if(*(it1) > *(it2))return false;
+			++it1;++it2;
+		}
+		return false;
+	}
+	inline bool operator>(const BigInt& o)const{
+		if(signum < o.signum){
+			return false;
+		}
+		if(signum > o.signum){
+			return true;
+		}
+		const_iterator it1 = begin();
+		const_iterator it2 = o.begin();
+		if(size() > o.size()){
+			it1 += size() - o.size();
+			auto _t = begin();
+			while(_t != it1)
+				if(*_t)return true;
+		}
+		else if(size() < o.size()){
+			it2 += o.size() - size();
+			auto _t = o.begin();
+			while(_t != it2)
+				if(*_t)return false;
+		}
+		while(it1 != end() && it2 != o.end()){
+			if(*(it1) > *(it2))return true;
+			if(*(it1) < *(it2))return false;
+			++it1;++it2;
+		}
+		return false;
+	}
+	inline bool operator<=(const BigInt& o)const{
+		if(signum > o.signum){
+			return false;
+		}
+		if(signum < o.signum){
+			return true;
+		}
+		const_iterator it1 = begin();
+		const_iterator it2 = o.begin();
+		if(size() > o.size()){
+			it1 += size() - o.size();
+			auto _t = begin();
+			while(_t != it1)
+				if(*_t)return true;
+		}
+		else if(size() < o.size()){
+			it2 += o.size() - size();
+			auto _t = o.begin();
+			while(_t != it2)
+				if(*_t)return false;
+		}
+		while(it1 != end() && it2 != o.end()){
+			if(*(it1) < *(it2))return true;
+			if(*(it1) > *(it2))return false;
+			++it1;++it2;
+		}
+		return true;
+	}
+	inline bool operator>=(const BigInt& o)const{
+		if(signum < o.signum){
+			return false;
+		}
+		if(signum > o.signum){
+			return true;
+		}
+		const_iterator it1 = begin();
+		const_iterator it2 = o.begin();
+		if(size() > o.size()){
+			it1 += size() - o.size();
+			auto _t = begin();
+			while(_t != it1)
+				if(*_t)return true;
+		}
+		else if(size() < o.size()){
+			it2 += o.size() - size();
+			auto _t = o.begin();
+			while(_t != it2)
+				if(*_t)return false;
+		}
+		while(it1 != end() && it2 != o.end()){
+			if(*(it1) > *(it2))return true;
+			if(*(it1) < *(it2))return false;
+			++it1;++it2;
+		}
+		return true;
+	}
+	inline bool operator==(const BigInt& o)const{
+		if(signum < o.signum){
+			return false;
+		}
+		if(signum > o.signum){
+			return false;
+		}
+		const_iterator it1 = begin();
+		const_iterator it2 = o.begin();
+		if(size() > o.size()){
+			it1 += size() - o.size();
+			auto _t = begin();
+			while(_t != it1)
+				if(*_t)return false;
+		}
+		else if(size() < o.size()){
+			it2 += o.size() - size();
+			auto _t = o.begin();
+			while(_t != it2)
+				if(*_t)return false;
+		}
+		while(it1 != end() && it2 != o.end()){
+			if(*(it1) != *(it2))return false;
+			++it1;++it2;
+		}
+		return true;
+	}
 	inline bool isZero()const{
 		for(auto it = data.begin();it != data.end();it++){
 			if(*it)return false;
@@ -108,7 +251,7 @@ struct BigInt{
 	}
 	inline BigInt& chunkshiftLeft(int c){
 		if(c < 0)return chunkshiftRight(-c);
-		if(c >= size()){std::fill(begin(),end(),0);return *this;}
+		if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
 		auto it1 = data.begin(); 
 		auto it2 = it1 + c;
 		while(it2 != data.end())*(it1++) = *(it2++);
@@ -117,13 +260,18 @@ struct BigInt{
 	}
 	inline BigInt& chunkshiftRight(int c){
 		if(c < 0)return chunkshiftLeft(-c);
-		if(c >= size()){std::fill(begin(),end(),0);return *this;}
+		if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
 		auto it1 = data.rbegin(); 
 		auto it2 = it1 + c;
 		while(it2 != data.rend())*(it1++) = *(it2++);
 		while(it1 != data.rend())*(it1++) = 0;
 		return *this;
 	}
+	inline BigInt add(const BigInt& o){
+		BigInt ret = *this;
+		ret.adda(o);
+		return ret;
+	}
 	inline BigInt& adda(const BigInt& o){
 		while(size() < o.size())data.push_front(0);
 		bool carry = 0;
@@ -141,10 +289,25 @@ struct BigInt{
 		if(carry)data.push_front(1);
 		return *this;
 	}
-	
-	inline BigInt mult(const BigInt& o){
-		BigInt result(size() + o.size(),0);
-		BigInt temp(size() + o.size(),0);
+	inline BigInt& suba(const BigInt& o){
+		assert((*this) >= (o));
+		bool carry = 0;
+		auto it1 = rbegin();
+		auto it2 = o.rbegin();
+		while(it1 != rend() && it2 != o.rend()){
+			carry = __builtin_usubll_overflow(*it1 - carry, *it2, (unsigned long long*)(&(*it1)));
+			carry |= ((*it1 - carry) == std::numeric_limits<uint64_t>::max());
+			it1++;
+			it2++;
+		}
+		while(it1 != rend() && carry){
+			carry = __builtin_usubll_overflow(*it1, carry, (unsigned long long*)(&(*it1)));
+		}
+		return *this;
+	}
+	inline BigInt mult(const BigInt& o)const{
+		BigInt result(size() + o.size() + 1,0);
+		BigInt temp(size() + o.size() + 1,0);
 		int p = 0;
 		for(auto it1 = rbegin();it1 != rend();it1++){
 			auto it = temp.rbegin();
@@ -155,7 +318,7 @@ struct BigInt{
 				*(it++) = (uint64_t)prod;
 				carry = (prod >> 64);
 			}
-			if(carry)(*it)++;
+			if(carry)(*it) += carry;
 			temp.chunkshiftLeft(p++);
 			result.adda(temp);
 			temp.setZero();
@@ -164,13 +327,48 @@ struct BigInt{
 		return result;
 	}
 	
+	inline std::string rawString(){
+		std::string s = "";
+		bool flag;
+		for(unsigned int i = 0;i < size();i++){
+			if(data[i])flag = true;
+			if(flag);
+			s += std::to_string(data[i]);
+			if(i < size() - 1)s += "|";
+		}
+		return s;
+	}
+	
 	inline std::string toString(){
+		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));
+			int a = 0;
+			for(auto it = frac.rbegin();it != frac.rend();it++){
+				c_str.push_front(*it);
+				a++;
+			}
+			while(a < 18){
+				c_str.push_front('0');
+				a++;
+			}
+			diver.div(q);
+		}
+		auto it = c_str.begin();
+		while(*(it) == '0')++it;
+		return std::string(it, c_str.end());
+	}
+	
+	inline std::string toString(unsigned int base){
 		std::vector<char> c_str;
-		c_str.reserve(data.size() * 19);
+		c_str.reserve(size() * (unsigned int)(64.0 * std::log(2) / std::log((double)base)));
 		BigInt diver = *this;
 		while(!diver.isZero()){
-			c_str.push_back(chars.at(diver.mod(10)));
-			diver.div(10);
+			c_str.push_back(chars.at(diver.mod(base)));
+			diver.div(base);
 		}
 		return std::string(c_str.rbegin(), c_str.rend());
 	}

+ 5 - 6
test.cpp

@@ -27,15 +27,14 @@ std::ostream& operator<< <char>(std::ostream& out, std::vector<char> o){
 	return out;
 }
 int main(){
-	BigInt a = {1LL << 32};
-	for(int i = 0;i < 12;i++){
-		std::cout << a.toString().size() << " - stellig: " << std::flush;
+	BigInt a = {20,20};
+	BigInt b = {1};
+	for(int i = 0;i < 30;i++){
 		auto t1 = nanoTime();
-		a = a.mult(a);
+		a.suba(b);
 		auto t2 = nanoTime();
-		std::cout << (t2 - t1) << " ns" << std::endl;
+		std::cout << a.rawString() << std::endl;
 	}
-	
 }
 int mian(){
 	cppsocket sock("192.168.178.79", 80);