123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- #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;
- }
|