Quellcode durchsuchen

First attempt for MSVC support, removed old multiplication

mawinkle vor 6 Jahren
Ursprung
Commit
f5f62a3407
6 geänderte Dateien mit 1060 neuen und 41 gelöschten Zeilen
  1. 27 37
      crypt/BigInt64.hpp
  2. 38 2
      crypt/intrin.hpp
  3. 469 0
      crypt/uint128_t.cpp
  4. 521 0
      crypt/uint128_t.h
  5. BIN
      crypt/uint128_t.o
  6. 5 2
      test.cpp

+ 27 - 37
crypt/BigInt64.hpp

@@ -15,31 +15,18 @@
 #include <iostream>
 #include "intrin.hpp"
 const static std::vector<char> chars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-/*std::uint64_t _mulx_u64(std::uint64_t a, std::uint64_t b, std::uint64_t* hi){
-	__uint128_t r = ((__uint128_t)a) * b;
-	*hi = (std::uint64_t)(r >> 64);
-	return r;
-}*/
 template<typename T>
 inline int signum(T t){
 	if(t < 0)return -1;
 	if(t >= 0)return 1;
 	assert(false);
 }
-inline std::ostream& operator<<(std::ostream& out, __uint128_t o){
-	if(o == 0)return out << "0";
-	while(o > 0){
-		out << std::to_string((int)(o % 10));
-		o /= 10;
-	}
-	return out;
-}
 struct BigInt{
+	using lui = ::__uint128_t;
 	using size_t = std::size_t;
 	using ssize_t = std::int64_t;
 	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;
@@ -56,6 +43,29 @@ struct BigInt{
 	inline BigInt(std::initializer_list<uint64_t>&& l) : data(std::move(l)), signum(1){}
 	inline BigInt(const BigInt& o) : data(o.data), signum(o.signum){}
 	inline BigInt(BigInt&& o) : data(std::move(o.data)), signum(o.signum){}
+	template<typename InputIterator>
+	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();});}
+	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 std::deque<uint64_t>::const_iterator cbegin()const{return data.cbegin();}
+	inline std::deque<uint64_t>::const_iterator cend()const{return data.cend();}
+	inline std::deque<uint64_t>::const_reverse_iterator crbegin()const{return data.crbegin();}
+	inline std::deque<uint64_t>::const_reverse_iterator crend()const{return data.crend();}
+	inline uint64_t& operator[](size_t i){return data[i];}
+	inline const uint64_t& operator[](size_t i)const{return data.at(i);}
+	inline uint64_t& at(size_t i){return data[i];}
+	inline const uint64_t& at(size_t i)const{return data.at(i);}
+	inline size_t size()const{return data.size();}
+	inline BigInt& operator=(const BigInt& o){signum = o.signum;data = o.data;return *this;}
+	inline BigInt& operator=(BigInt&& o){data = std::move(o.data);signum = o.signum;return *this;}
 	inline BigInt(const std::string& o){
 		signum = 1;
 		auto it = o.rbegin();
@@ -74,27 +84,6 @@ struct BigInt{
 		}
 		trim();
 	}
-	template<typename InputIterator>
-	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();});}
-	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;data = o.data;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;
@@ -455,6 +444,7 @@ struct BigInt{
 	}
 	inline BigInt& cut(size_t chunks){
 		while(size() > chunks)data.pop_front();
+		return *this;
 	}
 	inline int bitDifference(const BigInt& o){
 		int pos1(0),pos2(0);
@@ -665,8 +655,8 @@ struct BigInt{
 		bool flag;
 		for(unsigned int i = 0;i < size();i++){
 			if(data[i])flag = true;
-			if(flag);
-			s += std::to_string(data[i]);
+			if(flag)
+				s += std::to_string(data[i]);
 			if(i < size() - 1)s += "|";
 		}
 		return s;

+ 38 - 2
crypt/intrin.hpp

@@ -1,6 +1,25 @@
 #ifndef INTRIN_HPP
 #define INTRIN_HPP
 #include <cstdint>
+#ifdef _DEF_INT128
+#error _DEF_INT128 cannot be directly set
+#elif defined(__SIZEOF_INT128__)
+#if (defined(__clang__) && !defined(_WIN32) && !defined(__aarch64__)) || \
+    (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) ||                \
+    (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
+#define _DEF_INT128 1
+#elif defined(__CUDACC__)
+#if __CUDACC_VER__ >= 70000
+#define _DEF_INT128 1
+#endif
+#endif
+#endif
+#ifndef _DEF_INT128
+#include "uint128_t.h"
+using uint_128bit = uint128_t;
+#else
+using uint_128bit = unsigned __int128;
+#endif
 #if defined(__GNUC__) || defined(__clang__)
 inline int _leading_zeros(unsigned long long x){
 	return __builtin_clzll(x);
@@ -20,7 +39,24 @@ inline unsigned long long _mulx_u64(unsigned long long a, unsigned long long b,
 	return r;
 }
 #endif
-#ifdef _WIN64
-
+#ifdef _MSC_VER
+#include <intrin.h>
+inline int _leading_zeros(unsigned long long x){
+	int index = 0;
+	_BitScanForward64(x, &index);
+	return index;
+}
+inline int _trailing_zeros(unsigned long long x){
+	int index = 0;
+	_BitScanReverse64(x, &index);
+	return index;
+}
+bool _adc_u64(unsigned long long a,unsigned long long b,unsigned long long* c){
+	return _addcarry_u64(0, a, b, c);
+}
+bool _sbc_u64(unsigned long long a,unsigned long long b,unsigned long long* c){
+	 *c = a - b;
+	 return b > a;
+}
 #endif
 #endif //INTRIN_HPP

+ 469 - 0
crypt/uint128_t.cpp

@@ -0,0 +1,469 @@
+#include "uint128_t.h"
+
+const uint128_t uint128_0(0);
+const uint128_t uint128_1(1);
+
+uint128_t::uint128_t()
+    : UPPER(0), LOWER(0)
+{}
+
+uint128_t::uint128_t(const uint128_t & rhs)
+    : UPPER(rhs.UPPER), LOWER(rhs.LOWER)
+{}
+
+uint128_t::uint128_t(uint128_t && rhs)
+    : UPPER(std::move(rhs.UPPER)), LOWER(std::move(rhs.LOWER))
+{
+    if (this != &rhs){
+        rhs.UPPER = 0;
+        rhs.LOWER = 0;
+    }
+}
+
+uint128_t & uint128_t::operator=(const uint128_t & rhs){
+    UPPER = rhs.UPPER;
+    LOWER = rhs.LOWER;
+    return *this;
+}
+
+uint128_t & uint128_t::operator=(uint128_t && rhs){
+    if (this != &rhs){
+        UPPER = std::move(rhs.UPPER);
+        LOWER = std::move(rhs.LOWER);
+        rhs.UPPER = 0;
+        rhs.LOWER = 0;
+    }
+    return *this;
+}
+
+uint128_t::operator bool() const{
+    return (bool) (UPPER | LOWER);
+}
+
+uint128_t::operator uint8_t() const{
+    return (uint8_t) LOWER;
+}
+
+uint128_t::operator uint16_t() const{
+    return (uint16_t) LOWER;
+}
+
+uint128_t::operator uint32_t() const{
+    return (uint32_t) LOWER;
+}
+
+uint128_t::operator uint64_t() const{
+    return (uint64_t) LOWER;
+}
+
+uint128_t uint128_t::operator&(const uint128_t & rhs) const{
+    return uint128_t(UPPER & rhs.UPPER, LOWER & rhs.LOWER);
+}
+
+uint128_t & uint128_t::operator&=(const uint128_t & rhs){
+    UPPER &= rhs.UPPER;
+    LOWER &= rhs.LOWER;
+    return *this;
+}
+
+uint128_t uint128_t::operator|(const uint128_t & rhs) const{
+    return uint128_t(UPPER | rhs.UPPER, LOWER | rhs.LOWER);
+}
+
+uint128_t & uint128_t::operator|=(const uint128_t & rhs){
+    UPPER |= rhs.UPPER;
+    LOWER |= rhs.LOWER;
+    return *this;
+}
+
+uint128_t uint128_t::operator^(const uint128_t & rhs) const{
+    return uint128_t(UPPER ^ rhs.UPPER, LOWER ^ rhs.LOWER);
+}
+
+uint128_t & uint128_t::operator^=(const uint128_t & rhs){
+    UPPER ^= rhs.UPPER;
+    LOWER ^= rhs.LOWER;
+    return *this;
+}
+
+uint128_t uint128_t::operator~() const{
+    return uint128_t(~UPPER, ~LOWER);
+}
+
+uint128_t uint128_t::operator<<(const uint128_t & rhs) const{
+    const uint64_t shift = rhs.LOWER;
+    if (((bool) rhs.UPPER) || (shift >= 128)){
+        return uint128_0;
+    }
+    else if (shift == 64){
+        return uint128_t(LOWER, 0);
+    }
+    else if (shift == 0){
+        return *this;
+    }
+    else if (shift < 64){
+        return uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift);
+    }
+    else if ((128 > shift) && (shift > 64)){
+        return uint128_t(LOWER << (shift - 64), 0);
+    }
+    else{
+        return uint128_0;
+    }
+}
+
+uint128_t & uint128_t::operator<<=(const uint128_t & rhs){
+    *this = *this << rhs;
+    return *this;
+}
+
+uint128_t uint128_t::operator>>(const uint128_t & rhs) const{
+    const uint64_t shift = rhs.LOWER;
+    if (((bool) rhs.UPPER) || (shift >= 128)){
+        return uint128_0;
+    }
+    else if (shift == 64){
+        return uint128_t(0, UPPER);
+    }
+    else if (shift == 0){
+        return *this;
+    }
+    else if (shift < 64){
+        return uint128_t(UPPER >> shift, (UPPER << (64 - shift)) + (LOWER >> shift));
+    }
+    else if ((128 > shift) && (shift > 64)){
+        return uint128_t(0, (UPPER >> (shift - 64)));
+    }
+    else{
+        return uint128_0;
+    }
+}
+
+uint128_t & uint128_t::operator>>=(const uint128_t & rhs){
+    *this = *this >> rhs;
+    return *this;
+}
+
+bool uint128_t::operator!() const{
+    return !(bool) (UPPER | LOWER);
+}
+
+bool uint128_t::operator&&(const uint128_t & rhs) const{
+    return ((bool) *this && rhs);
+}
+
+bool uint128_t::operator||(const uint128_t & rhs) const{
+     return ((bool) *this || rhs);
+}
+
+bool uint128_t::operator==(const uint128_t & rhs) const{
+    return ((UPPER == rhs.UPPER) && (LOWER == rhs.LOWER));
+}
+
+bool uint128_t::operator!=(const uint128_t & rhs) const{
+    return ((UPPER != rhs.UPPER) | (LOWER != rhs.LOWER));
+}
+
+bool uint128_t::operator>(const uint128_t & rhs) const{
+    if (UPPER == rhs.UPPER){
+        return (LOWER > rhs.LOWER);
+    }
+    return (UPPER > rhs.UPPER);
+}
+
+bool uint128_t::operator<(const uint128_t & rhs) const{
+    if (UPPER == rhs.UPPER){
+        return (LOWER < rhs.LOWER);
+    }
+    return (UPPER < rhs.UPPER);
+}
+
+bool uint128_t::operator>=(const uint128_t & rhs) const{
+    return ((*this > rhs) | (*this == rhs));
+}
+
+bool uint128_t::operator<=(const uint128_t & rhs) const{
+    return ((*this < rhs) | (*this == rhs));
+}
+
+uint128_t uint128_t::operator+(const uint128_t & rhs) const{
+    return uint128_t(UPPER + rhs.UPPER + ((LOWER + rhs.LOWER) < LOWER), LOWER + rhs.LOWER);
+}
+
+uint128_t & uint128_t::operator+=(const uint128_t & rhs){
+    UPPER += rhs.UPPER + ((LOWER + rhs.LOWER) < LOWER);
+    LOWER += rhs.LOWER;
+    return *this;
+}
+
+uint128_t uint128_t::operator-(const uint128_t & rhs) const{
+    return uint128_t(UPPER - rhs.UPPER - ((LOWER - rhs.LOWER) > LOWER), LOWER - rhs.LOWER);
+}
+
+uint128_t & uint128_t::operator-=(const uint128_t & rhs){
+    *this = *this - rhs;
+    return *this;
+}
+
+uint128_t uint128_t::operator*(const uint128_t & rhs) const{
+    // split values into 4 32-bit parts
+    uint64_t top[4] = {UPPER >> 32, UPPER & 0xffffffff, LOWER >> 32, LOWER & 0xffffffff};
+    uint64_t bottom[4] = {rhs.UPPER >> 32, rhs.UPPER & 0xffffffff, rhs.LOWER >> 32, rhs.LOWER & 0xffffffff};
+    uint64_t products[4][4];
+
+    // multiply each component of the values
+    for(int y = 3; y > -1; y--){
+        for(int x = 3; x > -1; x--){
+            products[3 - x][y] = top[x] * bottom[y];
+        }
+    }
+
+    // first row
+    uint64_t fourth32 = (products[0][3] & 0xffffffff);
+    uint64_t third32  = (products[0][2] & 0xffffffff) + (products[0][3] >> 32);
+    uint64_t second32 = (products[0][1] & 0xffffffff) + (products[0][2] >> 32);
+    uint64_t first32  = (products[0][0] & 0xffffffff) + (products[0][1] >> 32);
+
+    // second row
+    third32  += (products[1][3] & 0xffffffff);
+    second32 += (products[1][2] & 0xffffffff) + (products[1][3] >> 32);
+    first32  += (products[1][1] & 0xffffffff) + (products[1][2] >> 32);
+
+    // third row
+    second32 += (products[2][3] & 0xffffffff);
+    first32  += (products[2][2] & 0xffffffff) + (products[2][3] >> 32);
+
+    // fourth row
+    first32  += (products[3][3] & 0xffffffff);
+
+    // move carry to next digit
+    third32  += fourth32 >> 32;
+    second32 += third32  >> 32;
+    first32  += second32 >> 32;
+
+    // remove carry from current digit
+    fourth32 &= 0xffffffff;
+    third32  &= 0xffffffff;
+    second32 &= 0xffffffff;
+    first32  &= 0xffffffff;
+
+    // combine components
+    return uint128_t((first32 << 32) | second32, (third32 << 32) | fourth32);
+}
+
+uint128_t & uint128_t::operator*=(const uint128_t & rhs){
+    *this = *this * rhs;
+    return *this;
+}
+
+std::pair <uint128_t, uint128_t> uint128_t::divmod(const uint128_t & lhs, const uint128_t & rhs) const{
+    // Save some calculations /////////////////////
+    if (rhs == uint128_0){
+        throw std::domain_error("Error: division or modulus by 0");
+    }
+    else if (rhs == uint128_1){
+        return std::pair <uint128_t, uint128_t> (lhs, uint128_0);
+    }
+    else if (lhs == rhs){
+        return std::pair <uint128_t, uint128_t> (uint128_1, uint128_0);
+    }
+    else if ((lhs == uint128_0) || (lhs < rhs)){
+        return std::pair <uint128_t, uint128_t> (uint128_0, lhs);
+    }
+
+    std::pair <uint128_t, uint128_t> qr (uint128_0, uint128_0);
+    for(uint8_t x = lhs.bits(); x > 0; x--){
+        qr.first  <<= uint128_1;
+        qr.second <<= uint128_1;
+
+        if ((lhs >> (x - 1U)) & 1){
+            ++qr.second;
+        }
+
+        if (qr.second >= rhs){
+            qr.second -= rhs;
+            ++qr.first;
+        }
+    }
+    return qr;
+}
+
+uint128_t uint128_t::operator/(const uint128_t & rhs) const{
+    return divmod(*this, rhs).first;
+}
+
+uint128_t & uint128_t::operator/=(const uint128_t & rhs){
+    *this = *this / rhs;
+    return *this;
+}
+
+uint128_t uint128_t::operator%(const uint128_t & rhs) const{
+    return divmod(*this, rhs).second;
+}
+
+uint128_t & uint128_t::operator%=(const uint128_t & rhs){
+    *this = *this % rhs;
+    return *this;
+}
+
+uint128_t & uint128_t::operator++(){
+    return *this += uint128_1;
+}
+
+uint128_t uint128_t::operator++(int){
+    uint128_t temp(*this);
+    ++*this;
+    return temp;
+}
+
+uint128_t & uint128_t::operator--(){
+    return *this -= uint128_1;
+}
+
+uint128_t uint128_t::operator--(int){
+    uint128_t temp(*this);
+    --*this;
+    return temp;
+}
+
+uint128_t uint128_t::operator+() const{
+    return *this;
+}
+
+uint128_t uint128_t::operator-() const{
+    return ~*this + uint128_1;
+}
+
+const uint64_t & uint128_t::upper() const{
+    return UPPER;
+}
+
+const uint64_t & uint128_t::lower() const{
+    return LOWER;
+}
+
+uint8_t uint128_t::bits() const{
+    uint8_t out = 0;
+    if (UPPER){
+        out = 64;
+        uint64_t up = UPPER;
+        while (up){
+            up >>= 1;
+            out++;
+        }
+    }
+    else{
+        uint64_t low = LOWER;
+        while (low){
+            low >>= 1;
+            out++;
+        }
+    }
+    return out;
+}
+
+std::string uint128_t::str(uint8_t base, const unsigned int & len) const{
+    if ((base < 2) || (base > 16)){
+        throw std::invalid_argument("Base must be in the range [2, 16]");
+    }
+    std::string out = "";
+    if (!(*this)){
+        out = "0";
+    }
+    else{
+        std::pair <uint128_t, uint128_t> qr(*this, uint128_0);
+        do{
+            qr = divmod(qr.first, base);
+            out = "0123456789abcdef"[(uint8_t) qr.second] + out;
+        } while (qr.first);
+    }
+    if (out.size() < len){
+        out = std::string(len - out.size(), '0') + out;
+    }
+    return out;
+}
+
+uint128_t operator<<(const bool & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const uint8_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const uint16_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const uint32_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const uint64_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const int8_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const int16_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const int32_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator<<(const int64_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) << rhs;
+}
+
+uint128_t operator>>(const bool & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const uint8_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const uint16_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const uint32_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const uint64_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const int8_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const int16_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const int32_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+uint128_t operator>>(const int64_t & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) >> rhs;
+}
+
+std::ostream & operator<<(std::ostream & stream, const uint128_t & rhs){
+    if (stream.flags() & stream.oct){
+        stream << rhs.str(8);
+    }
+    else if (stream.flags() & stream.dec){
+        stream << rhs.str(10);
+    }
+    else if (stream.flags() & stream.hex){
+        stream << rhs.str(16);
+    }
+    return stream;
+}

+ 521 - 0
crypt/uint128_t.h

@@ -0,0 +1,521 @@
+#ifndef _UINT128_H_
+#define _UINT128_H_
+#ifndef _UINT128_T_CONFIG_
+  #define _UINT128_T_CONFIG_
+  #if defined(_MSC_VER)
+    #if defined(_DLL)
+      #define _UINT128_T_EXPORT __declspec(dllexport)
+      #define _UINT128_T_IMPORT __declspec(dllimport)
+    #else
+      #define _UINT128_T_EXPORT
+      #define _UINT128_T_IMPORT
+    #endif
+  #else
+    // All modules on Unix are compiled with -fvisibility=hidden
+    // All API symbols get visibility default
+    // whether or not we're static linking or dynamic linking (with -fPIC)
+    #define _UINT128_T_EXPORT __attribute__((visibility("default")))
+    #define _UINT128_T_IMPORT __attribute__((visibility("default")))
+  #endif
+#endif
+#define UINT128_T_EXTERN _UINT128_T_IMPORT
+/*
+uint128_t.h
+An unsigned 128 bit integer type for C++
+
+Copyright (c) 2013 - 2017 Jason Lee @ calccrypto at gmail.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+With much help from Auston Sterling
+
+Thanks to Stefan Deigmüller for finding
+a bug in operator*.
+
+Thanks to François Dessenne for convincing me
+to do a general rewrite of this class.
+*/
+
+#ifndef __UINT128_T__
+#define __UINT128_T__
+
+#include <cstdint>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+class UINT128_T_EXTERN uint128_t;
+
+// Give uint128_t type traits
+namespace std {  // This is probably not a good idea
+    template <> struct is_arithmetic <uint128_t> : std::true_type {};
+    template <> struct is_integral   <uint128_t> : std::true_type {};
+    template <> struct is_unsigned   <uint128_t> : std::true_type {};
+}
+
+class uint128_t{
+    private:
+        uint64_t UPPER, LOWER;
+
+    public:
+        // Constructors
+        uint128_t();
+        uint128_t(const uint128_t & rhs);
+        uint128_t(uint128_t && rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t(const T & rhs)
+            : UPPER(0), LOWER(rhs)
+        {}
+
+        template <typename S, typename T, typename = typename std::enable_if <std::is_integral<S>::value && std::is_integral<T>::value, void>::type>
+        uint128_t(const S & upper_rhs, const T & lower_rhs)
+            : UPPER(upper_rhs), LOWER(lower_rhs)
+        {}
+
+        //  RHS input args only
+
+        // Assignment Operator
+        uint128_t & operator=(const uint128_t & rhs);
+        uint128_t & operator=(uint128_t && rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator=(const T & rhs){
+            UPPER = 0;
+            LOWER = rhs;
+            return *this;
+        }
+
+        // Typecast Operators
+        operator bool() const;
+        operator uint8_t() const;
+        operator uint16_t() const;
+        operator uint32_t() const;
+        operator uint64_t() const;
+
+        // Bitwise Operators
+        uint128_t operator&(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator&(const T & rhs) const{
+            return uint128_t(0, LOWER & (uint64_t) rhs);
+        }
+
+        uint128_t & operator&=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator&=(const T & rhs){
+            UPPER = 0;
+            LOWER &= rhs;
+            return *this;
+        }
+
+        uint128_t operator|(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator|(const T & rhs) const{
+            return uint128_t(UPPER, LOWER | (uint64_t) rhs);
+        }
+
+        uint128_t & operator|=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator|=(const T & rhs){
+            LOWER |= (uint64_t) rhs;
+            return *this;
+        }
+
+        uint128_t operator^(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator^(const T & rhs) const{
+            return uint128_t(UPPER, LOWER ^ (uint64_t) rhs);
+        }
+
+        uint128_t & operator^=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator^=(const T & rhs){
+            LOWER ^= (uint64_t) rhs;
+            return *this;
+        }
+
+        uint128_t operator~() const;
+
+        // Bit Shift Operators
+        uint128_t operator<<(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator<<(const T & rhs) const{
+            return *this << uint128_t(rhs);
+        }
+
+        uint128_t & operator<<=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator<<=(const T & rhs){
+            *this = *this << uint128_t(rhs);
+            return *this;
+        }
+
+        uint128_t operator>>(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator>>(const T & rhs) const{
+            return *this >> uint128_t(rhs);
+        }
+
+        uint128_t & operator>>=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator>>=(const T & rhs){
+            *this = *this >> uint128_t(rhs);
+            return *this;
+        }
+
+        // Logical Operators
+        bool operator!() const;
+        bool operator&&(const uint128_t & rhs) const;
+        bool operator||(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator&&(const T & rhs){
+            return static_cast <bool> (*this && rhs);
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator||(const T & rhs){
+            return static_cast <bool> (*this || rhs);
+        }
+
+        // Comparison Operators
+        bool operator==(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator==(const T & rhs) const{
+            return (!UPPER && (LOWER == (uint64_t) rhs));
+        }
+
+        bool operator!=(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator!=(const T & rhs) const{
+            return (UPPER | (LOWER != (uint64_t) rhs));
+        }
+
+        bool operator>(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator>(const T & rhs) const{
+            return (UPPER || (LOWER > (uint64_t) rhs));
+        }
+
+        bool operator<(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator<(const T & rhs) const{
+            return (!UPPER)?(LOWER < (uint64_t) rhs):false;
+        }
+
+        bool operator>=(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator>=(const T & rhs) const{
+            return ((*this > rhs) | (*this == rhs));
+        }
+
+        bool operator<=(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        bool operator<=(const T & rhs) const{
+            return ((*this < rhs) | (*this == rhs));
+        }
+
+        // Arithmetic Operators
+        uint128_t operator+(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator+(const T & rhs) const{
+            return uint128_t(UPPER + ((LOWER + (uint64_t) rhs) < LOWER), LOWER + (uint64_t) rhs);
+        }
+
+        uint128_t & operator+=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator+=(const T & rhs){
+            UPPER = UPPER + ((LOWER + rhs) < LOWER);
+            LOWER = LOWER + rhs;
+            return *this;
+        }
+
+        uint128_t operator-(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator-(const T & rhs) const{
+            return uint128_t((uint64_t) (UPPER - ((LOWER - rhs) > LOWER)), (uint64_t) (LOWER - rhs));
+        }
+
+        uint128_t & operator-=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator-=(const T & rhs){
+            *this = *this - rhs;
+            return *this;
+        }
+
+        uint128_t operator*(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator*(const T & rhs) const{
+            return *this * uint128_t(rhs);
+        }
+
+        uint128_t & operator*=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator*=(const T & rhs){
+            *this = *this * uint128_t(rhs);
+            return *this;
+        }
+
+    private:
+        std::pair <uint128_t, uint128_t> divmod(const uint128_t & lhs, const uint128_t & rhs) const;
+
+    public:
+        uint128_t operator/(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator/(const T & rhs) const{
+            return *this / uint128_t(rhs);
+        }
+
+        uint128_t & operator/=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator/=(const T & rhs){
+            *this = *this / uint128_t(rhs);
+            return *this;
+        }
+
+        uint128_t operator%(const uint128_t & rhs) const;
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t operator%(const T & rhs) const{
+            return *this % uint128_t(rhs);
+        }
+
+        uint128_t & operator%=(const uint128_t & rhs);
+
+        template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+        uint128_t & operator%=(const T & rhs){
+            *this = *this % uint128_t(rhs);
+            return *this;
+        }
+
+        // Increment Operator
+        uint128_t & operator++();
+        uint128_t operator++(int);
+
+        // Decrement Operator
+        uint128_t & operator--();
+        uint128_t operator--(int);
+
+        // Nothing done since promotion doesn't work here
+        uint128_t operator+() const;
+
+        // two's complement
+        uint128_t operator-() const;
+
+        // Get private values
+        const uint64_t & upper() const;
+        const uint64_t & lower() const;
+
+        // Get bitsize of value
+        uint8_t bits() const;
+
+        // Get string representation of value
+        std::string str(uint8_t base = 10, const unsigned int & len = 0) const;
+};
+
+// useful values
+UINT128_T_EXTERN extern const uint128_t uint128_0;
+UINT128_T_EXTERN extern const uint128_t uint128_1;
+
+// lhs type T as first arguemnt
+// If the output is not a bool, casts to type T
+
+// Bitwise Operators
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator&(const T & lhs, const uint128_t & rhs){
+    return rhs & lhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator&=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (rhs & lhs);
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator|(const T & lhs, const uint128_t & rhs){
+    return rhs | lhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator|=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (rhs | lhs);
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator^(const T & lhs, const uint128_t & rhs){
+    return rhs ^ lhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator^=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (rhs ^ lhs);
+}
+
+// Bitshift operators
+UINT128_T_EXTERN uint128_t operator<<(const bool     & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const uint8_t  & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const uint16_t & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const uint32_t & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const uint64_t & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const int8_t   & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const int16_t  & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const int32_t  & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator<<(const int64_t  & lhs, const uint128_t & rhs);
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator<<=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (uint128_t(lhs) << rhs);
+}
+
+UINT128_T_EXTERN uint128_t operator>>(const bool     & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const uint8_t  & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const uint16_t & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const uint32_t & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const uint64_t & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const int8_t   & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const int16_t  & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const int32_t  & lhs, const uint128_t & rhs);
+UINT128_T_EXTERN uint128_t operator>>(const int64_t  & lhs, const uint128_t & rhs);
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator>>=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (uint128_t(lhs) >> rhs);
+}
+
+// Comparison Operators
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+bool operator==(const T & lhs, const uint128_t & rhs){
+    return (!rhs.upper() && ((uint64_t) lhs == rhs.lower()));
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+bool operator!=(const T & lhs, const uint128_t & rhs){
+    return (rhs.upper() | ((uint64_t) lhs != rhs.lower()));
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+bool operator>(const T & lhs, const uint128_t & rhs){
+    return (!rhs.upper()) && ((uint64_t) lhs > rhs.lower());
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+bool operator<(const T & lhs, const uint128_t & rhs){
+    if (rhs.upper()){
+        return true;
+    }
+    return ((uint64_t) lhs < rhs.lower());
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+bool operator>=(const T & lhs, const uint128_t & rhs){
+    if (rhs.upper()){
+        return false;
+    }
+    return ((uint64_t) lhs >= rhs.lower());
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+bool operator<=(const T & lhs, const uint128_t & rhs){
+    if (rhs.upper()){
+        return true;
+    }
+    return ((uint64_t) lhs <= rhs.lower());
+}
+
+// Arithmetic Operators
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator+(const T & lhs, const uint128_t & rhs){
+    return rhs + lhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator+=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (rhs + lhs);
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator-(const T & lhs, const uint128_t & rhs){
+    return -(rhs - lhs);
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator-=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (-(rhs - lhs));
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator*(const T & lhs, const uint128_t & rhs){
+    return rhs * lhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator*=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (rhs * lhs);
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator/(const T & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) / rhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator/=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (uint128_t(lhs) / rhs);
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+uint128_t operator%(const T & lhs, const uint128_t & rhs){
+    return uint128_t(lhs) % rhs;
+}
+
+template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
+T & operator%=(T & lhs, const uint128_t & rhs){
+    return lhs = static_cast <T> (uint128_t(lhs) % rhs);
+}
+
+// IO Operator
+UINT128_T_EXTERN std::ostream & operator<<(std::ostream & stream, const uint128_t & rhs);
+#endif
+#endif

BIN
crypt/uint128_t.o


+ 5 - 2
test.cpp

@@ -50,8 +50,11 @@ unsigned long long multTest(size_t s){
 	return std::accumulate(times.begin(), times.end(), 0ULL);
 }
 int main(){
-	BigInt a(~(0ULL)),b(~(0ULL));
-	std::cout << a.mult(b).toString() << std::endl;
+	BigInt a(gen, 2);
+	BigInt b(gen, 2);
+	std::cout << a.toString() << "  " << b.toString() << std::endl;
+	a = a.mult(b);
+	std::cout << a.toString() << std::endl;
 	multTest(50);
 	multTest(100);
 	multTest(200);