Browse Source

First useful Bigint

mawinkle 6 years ago
parent
commit
29a7aecc1e
2 changed files with 55 additions and 21 deletions
  1. 50 16
      BigInt.hpp
  2. 5 5
      test.cpp

+ 50 - 16
BigInt.hpp

@@ -2,6 +2,7 @@
 #define BIG_INT_HPP
 #include "semi_bitset.hpp"
 #include <cstdlib>
+#include <string>
 template<size_t size>
 class BigInt{
 private:
@@ -19,8 +20,8 @@ public:
 		bits.data[bits.length() - 1] = o;
 	}
 	inline BigInt(long long o){
-		if(o < 0){signum = -1;o *= -1;}
-		bits.data[bits.length() - 1] = (lower_half);
+		if(o < 0){signum = -1;o = 0ULL - o;}
+		bits.data[bits.length() - 1] = (o & lower_half);
 		bits.data[bits.length() - 2] = (o >> 32);
 	}
 	inline BigInt(unsigned long long o){
@@ -28,7 +29,7 @@ public:
 		bits.data[bits.length() - 2] = (o >> 32);
 	}
 	template<std::size_t osize>
-	BigInt<size> add(const BigInt<osize>& o)const{
+	inline BigInt<size> add(const BigInt<osize>& o)const{
 		static_assert(size == osize);
 		BigInt<size> ret;
 		uint64_t carry = 0;
@@ -40,38 +41,71 @@ public:
 		}
 		return ret;
 	}
+	template<size_t osize>
+	inline BigInt<size> mult(const BigInt<osize>& o)const{
+		BigInt<size + osize> ret;
+		uint64_t mat[size][size] = {0};
+		uint64_t carry = 0;
+		for(size_t i = 0;i < size;i++){
+			for(size_t ih = size - 1;ih != ~(0ULL);ih--){
+				mat[i][ih] = (*this)[i] * o[ih] + carry;
+				carry = mat[i][ih] >> 32;
+				mat[i][ih] &= lower_half;
+				if(ih == 0)break;
+			}
+		}
+		carry = 0;
+		for(size_t i = size - 1;i != ~(0ULL);i--){
+			uint64_t accum = 0;
+			for(size_t ih = 0;ih < size;ih++){
+				accum += ((i + ih) >= size) ?  0 : mat[i + ih][ih];
+			}
+			accum += carry;
+			ret[i] = accum & lower_half;
+			carry = accum >> 32;
+		}
+		return ret;
+	}
 	
-	BigInt<size> div(unsigned int o)const{
+	inline BigInt<size> div(unsigned int o)const{
 		uint64_t carry = 0;
 		BigInt<size> ret;
 		for(size_t i = 0;i < size;i++){
-			lldiv_t dm = std::div((unsigned long long int)((carry << 32) + (*this)[i]),(unsigned long long int)o);
-			carry = dm.rem;
-			std::cout << " " << dm.rem << " ";
-			ret[i] = dm.quot;
+			uint64_t res = ((*this)[i] + (carry << 32)) / o;
+			carry = (*this)[i] % o;
+			ret[i] = res;
 		}
 		return ret;
 	}
-	unsigned int mod(unsigned int o)const{
+	inline unsigned int mod(unsigned int o)const{
 		uint64_t carry = 0;
 		for(size_t i = 0;i < size;i++){
-			lldiv_t dm = std::div((long long int)((carry << 32) + (*this)[i]),(unsigned long long int)o);
-			carry = dm.rem;
+			carry = (this->operator[](i) + (carry << 32)) % o;
 		}
 		return (unsigned int)(carry & lower_half);
 	}
-	std::uint64_t& operator[](size_t i){
+	inline std::uint64_t& operator[](size_t i){
 		return bits.data[i];
 	}
 	
-	const std::uint64_t& operator[](size_t i)const{
+	inline const std::uint64_t& operator[](size_t i)const{
 		return bits.data[i];
 	}
+	inline bool isZero()const{
+		for(size_t i = 0;i < size;i++){
+			if(this->operator[](i))return false;
+		}
+		return true;
+	}
 	template<typename stream, size_t osize>
 	inline friend stream& operator<<(stream& s, const BigInt<osize>& o){
-		for(size_t i = 0;i < o.bits.length();i++)
-			s << std::bitset<32>((uint32_t)(o.bits.data[i] & lower_half));
-		return s;
+		std::string a = "";
+		BigInt dis = o;
+		while(!dis.isZero()){
+			a = std::to_string(dis.mod(10)) + a;
+			dis = dis.div(10);
+		}
+		return s << a;
 	}
 };
 #endif

+ 5 - 5
test.cpp

@@ -21,11 +21,11 @@ std::ostream& operator<< <char>(std::ostream& out, std::vector<char> o){
 	return out;
 }
 int main(){
-	BigInt<2> a = (1LL << 63);
-	while(a[1]){
-		std::cout << a.mod(10);
-		a = a.div(10);
-	}
+	BigInt<100> a ((1ULL << 40) + 1);
+	std::cout << a << std::endl;
+	for(int i = 0;i < 1000;i++)
+	a = a.add(a);
+	std::cout << a << std::endl;
 }
 int mian(){
 	cppsocket sock("192.168.178.79", 80);