123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- #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
|