diff --git a/Makefile b/Makefile index 2c8163f..c4680c9 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ quick-verify: $(PROG) $(SCRIPTS)/verify.py $(DATA)/spneumoniae.fa $(PROG): $(SRC)/main.cpp $(SRC)/$(wildcard *.cpp *.h *.hpp) src/version.h ./create-version.sh - $(CXX) $(CXXFLAGS) $(SRC)/main.cpp $(SRC)/kthread.c -o $@ $(LDFLAGS) + $(CXX) $(CXXFLAGS) $(SRC)/main.cpp $(SRC)/uint256_t.cpp $(SRC)/kthread.c -o $@ $(LDFLAGS) prophasmtest: $(TESTS)/unittest.cpp gtest-all.o $(SRC)/$(wildcard *.cpp *.h *.hpp) $(TESTS)/$(wildcard *.cpp *.h *.hpp) diff --git a/src/khash_utils.h b/src/khash_utils.h index eab13a0..3ac2d99 100644 --- a/src/khash_utils.h +++ b/src/khash_utils.h @@ -6,20 +6,29 @@ #include "kmers.h" #include "khash.h" +typedef unsigned char byte; #define kh_int128_hash_func(key) kh_int64_hash_func((khint64_t)((key)>>65^(key)^(key)<<21)) #define kh_int128_hash_equal(a, b) ((a) == (b)) +#define kh_int256_hash_func(key) kh_int128_hash_func((__uint128_t)((key)>>129^(key)^(key)<<35)) +#define kh_int256_hash_equal(a, b) ((a) == (b)) #define KHASH_MAP_INIT_INT128(name, khval_t) \ KHASH_INIT(name, __uint128_t, khval_t, 1, kh_int128_hash_func, kh_int128_hash_equal) #define KHASH_SET_INIT_INT128(name) \ - KHASH_INIT(name, __uint128_t, char, 0, kh_int128_hash_func, kh_int128_hash_equal) + KHASH_INIT(name, __uint128_t, byte, 0, kh_int128_hash_func, kh_int256_hash_equal) -typedef unsigned char byte; +#define KHASH_MAP_INIT_INT256(name, khval_t) \ + KHASH_INIT(name, uint256_t, khval_t, 1, kh_int256_hash_func, kh_int128_hash_equal) + +#define KHASH_SET_INIT_INT256(name) \ + KHASH_INIT(name, uint256_t, byte, 0, kh_int256_hash_func, kh_int256_hash_equal) +KHASH_MAP_INIT_INT256(S256M, byte) KHASH_MAP_INIT_INT128(S128M, byte) KHASH_MAP_INIT_INT64(S64M, byte) +KHASH_SET_INIT_INT256(S256S) KHASH_SET_INIT_INT128(S128S) KHASH_SET_INIT_INT64(S64S) @@ -86,6 +95,8 @@ INIT_KHASH_UTILS(64, 64S) INIT_KHASH_UTILS(64, 64M) INIT_KHASH_UTILS(128, 128S) INIT_KHASH_UTILS(128, 128M) +INIT_KHASH_UTILS(256, 256S) +INIT_KHASH_UTILS(256, 256M) /// Return the next k-mer in the k-mer set and update the index. template diff --git a/src/kmers.h b/src/kmers.h index 996d115..182b1a6 100644 --- a/src/kmers.h +++ b/src/kmers.h @@ -4,8 +4,11 @@ #include #include +#include "uint256_t.h" + typedef uint64_t kmer64_t; typedef __uint128_t kmer128_t; +typedef uint256_t kmer256_t; /// Convert the given basic nucleotide to int so it can be used for indexing in AC. /// If non-existing nucleotide is given, return -1. @@ -71,9 +74,17 @@ inline kmer128_t word_reverse_complement(kmer128_t w) { w = ( w >> 64 ) | ( w << 64); return ((U)-1) - w; } +/// Compute the reverse complement of a word. +/// Copyright: Jellyfish GPL-3.0 +inline kmer256_t word_reverse_complement(kmer256_t w) { + kmer128_t low = word_reverse_complement(w.lower()); + kmer128_t high = word_reverse_complement(w.upper()); + return kmer256_t(high, low); +} constexpr int KMER_SIZE_64 = 64; constexpr int KMER_SIZE_128 = 128; +constexpr int KMER_SIZE_256 = 256; #define INIT_KMERS(type) \ \ /* Get the mask to mask k-mers. */ \ @@ -89,6 +100,7 @@ inline kmer##type##_t ReverseComplement(kmer##type##_t kMer, int k) { INIT_KMERS(64) INIT_KMERS(128) +INIT_KMERS(256) /// Return the lexicographically smaller of the k-mer and its reverse complement. template @@ -102,7 +114,7 @@ const char letters[4] {'A', 'C', 'G', 'T'}; /// Return the index-th nucleotide from the encoded k-mer. template inline char NucleotideAtIndex(kmer_t encoded, int k, int index) { - return letters[(encoded >> ((k - index - kmer_t(1)) << kmer_t(1))) & kmer_t(3)]; + return letters[(unsigned long)(encoded >> ((k - index - kmer_t(1)) << kmer_t(1))) & kmer_t(3)]; } /// Convert the encoded KMer representation to string. @@ -111,7 +123,7 @@ std::string NumberToKMer(kmer_t encoded, int length) { std::string ret(length, 'N'); for (int i = 0; i < length; ++i) { // The last two bits correspond to one nucleotide. - ret[length - i -1] = letters[encoded & 3]; + ret[length - i -1] = letters[(unsigned long)encoded & 3]; // Move to the next letter. encoded >>= 2; } diff --git a/src/main.cpp b/src/main.cpp index 634d6f3..5afcc7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ #include "khash_utils.h" -constexpr int MAX_K = 64; +constexpr int MAX_K = 128; int Help() { @@ -200,6 +200,8 @@ INIT_RUN(64, 64S) INIT_RUN(64, 64M) INIT_RUN(128, 128S) INIT_RUN(128, 128M) +INIT_RUN(256, 256S) +INIT_RUN(256, 256M) int main(int argc, char **argv) { int32_t k = -1; @@ -329,11 +331,17 @@ int main(int argc, char **argv) { } else { return run64M(k, intersectionPath, inPaths, outPaths, statsPath, fstats, computeIntersection, computeOutput, verbose, complements, threads, setCount); } - } else { + } else if (k <= 64) { if (MINIMUM_ABUNDANCE == (byte)1) { return run128S(k, intersectionPath, inPaths, outPaths, statsPath, fstats, computeIntersection, computeOutput, verbose, complements, threads, setCount); } else { return run128M(k, intersectionPath, inPaths, outPaths, statsPath, fstats, computeIntersection, computeOutput, verbose, complements, threads, setCount); } + } else { + if (MINIMUM_ABUNDANCE == (byte)1) { + return run256S(k, intersectionPath, inPaths, outPaths, statsPath, fstats, computeIntersection, computeOutput, verbose, complements, threads, setCount); + } else { + return run256M(k, intersectionPath, inPaths, outPaths, statsPath, fstats, computeIntersection, computeOutput, verbose, complements, threads, setCount); + } } } diff --git a/src/parser.h b/src/parser.h index a756085..cb1c4ea 100644 --- a/src/parser.h +++ b/src/parser.h @@ -82,3 +82,5 @@ INIT_PARSER(64, 64S) INIT_PARSER(64, 64M) INIT_PARSER(128, 128S) INIT_PARSER(128, 128M) +INIT_PARSER(256, 256S) +INIT_PARSER(256, 256M) diff --git a/src/prophasm.h b/src/prophasm.h index 2d7ac43..d099cfb 100644 --- a/src/prophasm.h +++ b/src/prophasm.h @@ -60,7 +60,7 @@ void NextSimplitig(KHT *kMers, kmer_t begin, std::ostream& of, int k, bool comp } else { // Extend the simplitig to the right. eraseKMer(kMers, next, k, complements); - simplitig.emplace_back(letters[ext]); + simplitig.emplace_back(letters[(unsigned int)ext]); last = next; } } else { @@ -71,7 +71,7 @@ void NextSimplitig(KHT *kMers, kmer_t begin, std::ostream& of, int k, bool comp } else { // Extend the simplitig to the left. eraseKMer(kMers, next, k, complements); - simplitig.emplace_front(letters[ext]); + simplitig.emplace_front(letters[(unsigned int)ext]); first = next; } } @@ -121,3 +121,5 @@ INIT_PROPHASM(64, 64S) INIT_PROPHASM(64, 64M) INIT_PROPHASM(128, 128S) INIT_PROPHASM(128, 128M) +INIT_PROPHASM(256, 256S) +INIT_PROPHASM(256, 256M) diff --git a/src/uint256_t.build b/src/uint256_t.build new file mode 100644 index 0000000..114299a --- /dev/null +++ b/src/uint256_t.build @@ -0,0 +1,17 @@ +// IMPLEMENTATION BUILD HEADER + +// We need uint128_t symbols as plain "extern", neither import nor export +// because we're linking the 128 and 256 object files into a single library +// So we can only have one export for symbol in any translation unit +#define UINT256_T_EXTERN +typedef __uint128_t uint128_t; +#undef UINT256_T_EXTERN + +#ifndef _UNIT256_T_BUILD + #define _UINT256_T_BUILD + #include "uint256_t_config.include" + const uint128_t uint128_0(0); + const uint128_t uint128_1(1); + #define UINT256_T_EXTERN _UINT256_T_EXPORT +#endif +#include "uint256_t.include" diff --git a/src/uint256_t.cpp b/src/uint256_t.cpp new file mode 100644 index 0000000..0cc4858 --- /dev/null +++ b/src/uint256_t.cpp @@ -0,0 +1,756 @@ +#define __LITTLE_ENDIAN__ +#include "uint256_t.build" +#include +#include + +const uint128_t uint128_64(64); +const uint128_t uint128_128(128); +const uint128_t uint128_256(256); +const uint256_t uint256_0(0); +const uint256_t uint256_1(1); +const uint256_t uint256_max(uint128_t(-1), uint128_t(-1)); + +/* +uint256_t::uint256_t(const std::string & s, uint8_t base) { + init_from_base(s.c_str(), base); +} + +uint256_t::uint256_t(const char * s, uint8_t base) { + init_from_base(s, base); +} +*/ + +uint256_t::uint256_t(const bool & b) + : uint256_t((uint8_t) b) +{} +/* +void uint256_t::init_from_base(const char * s, uint8_t base) { + *this = 0; + + uint256_t power(1); + uint8_t digit; + int pos = strlen(s) - 1; + while(pos >= 0) { + digit = 0; + if('0' <= s[pos] && s[pos] <= '9') { + digit = s[pos] - '0'; + } else if('a' <= s[pos] && s[pos] <= 'z') { + digit = s[pos] - 'a' + 10; + } + *this += digit * power; + pos--; + power *= base; + } +} +*/ + +uint256_t & uint256_t::operator=(const bool & rhs) { + UPPER = 0; + LOWER = rhs; + return *this; +} + +uint256_t::operator bool() const{ + return (bool) (UPPER | LOWER); +} + +uint256_t::operator uint8_t() const{ + return (uint8_t) LOWER; +} + +uint256_t::operator uint16_t() const{ + return (uint16_t) LOWER; +} + +uint256_t::operator uint32_t() const{ + return (uint32_t) LOWER; +} + +uint256_t::operator uint64_t() const{ + return (uint64_t) LOWER; +} + +uint256_t::operator uint128_t() const{ + return LOWER; +} + +uint256_t uint256_t::operator&(const uint128_t & rhs) const{ + return uint256_t(uint128_0, LOWER & rhs); +} + +uint256_t uint256_t::operator&(const uint256_t & rhs) const{ + return uint256_t(UPPER & rhs.UPPER, LOWER & rhs.LOWER); +} + +uint256_t & uint256_t::operator&=(const uint128_t & rhs){ + UPPER = uint128_0; + LOWER &= rhs; + return *this; +} + +uint256_t & uint256_t::operator&=(const uint256_t & rhs){ + UPPER &= rhs.UPPER; + LOWER &= rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator|(const uint128_t & rhs) const{ + return uint256_t(UPPER , LOWER | rhs); +} + +uint256_t uint256_t::operator|(const uint256_t & rhs) const{ + return uint256_t(UPPER | rhs.UPPER, LOWER | rhs.LOWER); +} + +uint256_t & uint256_t::operator|=(const uint128_t & rhs){ + LOWER |= rhs; + return *this; +} + +uint256_t & uint256_t::operator|=(const uint256_t & rhs){ + UPPER |= rhs.UPPER; + LOWER |= rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator^(const uint128_t & rhs) const{ + return uint256_t(UPPER, LOWER ^ rhs); +} + +uint256_t uint256_t::operator^(const uint256_t & rhs) const{ + return uint256_t(UPPER ^ rhs.UPPER, LOWER ^ rhs.LOWER); +} + +uint256_t & uint256_t::operator^=(const uint128_t & rhs){ + LOWER ^= rhs; + return *this; +} + +uint256_t & uint256_t::operator^=(const uint256_t & rhs){ + UPPER ^= rhs.UPPER; + LOWER ^= rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator~() const{ + return uint256_t(~UPPER, ~LOWER); +} + +uint256_t uint256_t::operator<<(const uint128_t & rhs) const{ + return *this << uint256_t(rhs); +} + +uint256_t uint256_t::operator<<(const uint256_t & rhs) const{ + const uint128_t shift = rhs.LOWER; + if (((bool) rhs.UPPER) || (shift >= uint128_256)){ + return uint256_0; + } + else if (shift == uint128_128){ + return uint256_t(LOWER, uint128_0); + } + else if (shift == uint128_0){ + return *this; + } + else if (shift < uint128_128){ + return uint256_t((UPPER << shift) + (LOWER >> (uint128_128 - shift)), LOWER << shift); + } + else if ((uint128_256 > shift) && (shift > uint128_128)){ + return uint256_t(LOWER << (shift - uint128_128), uint128_0); + } + else{ + return uint256_0; + } +} + +uint256_t & uint256_t::operator<<=(const uint128_t & shift){ + return *this <<= uint256_t(shift); +} + +uint256_t & uint256_t::operator<<=(const uint256_t & shift){ + *this = *this << shift; + return *this; +} + +uint256_t uint256_t::operator>>(const uint128_t & rhs) const{ + return *this >> uint256_t(rhs); +} + +uint256_t uint256_t::operator>>(const uint256_t & rhs) const{ + const uint128_t shift = rhs.LOWER; + if (((bool) rhs.UPPER) | (shift >= uint128_256)){ + return uint256_0; + } + else if (shift == uint128_128){ + return uint256_t(UPPER); + } + else if (shift == uint128_0){ + return *this; + } + else if (shift < uint128_128){ + return uint256_t(UPPER >> shift, (UPPER << (uint128_128 - shift)) + (LOWER >> shift)); + } + else if ((uint128_256 > shift) && (shift > uint128_128)){ + return uint256_t(UPPER >> (shift - uint128_128)); + } + else{ + return uint256_0; + } +} + +uint256_t & uint256_t::operator>>=(const uint128_t & shift){ + return *this >>= uint256_t(shift); +} + +uint256_t & uint256_t::operator>>=(const uint256_t & shift){ + *this = *this >> shift; + return *this; +} + +bool uint256_t::operator!() const{ + return ! (bool) *this; +} + +bool uint256_t::operator&&(const uint128_t & rhs) const{ + return (*this && uint256_t(rhs)); +} + +bool uint256_t::operator&&(const uint256_t & rhs) const{ + return ((bool) *this && (bool) rhs); +} + +bool uint256_t::operator||(const uint128_t & rhs) const{ + return (*this || uint256_t(rhs)); +} + +bool uint256_t::operator||(const uint256_t & rhs) const{ + return ((bool) *this || (bool) rhs); +} + +bool uint256_t::operator==(const uint128_t & rhs) const{ + return (*this == uint256_t(rhs)); +} + +bool uint256_t::operator==(const uint256_t & rhs) const{ + return ((UPPER == rhs.UPPER) && (LOWER == rhs.LOWER)); +} + +bool uint256_t::operator!=(const uint128_t & rhs) const{ + return (*this != uint256_t(rhs)); +} + +bool uint256_t::operator!=(const uint256_t & rhs) const{ + return ((UPPER != rhs.UPPER) | (LOWER != rhs.LOWER)); +} + +bool uint256_t::operator>(const uint128_t & rhs) const{ + return (*this > uint256_t(rhs)); +} + +bool uint256_t::operator>(const uint256_t & rhs) const{ + if (UPPER == rhs.UPPER){ + return (LOWER > rhs.LOWER); + } + if (UPPER > rhs.UPPER){ + return true; + } + return false; +} + +bool uint256_t::operator<(const uint128_t & rhs) const{ + return (*this < uint256_t(rhs)); +} + +bool uint256_t::operator<(const uint256_t & rhs) const{ + if (UPPER == rhs.UPPER){ + return (LOWER < rhs.LOWER); + } + if (UPPER < rhs.UPPER){ + return true; + } + return false; +} + +bool uint256_t::operator>=(const uint128_t & rhs) const{ + return (*this >= uint256_t(rhs)); +} + +bool uint256_t::operator>=(const uint256_t & rhs) const{ + return ((*this > rhs) | (*this == rhs)); +} + +bool uint256_t::operator<=(const uint128_t & rhs) const{ + return (*this <= uint256_t(rhs)); +} + +bool uint256_t::operator<=(const uint256_t & rhs) const{ + return ((*this < rhs) | (*this == rhs)); +} + +uint256_t uint256_t::operator+(const uint128_t & rhs) const{ + return *this + uint256_t(rhs); +} + +uint256_t uint256_t::operator+(const uint256_t & rhs) const{ + return uint256_t(UPPER + rhs.UPPER + (((LOWER + rhs.LOWER) < LOWER)?uint128_1:uint128_0), LOWER + rhs.LOWER); +} + +uint256_t & uint256_t::operator+=(const uint128_t & rhs){ + return *this += uint256_t(rhs); +} + +uint256_t & uint256_t::operator+=(const uint256_t & rhs){ + UPPER = rhs.UPPER + UPPER + ((LOWER + rhs.LOWER) < LOWER); + LOWER = LOWER + rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator-(const uint128_t & rhs) const{ + return *this - uint256_t(rhs); +} + +uint256_t uint256_t::operator-(const uint256_t & rhs) const{ + return uint256_t(UPPER - rhs.UPPER - ((LOWER - rhs.LOWER) > LOWER), LOWER - rhs.LOWER); +} + +uint256_t & uint256_t::operator-=(const uint128_t & rhs){ + return *this -= uint256_t(rhs); +} + +uint256_t & uint256_t::operator-=(const uint256_t & rhs){ + *this = *this - rhs; + return *this; +} + +/* +uint256_t uint256_t::operator*(const uint128_t & rhs) const{ + return *this * uint256_t(rhs); +} + */ + +/* +uint256_t uint256_t::operator*(const uint256_t & rhs) const{ + // split values into 4 64-bit parts + uint128_t top[4] = {UPPER.upper(), UPPER.lower(), LOWER.upper(), LOWER.lower()}; + uint128_t bottom[4] = {rhs.upper().upper(), rhs.upper().lower(), rhs.lower().upper(), rhs.lower().lower()}; + uint128_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 - y][x] = top[x] * bottom[y]; + } + } + + // first row + uint128_t fourth64 = uint128_t(products[0][3].lower()); + uint128_t third64 = uint128_t(products[0][2].lower()) + uint128_t(products[0][3].upper()); + uint128_t second64 = uint128_t(products[0][1].lower()) + uint128_t(products[0][2].upper()); + uint128_t first64 = uint128_t(products[0][0].lower()) + uint128_t(products[0][1].upper()); + + // second row + third64 += uint128_t(products[1][3].lower()); + second64 += uint128_t(products[1][2].lower()) + uint128_t(products[1][3].upper()); + first64 += uint128_t(products[1][1].lower()) + uint128_t(products[1][2].upper()); + + // third row + second64 += uint128_t(products[2][3].lower()); + first64 += uint128_t(products[2][2].lower()) + uint128_t(products[2][3].upper()); + + // fourth row + first64 += uint128_t(products[3][3].lower()); + + // combines the values, taking care of carry over + return uint256_t(first64 << uint128_64, uint128_0) + + uint256_t(third64.upper(), third64 << uint128_64) + + uint256_t(second64, uint128_0) + + uint256_t(fourth64); +} + */ + +/* +uint256_t & uint256_t::operator*=(const uint128_t & rhs){ + return *this *= uint256_t(rhs); +} + +uint256_t & uint256_t::operator*=(const uint256_t & rhs){ + *this = *this * rhs; + return *this; +} + */ + +/* +std::pair uint256_t::divmod(const uint256_t & lhs, const uint256_t & rhs) const{ + // Save some calculations ///////////////////// + if (rhs == uint256_0){ + throw std::domain_error("Error: division or modulus by 0"); + } + else if (rhs == uint256_1){ + return std::pair (lhs, uint256_0); + } + else if (lhs == rhs){ + return std::pair (uint256_1, uint256_0); + } + else if ((lhs == uint256_0) || (lhs < rhs)){ + return std::pair (uint256_0, lhs); + } + + std::pair qr(uint256_0, lhs); + uint256_t copyd = rhs << (lhs.bits() - rhs.bits()); + uint256_t adder = uint256_1 << (lhs.bits() - rhs.bits()); + if (copyd > qr.second){ + copyd >>= uint256_1; + adder >>= uint256_1; + } + while (qr.second >= rhs){ + if (qr.second >= copyd){ + qr.second -= copyd; + qr.first |= adder; + } + copyd >>= uint256_1; + adder >>= uint256_1; + } + return qr; +} + + +uint256_t uint256_t::operator/(const uint128_t & rhs) const{ + return *this / uint256_t(rhs); +} + +uint256_t uint256_t::operator/(const uint256_t & rhs) const{ + return divmod(*this, rhs).first; +} + +uint256_t & uint256_t::operator/=(const uint128_t & rhs){ + return *this /= uint256_t(rhs); +} + +uint256_t & uint256_t::operator/=(const uint256_t & rhs){ + *this = *this / rhs; + return *this; +} + +uint256_t uint256_t::operator%(const uint128_t & rhs) const{ + return *this % uint256_t(rhs); +} + +uint256_t uint256_t::operator%(const uint256_t & rhs) const{ + return *this - (rhs * (*this / rhs)); +} + +uint256_t & uint256_t::operator%=(const uint128_t & rhs){ + return *this %= uint256_t(rhs); +} + +uint256_t & uint256_t::operator%=(const uint256_t & rhs){ + *this = *this % rhs; + return *this; +} + */ + +uint256_t & uint256_t::operator++(){ + *this += uint256_1; + return *this; +} + +uint256_t uint256_t::operator++(int){ + uint256_t temp(*this); + ++*this; + return temp; +} + +uint256_t & uint256_t::operator--(){ + *this -= uint256_1; + return *this; +} + +uint256_t uint256_t::operator--(int){ + uint256_t temp(*this); + --*this; + return temp; +} + +uint256_t uint256_t::operator+() const{ + return *this; +} + +uint256_t uint256_t::operator-() const{ + return ~*this + uint256_1; +} + +const uint128_t & uint256_t::upper() const { + return UPPER; +} + +const uint128_t & uint256_t::lower() const { + return LOWER; +} + +/* +std::vector uint256_t::export_bits() const { + std::vector ret; + ret.reserve(32); + UPPER.export_bits(ret); + LOWER.export_bits(ret); + return ret; +} + +std::vector uint256_t::export_bits_truncate() const { + std::vector ret = export_bits(); + + //prune the zeroes + int i = 0; + while (ret[i] == 0 && i < 64) i++; + ret.erase(ret.begin(), ret.begin() + i); + + return ret; +} + +uint16_t uint256_t::bits() const{ + uint16_t out = 0; + if (UPPER){ + out = 128; + uint128_t up = UPPER; + while (up){ + up >>= uint128_1; + out++; + } + } + else{ + uint128_t low = LOWER; + while (low){ + low >>= uint128_1; + out++; + } + } + return out; +} + */ + +/* +std::string uint256_t::str(uint8_t base, const unsigned int & len) const{ + if ((base < 2) || (base > 36)){ + throw std::invalid_argument("Base must be in the range 2-36"); + } + std::string out = ""; + if (!(*this)){ + out = "0"; + } + else{ + std::pair qr(*this, uint256_0); + do{ + qr = divmod(qr.first, base); + out = "0123456789abcdefghijklmnopqrstuvwxyz"[(uint8_t) qr.second] + out; + } while (qr.first); + } + if (out.size() < len){ + out = std::string(len - out.size(), '0') + out; + } + return out; +} +*/ + +uint256_t operator&(const uint128_t & lhs, const uint256_t & rhs){ + return rhs & lhs; +} + +uint128_t & operator&=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs & lhs).lower(); + return lhs; +} + +uint256_t operator|(const uint128_t & lhs, const uint256_t & rhs){ + return rhs | lhs; +} + +uint128_t & operator|=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs | lhs).lower(); + return lhs; +} + +uint256_t operator^(const uint128_t & lhs, const uint256_t & rhs){ + return rhs ^ lhs; +} + +uint128_t & operator^=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs ^ lhs).lower(); + return lhs; +} + +uint256_t operator<<(const bool & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint128_t & operator<<=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) << rhs).lower(); + return lhs; +} + +uint256_t operator>>(const bool & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint128_t & operator>>=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) >> rhs).lower(); + return lhs; +} + +// Comparison Operators +bool operator==(const uint128_t & lhs, const uint256_t & rhs){ + return rhs == lhs; +} + +bool operator!=(const uint128_t & lhs, const uint256_t & rhs){ + return rhs != lhs; +} + +bool operator>(const uint128_t & lhs, const uint256_t & rhs){ + return rhs < lhs; +} + +bool operator<(const uint128_t & lhs, const uint256_t & rhs){ + return rhs > lhs; +} + +bool operator>=(const uint128_t & lhs, const uint256_t & rhs){ + return rhs <= lhs; +} + +bool operator<=(const uint128_t & lhs, const uint256_t & rhs){ + return rhs >= lhs; +} + +// Arithmetic Operators +uint256_t operator+(const uint128_t & lhs, const uint256_t & rhs){ + return rhs + lhs; +} + +uint128_t & operator+=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs + lhs).lower(); + return lhs; +} + +uint256_t operator-(const uint128_t & lhs, const uint256_t & rhs){ + return -(rhs - lhs); +} + +uint128_t & operator-=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (-(rhs - lhs)).lower(); + return lhs; +} + +/* +uint256_t operator*(const uint128_t & lhs, const uint256_t & rhs){ + return rhs * lhs; +} + +uint128_t & operator*=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs * lhs).lower(); + return lhs; +} + +uint256_t operator/(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) / rhs; +} + +uint128_t & operator/=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) / rhs).lower(); + return lhs; +} + +uint256_t operator%(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) % rhs; +} + +uint128_t & operator%=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) % rhs).lower(); + return lhs; +} + */ + +/* +std::ostream & operator<<(std::ostream & stream, const uint256_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; +} + */ diff --git a/src/uint256_t.h b/src/uint256_t.h new file mode 100644 index 0000000..1e9f552 --- /dev/null +++ b/src/uint256_t.h @@ -0,0 +1,11 @@ +// PUBLIC IMPORT HEADER +#ifndef _UINT256_H_ +#define _UINT256_H_ +#include "uint256_t_config.include" +#define UINT256_T_EXTERN _UINT256_T_IMPORT +typedef __uint128_t uint128_t; +const uint128_t uint128_0(0); +const uint128_t uint128_1(1); +#define __LITTLE_ENDIAN__ +#include "uint256_t.include" +#endif diff --git a/src/uint256_t.include b/src/uint256_t.include new file mode 100644 index 0000000..5dfa739 --- /dev/null +++ b/src/uint256_t.include @@ -0,0 +1,639 @@ +/* +uint256_t.h +An unsigned 256 bit integer library 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 François Dessenne for convincing me +to do a general rewrite of this class. +*/ + +#ifndef __UINT256_T__ +#define __UINT256_T__ + +#include +#include +#include +#include +#include +#include + +class UINT256_T_EXTERN uint256_t; + +// Give uint256_t type traits +namespace std { // This is probably not a good idea + template <> struct is_arithmetic : std::true_type {}; + template <> struct is_integral : std::true_type {}; + template <> struct is_unsigned : std::true_type {}; +} + +class uint256_t{ + private: +#ifdef __BIG_ENDIAN__ + uint128_t UPPER, LOWER; +#endif +#ifdef __LITTLE_ENDIAN__ + uint128_t LOWER, UPPER; +#endif + + public: + // Constructors + uint256_t() = default; + uint256_t(const uint256_t & rhs) = default; + uint256_t(uint256_t && rhs) = default; + uint256_t(const std::string & s); + uint256_t(const char *val); + uint256_t(const std::string & s, uint8_t base); + uint256_t(const char *val, uint8_t base); + uint256_t(const bool & b); + + template ::value, T>::type > + uint256_t(const T & rhs) +#ifdef __BIG_ENDIAN__ + : UPPER(uint128_0), LOWER(rhs) +#endif +#ifdef __LITTLE_ENDIAN__ + : LOWER(rhs), UPPER(uint128_0) +#endif + { + if (std::is_signed::value) { + if (rhs < 0) { + UPPER = uint128_t(-1); + } + } + } + + template ::value && std::is_integral::value, void>::type> + uint256_t(const S & upper_rhs, const T & lower_rhs) +#ifdef __BIG_ENDIAN__ + : UPPER(upper_rhs), LOWER(lower_rhs) +#endif +#ifdef __LITTLE_ENDIAN__ + : LOWER(lower_rhs), UPPER(upper_rhs) +#endif + {} + + uint256_t(const uint128_t & upper_rhs, const uint128_t & lower_rhs) +#ifdef __BIG_ENDIAN__ + : UPPER(upper_rhs), LOWER(lower_rhs) +#endif +#ifdef __LITTLE_ENDIAN__ + : LOWER(lower_rhs), UPPER(upper_rhs) +#endif + {} + uint256_t(const uint128_t & lower_rhs) +#ifdef __BIG_ENDIAN__ + : UPPER(uint128_0), LOWER(lower_rhs) +#endif +#ifdef __LITTLE_ENDIAN__ + : LOWER(lower_rhs), UPPER(uint128_0) +#endif + {} + + template ::value && + std::is_integral::value && + std::is_integral::value && + std::is_integral::value, void>::type> + uint256_t(const R & upper_lhs, const S & lower_lhs, const T & upper_rhs, const U & lower_rhs) +#ifdef __BIG_ENDIAN__ + : UPPER(upper_lhs, lower_lhs), LOWER(upper_rhs, lower_rhs) +#endif +#ifdef __LITTLE_ENDIAN__ + : LOWER(upper_rhs, lower_rhs), UPPER(upper_lhs, lower_lhs) +#endif + {} + + /* + // RHS input args only + std::vector export_bits() const; + std::vector export_bits_truncate() const; + */ + // Assignment Operator + uint256_t & operator=(const uint256_t & rhs) = default; + uint256_t & operator=(uint256_t && rhs) = default; + + template ::value, T>::type> + uint256_t & operator=(const T & rhs){ + UPPER = uint128_0; + + if (std::is_signed::value) { + if (rhs < 0) { + UPPER = uint128_t(-1); + } + } + + LOWER = rhs; + return *this; + } + + uint256_t & operator=(const bool & rhs); + + // Typecast Operators + operator bool () const; + operator uint8_t () const; + operator uint16_t () const; + operator uint32_t () const; + operator uint64_t () const; + operator uint128_t () const; + + // Bitwise Operators + uint256_t operator&(const uint128_t & rhs) const; + uint256_t operator&(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator&(const T & rhs) const{ + return uint256_t(uint128_0, LOWER & (uint128_t) rhs); + } + + uint256_t & operator&=(const uint128_t & rhs); + uint256_t & operator&=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator&=(const T & rhs){ + UPPER = uint128_0; + LOWER &= rhs; + return *this; + } + + uint256_t operator|(const uint128_t & rhs) const; + uint256_t operator|(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator|(const T & rhs) const{ + return uint256_t(UPPER, LOWER | uint128_t(rhs)); + } + + uint256_t & operator|=(const uint128_t & rhs); + uint256_t & operator|=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator|=(const T & rhs){ + LOWER |= (uint128_t) rhs; + return *this; + } + + uint256_t operator^(const uint128_t & rhs) const; + uint256_t operator^(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator^(const T & rhs) const{ + return uint256_t(UPPER, LOWER ^ (uint128_t) rhs); + } + + uint256_t & operator^=(const uint128_t & rhs); + uint256_t & operator^=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator^=(const T & rhs){ + LOWER ^= (uint128_t) rhs; + return *this; + } + + uint256_t operator~() const; + + // Bit Shift Operators + uint256_t operator<<(const uint128_t & shift) const; + uint256_t operator<<(const uint256_t & shift) const; + + template ::value, T>::type > + uint256_t operator<<(const T & rhs) const{ + return *this << uint256_t(rhs); + } + + uint256_t & operator<<=(const uint128_t & shift); + uint256_t & operator<<=(const uint256_t & shift); + + template ::value, T>::type > + uint256_t & operator<<=(const T & rhs){ + *this = *this << uint256_t(rhs); + return *this; + } + + uint256_t operator>>(const uint128_t & shift) const; + uint256_t operator>>(const uint256_t & shift) const; + + template ::value, T>::type > + uint256_t operator>>(const T & rhs) const{ + return *this >> uint256_t(rhs); + } + + uint256_t & operator>>=(const uint128_t & shift); + uint256_t & operator>>=(const uint256_t & shift); + + template ::value, T>::type > + uint256_t & operator>>=(const T & rhs){ + *this = *this >> uint256_t(rhs); + return *this; + } + + // Logical Operators + bool operator!() const; + + bool operator&&(const uint128_t & rhs) const; + bool operator&&(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator&&(const T & rhs) const{ + return ((bool) *this && rhs); + } + + bool operator||(const uint128_t & rhs) const; + bool operator||(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator||(const T & rhs) const{ + return ((bool) *this || rhs); + } + + // Comparison Operators + bool operator==(const uint128_t & rhs) const; + bool operator==(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator==(const T & rhs) const{ + return (!UPPER && (LOWER == uint128_t(rhs))); + } + + bool operator!=(const uint128_t & rhs) const; + bool operator!=(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator!=(const T & rhs) const{ + return ((bool) UPPER | (LOWER != uint128_t(rhs))); + } + + bool operator>(const uint128_t & rhs) const; + bool operator>(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator>(const T & rhs) const{ + return ((bool) UPPER | (LOWER > uint128_t(rhs))); + } + + bool operator<(const uint128_t & rhs) const; + bool operator<(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator<(const T & rhs) const{ + return (!UPPER)?(LOWER < uint128_t(rhs)):false; + } + + bool operator>=(const uint128_t & rhs) const; + bool operator>=(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator>=(const T & rhs) const{ + return ((*this > rhs) | (*this == rhs)); + } + + bool operator<=(const uint128_t & rhs) const; + bool operator<=(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator<=(const T & rhs) const{ + return ((*this < rhs) | (*this == rhs)); + } + + // Arithmetic Operators + uint256_t operator+(const uint128_t & rhs) const; + uint256_t operator+(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator+(const T & rhs) const{ + return uint256_t(UPPER + ((LOWER + (uint128_t) rhs) < LOWER), LOWER + (uint128_t) rhs); + } + + uint256_t & operator+=(const uint128_t & rhs); + uint256_t & operator+=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator+=(const T & rhs){ + return *this += uint256_t(rhs); + } + + uint256_t operator-(const uint128_t & rhs) const; + uint256_t operator-(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator-(const T & rhs) const{ + return uint256_t(UPPER - ((LOWER - rhs) > LOWER), LOWER - rhs); + } + + uint256_t & operator-=(const uint128_t & rhs); + uint256_t & operator-=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator-=(const T & rhs){ + return *this = *this - uint256_t(rhs); + } + + /* + uint256_t operator*(const uint128_t & rhs) const; + uint256_t operator*(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator*(const T & rhs) const{ + return *this * uint256_t(rhs); + } + uint256_t & operator*=(const uint128_t & rhs); + uint256_t & operator*=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator*=(const T & rhs){ + return *this = *this * uint256_t(rhs); + } +*/ + + private: + std::pair divmod(const uint256_t & lhs, const uint256_t & rhs) const; + void init(const char * s); + void init_from_base(const char * s, uint8_t base); + + public: + uint256_t operator/(const uint128_t & rhs) const; + uint256_t operator/(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator/(const T & rhs) const{ + return *this / uint256_t(rhs); + } + + uint256_t & operator/=(const uint128_t & rhs); + uint256_t & operator/=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator/=(const T & rhs){ + return *this = *this / uint256_t(rhs); + } + + uint256_t operator%(const uint128_t & rhs) const; + uint256_t operator%(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator%(const T & rhs) const{ + return *this % uint256_t(rhs); + } + + uint256_t & operator%=(const uint128_t & rhs); + uint256_t & operator%=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator%=(const T & rhs){ + return *this = *this % uint256_t(rhs); + } + + // Increment Operators + uint256_t & operator++(); + uint256_t operator++(int); + + // Decrement Operators + uint256_t & operator--(); + uint256_t operator--(int); + + // Nothing done since promotion doesn't work here + uint256_t operator+() const; + + // two's complement + uint256_t operator-() const; + + // Get private values + const uint128_t & upper() const; + const uint128_t & lower() const; + + // Get bitsize of value + uint16_t bits() const; + + // Get string representation of value + std::string str(uint8_t base = 10, const unsigned int & len = 0) const; +}; + +// useful values +UINT256_T_EXTERN extern const uint128_t uint128_64; +UINT256_T_EXTERN extern const uint128_t uint128_128; +UINT256_T_EXTERN extern const uint128_t uint128_256; +UINT256_T_EXTERN extern const uint256_t uint256_0; +UINT256_T_EXTERN extern const uint256_t uint256_1; +UINT256_T_EXTERN extern const uint256_t uint256_max; + +// Bitwise Operators +UINT256_T_EXTERN uint256_t operator&(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > + uint256_t operator&(const T & lhs, const uint256_t & rhs){ + return rhs & lhs; +} + +UINT256_T_EXTERN uint128_t & operator&=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator&=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs & lhs); +} + +UINT256_T_EXTERN uint256_t operator|(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator|(const T & lhs, const uint256_t & rhs){ + return rhs | lhs; +} + +UINT256_T_EXTERN uint128_t & operator|=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator|=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs | lhs); +} + +UINT256_T_EXTERN uint256_t operator^(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator^(const T & lhs, const uint256_t & rhs){ + return rhs ^ lhs; +} + +uint128_t & operator^=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator^=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs ^ lhs); +} + +// Bitshift operators +UINT256_T_EXTERN uint256_t operator<<(const bool & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint64_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint128_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int64_t & lhs, const uint256_t & rhs); + +UINT256_T_EXTERN uint128_t & operator<<=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator<<=(T & lhs, const uint256_t & rhs){ + lhs = static_cast (uint256_t(lhs) << rhs); + return lhs; +} + +UINT256_T_EXTERN uint256_t operator>>(const bool & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint64_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint128_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int64_t & lhs, const uint256_t & rhs); + +UINT256_T_EXTERN uint128_t & operator>>=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator>>=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (uint256_t(lhs) >> rhs); +} + +// Comparison Operators +UINT256_T_EXTERN bool operator==(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator==(const T & lhs, const uint256_t & rhs){ + return (!rhs.upper() && ((uint64_t) lhs == rhs.lower())); +} + +UINT256_T_EXTERN bool operator!=(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator!=(const T & lhs, const uint256_t & rhs){ + return (rhs.upper() | ((uint64_t) lhs != rhs.lower())); +} + +UINT256_T_EXTERN bool operator>(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator>(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?false:((uint128_t) lhs > rhs.lower()); +} + +UINT256_T_EXTERN bool operator<(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator<(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?true:((uint128_t) lhs < rhs.lower()); +} + +UINT256_T_EXTERN bool operator>=(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator>=(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?false:((uint128_t) lhs >= rhs.lower()); +} + +UINT256_T_EXTERN bool operator<=(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator<=(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?true:((uint128_t) lhs <= rhs.lower()); +} + +// Arithmetic Operators +UINT256_T_EXTERN uint256_t operator+(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator+(const T & lhs, const uint256_t & rhs){ + return rhs + lhs; +} + +UINT256_T_EXTERN uint128_t & operator+=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator+=(T & lhs, const uint256_t & rhs){ + lhs = static_cast (rhs + lhs); + return lhs; +} + +UINT256_T_EXTERN uint256_t operator-(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator-(const T & lhs, const uint256_t & rhs){ + return -(rhs - lhs); +} + +UINT256_T_EXTERN uint128_t & operator-=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator-=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (-(rhs - lhs)); +} + +/* +UINT256_T_EXTERN uint256_t operator*(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator*(const T & lhs, const uint256_t & rhs){ + return rhs * lhs; +} + +UINT256_T_EXTERN uint128_t & operator*=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator*=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs * lhs); +} + */ + +UINT256_T_EXTERN uint256_t operator/(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator/(const T & lhs, const uint256_t & rhs){ + return uint256_t(lhs) / rhs; +} + +UINT256_T_EXTERN uint128_t & operator/=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator/=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (uint256_t(lhs) / rhs); +} + +UINT256_T_EXTERN uint256_t operator%(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator%(const T & lhs, const uint256_t & rhs){ + return uint256_t(lhs) % rhs; +} + +UINT256_T_EXTERN uint128_t & operator%=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator%=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (uint256_t(lhs) % rhs); +} + +// IO Operator +UINT256_T_EXTERN std::ostream & operator<<(std::ostream & stream, const uint256_t & rhs); +#endif diff --git a/src/uint256_t_config.include b/src/uint256_t_config.include new file mode 100644 index 0000000..e83db51 --- /dev/null +++ b/src/uint256_t_config.include @@ -0,0 +1,19 @@ +#ifndef _UINT256_T_CONFIG_ + #define _UINT256_T_CONFIG_ + #if defined(_MSC_VER) + #if defined(_DLL) + #define _UINT256_T_EXPORT __declspec(dllexport) + #define _UINT256_T_IMPORT __declspec(dllimport) + #else + #define _UINT256_T_EXPORT + #define _UINT256_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 _UINT256_T_EXPORT __attribute__((visibility("default"))) + #define _UINT256_T_IMPORT __attribute__((visibility("default"))) + #endif +#endif +