mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
1107 lines
35 KiB
C++
1107 lines
35 KiB
C++
|
/**
|
||
|
* @file
|
||
|
*
|
||
|
* @details Implementation of 128-bit unsigned integers.
|
||
|
* @note The implementation can be flagged as not completed. This header is used
|
||
|
* with enough operations as a part of bigger integer types 256-bit integer.
|
||
|
* @author [Ashish Daulatabad](https://github.com/AshishYUO)
|
||
|
*/
|
||
|
|
||
|
#include <algorithm> /// for `std::reverse` and other operations
|
||
|
#include <ostream> /// for `std::cout` overload
|
||
|
#include <string> /// for `std::string`
|
||
|
#include <utility> /// for `std::pair` library
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#include <intrin.h> /// for _BitScanForward64 and __BitScanReverse64 operation
|
||
|
#endif
|
||
|
|
||
|
#ifndef CIPHERS_UINT128_T_HPP_
|
||
|
#define CIPHERS_UINT128_T_HPP_
|
||
|
class uint128_t;
|
||
|
|
||
|
template <>
|
||
|
struct std::is_integral<uint128_t> : std::true_type {};
|
||
|
template <>
|
||
|
struct std::is_arithmetic<uint128_t> : std::true_type {};
|
||
|
template <>
|
||
|
struct std::is_unsigned<uint128_t> : std::true_type {};
|
||
|
|
||
|
/**
|
||
|
* @brief Adding two string
|
||
|
* @details Adds two long integer, only used for printing numbers
|
||
|
* @param first First integer string
|
||
|
* @param second Second integer string
|
||
|
* @returns string denoting the addition of both the strings
|
||
|
*/
|
||
|
std::string add(const std::string &first, const std::string &second) {
|
||
|
std::string third;
|
||
|
int16_t sum = 0, carry = 0;
|
||
|
for (int32_t i = static_cast<int32_t>(first.size()) - 1,
|
||
|
j = static_cast<int32_t>(second.size()) - 1;
|
||
|
i >= 0 || j >= 0; --i, --j) {
|
||
|
sum = ((i >= 0 ? first[i] - '0' : 0) + (j >= 0 ? second[j] - '0' : 0) +
|
||
|
carry);
|
||
|
carry = sum / 10;
|
||
|
sum %= 10;
|
||
|
third.push_back(sum + '0');
|
||
|
}
|
||
|
if (carry) {
|
||
|
third.push_back('1');
|
||
|
}
|
||
|
std::reverse(third.begin(), third.end());
|
||
|
return third;
|
||
|
}
|
||
|
/**
|
||
|
* @class uint128_t
|
||
|
* @brief class for 128-bit unsigned integer
|
||
|
*/
|
||
|
class uint128_t {
|
||
|
uint64_t f{}, s{}; /// First and second half of 128 bit number
|
||
|
|
||
|
/**
|
||
|
* @brief Get integer from given string.
|
||
|
* @details Create an integer from a given string
|
||
|
* @param str integer string, can be hexadecimal (starting on 0x... or
|
||
|
* number)
|
||
|
* @returns void
|
||
|
*/
|
||
|
void __get_integer_from_string(const std::string &str) {
|
||
|
this->f = this->s = 0;
|
||
|
if (str.size() > 1 && str[1] == 'x') { // if hexadecimal
|
||
|
for (auto i = 2; i < str.size(); ++i) {
|
||
|
*this *= 16LL;
|
||
|
if (str[i] >= '0' && str[i] <= '9') {
|
||
|
*this += (str[i] - '0');
|
||
|
} else if (str[i] >= 'A' && str[i] <= 'F') {
|
||
|
*this += (str[i] - 'A' + 10);
|
||
|
} else if (str[i] >= 'a' && str[i] <= 'f') {
|
||
|
*this += (str[i] - 'a' + 10);
|
||
|
}
|
||
|
}
|
||
|
} else { // if decimal
|
||
|
for (auto &x : str) {
|
||
|
*this *= 10LL;
|
||
|
*this += (x - '0');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
uint128_t() = default;
|
||
|
|
||
|
/**
|
||
|
* @brief Parameterized constructor
|
||
|
* @tparam T integral type
|
||
|
* @param low lower part 8-bit unisgned integer
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
explicit uint128_t(T low) : s(low) {}
|
||
|
|
||
|
/**
|
||
|
* @brief Parameterized constructor
|
||
|
* @param str Integer string (hexadecimal starting with 0x.. or decimal)
|
||
|
*/
|
||
|
explicit uint128_t(const std::string &str) {
|
||
|
__get_integer_from_string(str);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Parameterized constructor
|
||
|
* @param high higher part 64-bit unsigned integer
|
||
|
* @param low lower part 64-bit unsigned integer
|
||
|
*/
|
||
|
uint128_t(const uint64_t high, const uint64_t low) : f(high), s(low) {}
|
||
|
|
||
|
/**
|
||
|
* @brief Copy constructor
|
||
|
* @param num 128-bit unsigned integer
|
||
|
*/
|
||
|
uint128_t(const uint128_t &num) = default;
|
||
|
|
||
|
/**
|
||
|
* @brief Move constructor
|
||
|
* @param num 128-bit unsigned integer
|
||
|
*/
|
||
|
uint128_t(uint128_t &&num) noexcept : f(num.f), s(num.s) {}
|
||
|
|
||
|
/**
|
||
|
* @brief Destructor for uint128_t
|
||
|
*/
|
||
|
~uint128_t() = default;
|
||
|
|
||
|
/**
|
||
|
* @brief Leading zeroes in binary
|
||
|
* @details Calculates leading zeros in 128-bit integer
|
||
|
* @returns Integer denoting leading zeroes
|
||
|
*/
|
||
|
inline uint32_t _lez() {
|
||
|
#ifndef _MSC_VER
|
||
|
if (f) {
|
||
|
return __builtin_clzll(f);
|
||
|
}
|
||
|
return 64 + __builtin_clzll(s);
|
||
|
#else
|
||
|
unsigned long r = 0;
|
||
|
_BitScanForward64(&r, f);
|
||
|
if (r == 64) {
|
||
|
unsigned long l = 0;
|
||
|
_BitScanForward64(&l, s);
|
||
|
return 64 + l;
|
||
|
}
|
||
|
return r;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Trailing zeroes in binary
|
||
|
* @details Calculates leading zeros in 128-bit integer
|
||
|
* @returns Integer denoting Trailing zeroes
|
||
|
*/
|
||
|
inline uint32_t _trz() {
|
||
|
#ifndef _MSC_VER
|
||
|
if (f) {
|
||
|
return __builtin_ctzll(f);
|
||
|
}
|
||
|
return 64 + __builtin_ctzll(s);
|
||
|
#else
|
||
|
unsigned long r = 0;
|
||
|
_BitScanReverse64(&r, s);
|
||
|
if (r == 64) {
|
||
|
unsigned long l = 0;
|
||
|
_BitScanReverse64(&l, f);
|
||
|
return 64 + l;
|
||
|
}
|
||
|
return r;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief casting operator to boolean value
|
||
|
* @returns true if value of this is non-zero, else false
|
||
|
*/
|
||
|
inline explicit operator bool() const { return (f || s); }
|
||
|
|
||
|
/**
|
||
|
* @brief casting operator to any integer valu
|
||
|
* @tparam T any integer type
|
||
|
* @returns integer value casted to mentioned type
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline explicit operator T() const {
|
||
|
return static_cast<T>(s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief returns lower 64-bit integer part
|
||
|
* @returns returns lower 64-bit integer part
|
||
|
*/
|
||
|
inline uint64_t lower() const { return s; }
|
||
|
|
||
|
/**
|
||
|
* @brief returns upper 64-bit integer part
|
||
|
* @returns returns upper 64-bit integer part
|
||
|
*/
|
||
|
inline uint64_t upper() const { return f; }
|
||
|
|
||
|
/**
|
||
|
* @brief operator = for other types
|
||
|
* @tparam T denoting any integer type
|
||
|
* @param p an integer to assign it's value
|
||
|
* @returns this pointer with it's value equal to `p`
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator=(const T &p) {
|
||
|
this->s = p;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator = for type string
|
||
|
* @param p a string to assign it's value to equivalent integer
|
||
|
* @returns this pointer with it's value equal to `p`
|
||
|
*/
|
||
|
inline uint128_t &operator=(const std::string &p) {
|
||
|
this->__get_integer_from_string(p);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator = for uint128_t
|
||
|
* @param p an 128-bit integer to assign it's value
|
||
|
* @returns this pointer with it's value equal to `p`
|
||
|
*/
|
||
|
inline uint128_t &operator=(const uint128_t &p) = default;
|
||
|
|
||
|
/**
|
||
|
* @brief Move assignment operator
|
||
|
*/
|
||
|
inline uint128_t &operator=(uint128_t &&p) = default;
|
||
|
|
||
|
/**
|
||
|
* @brief operator + for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns addition of this and p, returning uint128_t integer
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator+(const T p) {
|
||
|
return uint128_t(f + (p + s < s), p + s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator + for uint128_t and other integer types.
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns addition of this and p, returning uint128_t integer
|
||
|
*/
|
||
|
inline uint128_t operator+(const uint128_t &p) {
|
||
|
return uint128_t(f + (p.s + s < s) + p.f, p.s + s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator += for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns addition of this and p, returning this
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator+=(const T p) {
|
||
|
bool app = p + s < s;
|
||
|
this->f += app;
|
||
|
this->s += p;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator += for uint128_t
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns addition of this and p, returning this
|
||
|
*/
|
||
|
uint128_t &operator+=(const uint128_t &p) {
|
||
|
bool app = p.s + s < s;
|
||
|
f = f + app + p.f;
|
||
|
s = p.s + s;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief pre-increment operator
|
||
|
* @returns incremented value of this.
|
||
|
*/
|
||
|
inline uint128_t &operator++() {
|
||
|
*this += 1;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief post-increment operator
|
||
|
* @returns incremented value of this.
|
||
|
*/
|
||
|
inline uint128_t operator++(int) {
|
||
|
++*this;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator - for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns subtraction of this and p, returning uint128_t integer
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator-(const T &p) {
|
||
|
bool app = p > s;
|
||
|
return uint128_t(f - app, s - p);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator - for uint128_t
|
||
|
* @param p a type of integer variable
|
||
|
* @returns subtraction of this and p, returning uint128_t integer
|
||
|
*/
|
||
|
inline uint128_t operator-(const uint128_t &p) {
|
||
|
bool app = p.s > s;
|
||
|
return uint128_t(f - p.f - app, s - p.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator - using twos complement
|
||
|
* @returns 2's complement of this.
|
||
|
*/
|
||
|
inline uint128_t operator-() { return ~*this + uint128_t(1); }
|
||
|
|
||
|
/**
|
||
|
* @brief operator -- (pre-decrement)
|
||
|
* @returns decremented value of this
|
||
|
*/
|
||
|
inline uint128_t &operator--() {
|
||
|
*this -= 1;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator -- (post-decrement)
|
||
|
* @returns decremented value of this
|
||
|
*/
|
||
|
inline uint128_t operator--(int p) {
|
||
|
--*this;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator -= for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns subtraction of this and p, returning this
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t &operator-=(const T &p) {
|
||
|
bool app = p > s;
|
||
|
f -= app;
|
||
|
s -= p;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator -= for uint128_t
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns subtraction of this and p, returning this
|
||
|
*/
|
||
|
uint128_t &operator-=(const uint128_t &p) {
|
||
|
bool app = p.s > s;
|
||
|
f = f - p.f - app;
|
||
|
s = s - p.s;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator * for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns multiplication of this and p, returning uint128_t integer
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator*(const T p) {
|
||
|
return *this * uint128_t(p);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator * for uint128_t and other integer types.
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns multiplication of this and p, returning uint128_t integer
|
||
|
*/
|
||
|
uint128_t operator*(const uint128_t &p) {
|
||
|
uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF,
|
||
|
s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF;
|
||
|
uint64_t fi = f_first * s_first, se = f_first * s_second,
|
||
|
th = s_first * f_second, fo = s_second * f_second;
|
||
|
uint64_t tmp = ((se & 0xFFFFFFFF) << 32), tmp2 = (th & 0xFFFFFFFF)
|
||
|
<< 32;
|
||
|
int cc = (tmp + tmp2 < tmp);
|
||
|
tmp += tmp2;
|
||
|
cc += (tmp + fo < tmp);
|
||
|
uint64_t carry = fi + (se >> 32) + (th >> 32);
|
||
|
return uint128_t(this->f * p.s + this->s * p.f + carry + cc, tmp + fo);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator *= for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns multiplication of this and p, returning this
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator*=(const T p) {
|
||
|
*this *= uint128_t(p);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator *= for uint128_t and other integer types.
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns multiplication of this and p, returning this
|
||
|
*/
|
||
|
uint128_t &operator*=(const uint128_t &p) {
|
||
|
uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF,
|
||
|
s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF;
|
||
|
uint64_t fi = f_first * s_first, se = f_first * s_second,
|
||
|
th = s_first * f_second, fo = s_second * f_second;
|
||
|
uint64_t tmp = (se << 32), tmp2 = (th << 32);
|
||
|
int cc = (tmp + tmp2 < tmp);
|
||
|
tmp += tmp2;
|
||
|
cc += (tmp + fo < tmp);
|
||
|
uint64_t carry = fi + (se >> 32) + (th >> 32);
|
||
|
f = this->f * p.s + this->s * p.f + carry + cc;
|
||
|
s = tmp + fo;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief divide function for uint128_t and other integer types.
|
||
|
* @details divide this value and
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns pair denoting quotient and remainder.
|
||
|
*/
|
||
|
std::pair<uint128_t, uint128_t> divide(const uint128_t &p) {
|
||
|
if (*this < p) { // if this is less than divisor
|
||
|
return {uint128_t(0), *this};
|
||
|
} else if (*this == p) { // if this is equal to divisor
|
||
|
return {uint128_t(1), uint128_t(0)};
|
||
|
}
|
||
|
uint128_t tmp = p, tmp2 = *this;
|
||
|
uint16_t left = tmp._lez() - _lez();
|
||
|
tmp <<= left;
|
||
|
uint128_t quotient(0);
|
||
|
uint128_t zero(0);
|
||
|
while (left >= 0 && tmp2 >= p) {
|
||
|
uint16_t shf = tmp2._lez() - tmp._lez();
|
||
|
if (shf) {
|
||
|
tmp >>= shf;
|
||
|
quotient <<= shf;
|
||
|
left -= shf;
|
||
|
}
|
||
|
if (tmp2 < tmp) {
|
||
|
tmp >>= 1;
|
||
|
quotient <<= 1;
|
||
|
--left;
|
||
|
}
|
||
|
tmp2 -= tmp;
|
||
|
++quotient;
|
||
|
}
|
||
|
return {quotient << left, tmp2};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator / for uint128_t and other integer types.
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns unsigned 128-bit quotient.
|
||
|
*/
|
||
|
inline uint128_t operator/(const uint128_t &p) { return divide(p).first; }
|
||
|
|
||
|
/**
|
||
|
* @brief operator / for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns unsigned 128-bit quotient.
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator/(const T p) {
|
||
|
uint128_t tmp = *this;
|
||
|
tmp /= uint128_t(0, p);
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator /= for uint128_t
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns this set as unsigned 128-bit quotient.
|
||
|
*/
|
||
|
inline uint128_t &operator/=(const uint128_t &p) {
|
||
|
*this = divide(p).first;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator /= for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns this set as unsigned 128-bit quotient.
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator/=(const T p) {
|
||
|
*this /= uint128_t(0, p);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator % for uint128_t
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns unsigned 128-bit remainder.
|
||
|
*/
|
||
|
inline uint128_t operator%(const uint128_t &p) { return divide(p).second; }
|
||
|
|
||
|
/**
|
||
|
* @brief operator % for uint128_t and other integer types.
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns unsigned 128-bit remainder.
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator%(const T &p) {
|
||
|
return *this % uint128_t(p);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator %= for uint128_t
|
||
|
* @param p 128-bit unsigned integer
|
||
|
* @returns this set as unsigned 128-bit remainder.
|
||
|
*/
|
||
|
inline uint128_t &operator%=(const uint128_t &p) {
|
||
|
*this = divide(p).second;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator %= for uint128_t
|
||
|
* @tparam T denoting integral type
|
||
|
* @param p a type of integer variable
|
||
|
* @returns this set as unsigned 128-bit remainder.
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator%=(const T &p) {
|
||
|
*this %= uint128_t(p);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator < for uint128_t
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is less than other, else false
|
||
|
*/
|
||
|
inline bool operator<(const uint128_t &other) {
|
||
|
return f < other.f || (f == other.f && s < other.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator <= for uint128_t
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is less than or equal to other, else false
|
||
|
*/
|
||
|
inline bool operator<=(const uint128_t &other) {
|
||
|
return f < other.f || (f == other.f && s <= other.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator > for uint128_t
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is greater than other, else false
|
||
|
*/
|
||
|
inline bool operator>(const uint128_t &other) {
|
||
|
return f > other.f || (f == other.f && s > other.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator >= for uint128_t
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is greater than or equal than other, else false
|
||
|
*/
|
||
|
inline bool operator>=(const uint128_t &other) {
|
||
|
return (f > other.f) || (f == other.f && s >= other.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator == for uint128_t
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is equal than other, else false
|
||
|
*/
|
||
|
inline bool operator==(const uint128_t &other) {
|
||
|
return f == other.f && s == other.s;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator != for uint128_t
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is not equal than other, else false
|
||
|
*/
|
||
|
inline bool operator!=(const uint128_t &other) {
|
||
|
return f != other.f || s != other.s;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator ! for uint128_t
|
||
|
* @returns true if this has zero value, else false
|
||
|
*/
|
||
|
inline bool operator!() { return !f && !s; }
|
||
|
|
||
|
/**
|
||
|
* @brief operator && for uint128_t
|
||
|
* @param b number to be compared with this
|
||
|
* @returns true if both of the values are not zero, else false
|
||
|
*/
|
||
|
inline bool operator&&(const uint128_t &b) {
|
||
|
return (s || f) && (b.s || b.f);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator || for uint128_t
|
||
|
* @param b number to be compared with this
|
||
|
* @returns true if one of the values are not zero, else false
|
||
|
*/
|
||
|
inline bool operator||(const uint128_t &b) {
|
||
|
return (s || f) || (b.s || b.f);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator () for uint128_t
|
||
|
* @returns true if this value is non-zero, else false
|
||
|
*/
|
||
|
inline bool operator()() { return s || f; }
|
||
|
|
||
|
/**
|
||
|
* @brief operator < for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is less than other, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator<(const T other) {
|
||
|
return *this < uint128_t(other);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator <= for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is less than or equal to other, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator<=(const T other) {
|
||
|
return *this <= uint128_t(other);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator > for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is greater than other, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator>(const T other) {
|
||
|
return *this > uint128_t(other);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator >= for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is greater than or equal other, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator>=(const T other) {
|
||
|
return *this >= uint128_t(other);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator == for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is equal to other, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator==(const T other) {
|
||
|
return *this == uint128_t(other);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator != for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is not equal to other, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator!=(const T other) {
|
||
|
return *this != uint128_t(other);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator && for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is both values are non-zero, else false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator&&(const T b) {
|
||
|
return (f || s) && b;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator || for other types
|
||
|
* @tparam T integral type
|
||
|
* @param other number to be compared with this
|
||
|
* @returns true if this is either one of the values are non-zero, else
|
||
|
* false
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator||(const T b) {
|
||
|
return (f || s) || b;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator ~ for uint128_t
|
||
|
* @returns 1's complement of this number
|
||
|
*/
|
||
|
uint128_t operator~() { return uint128_t(~this->f, ~this->s); }
|
||
|
|
||
|
/**
|
||
|
* @brief operator << for uint128_t
|
||
|
* @tparam T integral type
|
||
|
* @param p number denoting number of shifts
|
||
|
* @returns value of this shifted by p to left
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t operator<<(const T p) {
|
||
|
if (!p) {
|
||
|
return uint128_t(f, s);
|
||
|
} else if (p >= 64 && p <= 128) {
|
||
|
return uint128_t((this->s << (p - 64)), 0);
|
||
|
} else if (p < 64 && p > 0) {
|
||
|
return uint128_t((this->f << p) + ((this->s >> (64 - p))),
|
||
|
this->s << p);
|
||
|
}
|
||
|
return uint128_t(0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator <<= for uint128_t
|
||
|
* @tparam T integral type
|
||
|
* @param p number denoting number of shifts
|
||
|
* @returns this shifted by p to left
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t &operator<<=(const T p) {
|
||
|
if (p) {
|
||
|
if (p >= 64 && p <= 128) {
|
||
|
this->f = (this->s << (p - 64));
|
||
|
this->s = 0;
|
||
|
} else {
|
||
|
f = ((this->f << p) + (this->s >> (64 - p)));
|
||
|
s = (this->s << p);
|
||
|
}
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator >> for uint128_t
|
||
|
* @tparam T integral type
|
||
|
* @param p number denoting number of shifts
|
||
|
* @returns value of this shifted by p to right
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t operator>>(const T p) {
|
||
|
if (!p) {
|
||
|
return uint128_t(this->f, this->s);
|
||
|
} else if (p >= 64 && p <= 128) {
|
||
|
return uint128_t(0, (this->f >> (p - 64)));
|
||
|
} else if (p < 64 && p > 0) {
|
||
|
return uint128_t((this->f >> p),
|
||
|
(this->s >> p) + (this->f << (64 - p)));
|
||
|
}
|
||
|
return uint128_t(0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator >>= for uint128_t
|
||
|
* @tparam T integral type
|
||
|
* @param p number denoting number of shifts
|
||
|
* @returns this shifted by p to right
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t &operator>>=(const T p) {
|
||
|
if (p) {
|
||
|
if (p >= 64) {
|
||
|
f = 0;
|
||
|
s = (this->f >> (p - 64));
|
||
|
} else {
|
||
|
s = (this->s >> p) + (this->f << (64 - p));
|
||
|
f = (this->f >> p);
|
||
|
}
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator & for uint128_t (bitwise operator)
|
||
|
* @param p number to be operated
|
||
|
* @returns value of this & p (& is bit-wise operator)
|
||
|
*/
|
||
|
inline uint128_t operator&(const uint128_t &p) {
|
||
|
return uint128_t(this->f & p.f, this->s & p.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator & for other types (bitwise operator)
|
||
|
* @tparam T integral type
|
||
|
* @param p number to be operated
|
||
|
* @returns value of this & p (& is bit-wise operator)
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t operator&(const T p) {
|
||
|
uint128_t tmp = *this;
|
||
|
return tmp & uint128_t(p);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator &= for uint128_t (bitwise operator)
|
||
|
* @param p number to be operated
|
||
|
* @returns this = this & p (& is bit-wise operator)
|
||
|
*/
|
||
|
uint128_t &operator&=(const uint128_t &p) {
|
||
|
this->f &= p.f;
|
||
|
this->s &= p.s;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator &= for other types (bitwise operator)
|
||
|
* @tparam T integral type
|
||
|
* @param p number to be operated
|
||
|
* @returns this = this & p (& is bit-wise operator)
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
uint128_t &operator&=(const T p) {
|
||
|
*this &= uint128_t(p);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator | for other types (bitwise operator)
|
||
|
* @tparam T integral type
|
||
|
* @param p number to be operated
|
||
|
* @returns value of this | p (| is bit-wise operator)
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator|(const T p) {
|
||
|
return uint128_t(p | s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator | for uint128_t (bitwise operator)
|
||
|
* @param p number to be operated
|
||
|
* @returns value of this | p (| is bit-wise OR operator)
|
||
|
*/
|
||
|
inline uint128_t operator|(const uint128_t &p) {
|
||
|
return uint128_t(this->f | p.f, this->s | p.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator |= for uint128_t (bitwise operator)
|
||
|
* @param p number to be operated
|
||
|
* @returns this = this | p (| is bit-wise OR operator)
|
||
|
*/
|
||
|
uint128_t &operator|=(const uint128_t &p) {
|
||
|
f |= p.f;
|
||
|
s |= p.s;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator |= for other types (bitwise operator)
|
||
|
* @tparam T integral type
|
||
|
* @param p number to be operated
|
||
|
* @returns this = this | p (| is bit-wise OR operator)
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator|=(const T p) {
|
||
|
s |= p.s;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator ^ for other types (bitwise operator)
|
||
|
* @tparam T integral type
|
||
|
* @param p number to be operated
|
||
|
* @returns value of this ^ p (^ is bit-wise XOR operator)
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator^(const T p) {
|
||
|
return uint128_t(this->f, this->s ^ p);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator ^ for uint128_t (bitwise operator)
|
||
|
* @param p number to be operated
|
||
|
* @returns value of this ^ p (^ is bit-wise XOR operator)
|
||
|
*/
|
||
|
inline uint128_t operator^(const uint128_t &p) {
|
||
|
return uint128_t(this->f ^ p.f, this->s ^ p.s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator ^= for uint128_t (bitwise operator)
|
||
|
* @param p number to be operated
|
||
|
* @returns this = this ^ p (^ is bit-wise XOR operator)
|
||
|
*/
|
||
|
uint128_t &operator^=(const uint128_t &p) {
|
||
|
f ^= p.f;
|
||
|
s ^= p.s;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator ^= for other types (bitwise operator)
|
||
|
* @tparam T integral type
|
||
|
* @param p number to be operated
|
||
|
* @returns this = this ^ p (^ is bit-wise XOR operator)
|
||
|
*/
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t &operator^=(const T &p) {
|
||
|
s ^= p;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief operator << for printing uint128_t integer
|
||
|
* @details Prints the uint128_t integer in decimal form
|
||
|
* @note Note that this operator is costly since it uses strings to print
|
||
|
* the value
|
||
|
* @param op ostream object
|
||
|
* @param p 128-bit integer
|
||
|
* @returns op, ostream object.
|
||
|
*/
|
||
|
friend std::ostream &operator<<(std::ostream &op, const uint128_t &p) {
|
||
|
if (!p.f) {
|
||
|
op << p.s;
|
||
|
} else {
|
||
|
std::string out = "0", p_2 = "1";
|
||
|
for (int i = 0; i < 64; ++i) {
|
||
|
if (p.s & (1LL << i)) {
|
||
|
out = add(out, p_2);
|
||
|
}
|
||
|
p_2 = add(p_2, p_2);
|
||
|
}
|
||
|
for (int i = 0; i < 64; ++i) {
|
||
|
if (p.f & (1LL << i)) {
|
||
|
out = add(out, p_2);
|
||
|
}
|
||
|
p_2 = add(p_2, p_2);
|
||
|
}
|
||
|
op << out;
|
||
|
}
|
||
|
return op;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Arithmetic operators
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator+(const T &p, const uint128_t &q) {
|
||
|
return uint128_t(p) + q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator-(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) - q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator*(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) * q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator/(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) / q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator%(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) % q;
|
||
|
}
|
||
|
|
||
|
// Bitwise operators
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator&(const T &p, const uint128_t &q) {
|
||
|
return uint128_t(p) & q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator|(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) | q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline uint128_t operator^(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) ^ q;
|
||
|
}
|
||
|
|
||
|
// Boolean operators
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator&&(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) && q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator||(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) || q;
|
||
|
}
|
||
|
|
||
|
// Comparison operators
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator==(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) == q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator!=(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) != q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator<(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) < q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator<=(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) <= q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator>(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) > q;
|
||
|
}
|
||
|
|
||
|
template <typename T, typename = typename std::enable_if<
|
||
|
std::is_integral<T>::value, T>::type>
|
||
|
inline bool operator>=(const T p, const uint128_t &q) {
|
||
|
return uint128_t(p) >= q;
|
||
|
}
|
||
|
|
||
|
#endif // CIPHERS_UINT128_T_HPP_
|