|
@@ -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
|