mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
d9a97f106f
* updating DIRECTORY.md * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers * updating DIRECTORY.md * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers: Error handling * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers: Error handling * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers: Error handling-2 * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers: Error handling-bit handling * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers: Error handling-bit handling * Feat: Elliptic Curve Diffie Hellman Key Exchange, Ciphers: Error handling-bit handling * Type checks and destructor added * Type checks and integer shift checked * clang-format and clang-tidy fixes for276fde9d
* Comment modification * clang-format and clang-tidy fixes forae6a048d
* Comment modification * Wrong return * clang-format and clang-tidy fixes forbb40ea4c
* Type checks * windows error * clang-format and clang-tidy fixes for2c41f111
* Error handling * Error handling-2 * Comments * Comment modifications * Update ciphers/uint128_t.hpp Co-authored-by: David Leal <halfpacho@gmail.com> * Comment modifications-2 * Comment modifications-3 * Empty commit * Comments * Additional comments * clang-format and clang-tidy fixes forf7daaa15
* Empty commit for build * Additional test correction and comment modification Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal <halfpacho@gmail.com>
1075 lines
33 KiB
C++
1075 lines
33 KiB
C++
/**
|
|
* @file
|
|
*
|
|
* @details Implementation of 256-bit unsigned integers.
|
|
* @note The implementation can be flagged as not completed. This header is used
|
|
* with enough operations to demonstrate the usage of ECDH (Elliptic Curve
|
|
* Diffie-Hellman) Key exchange.
|
|
* @author [Ashish Daulatabad](https://github.com/AshishYUO)
|
|
*/
|
|
#include <string> /// for `std::string`
|
|
#include <utility> /// for `std::pair` library
|
|
|
|
#include "uint128_t.hpp" /// for uint128_t integer
|
|
|
|
#ifndef CIPHERS_UINT256_T_HPP_
|
|
#define CIPHERS_UINT256_T_HPP_
|
|
|
|
class uint256_t;
|
|
|
|
template <>
|
|
struct std::is_integral<uint256_t> : std::true_type {};
|
|
|
|
template <>
|
|
struct std::is_arithmetic<uint256_t> : std::true_type {};
|
|
|
|
template <>
|
|
struct std::is_unsigned<uint256_t> : std::true_type {};
|
|
|
|
/**
|
|
* @class uint256_t
|
|
* @brief class for 256-bit unsigned integer
|
|
*/
|
|
class uint256_t {
|
|
uint128_t f{}, s{}; /// First and second half of 256 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 = uint128_t(0);
|
|
if (str.size() > 1 && str[1] == 'x') {
|
|
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 {
|
|
for (auto &x : str) {
|
|
*this *= 10LL;
|
|
*this += (x - '0');
|
|
}
|
|
}
|
|
}
|
|
|
|
public:
|
|
// Constructors
|
|
uint256_t() = default;
|
|
|
|
/**
|
|
* @brief Parameterized constructor
|
|
* @tparam T template for integer types
|
|
* @param low Integer denoting lower 128-bits
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
explicit uint256_t(T low) : s(low), f(0) {}
|
|
|
|
/**
|
|
* @brief Parameterized constructor
|
|
* @param str Integer string (hexadecimal starting with 0x.. or decimal)
|
|
*/
|
|
explicit uint256_t(const std::string &str) {
|
|
__get_integer_from_string(str);
|
|
}
|
|
|
|
/**
|
|
* @brief Copy constructor
|
|
* @param num 256-bit unsigned integer
|
|
*/
|
|
uint256_t(const uint256_t &num) = default;
|
|
|
|
/**
|
|
* @brief Move constructor
|
|
* @param num 256-bit unsigned integer
|
|
*/
|
|
uint256_t(uint256_t &&num) noexcept
|
|
: f(std::move(num.f)), s(std::move(num.s)) {}
|
|
|
|
/**
|
|
* @brief Parameterized constructor
|
|
* @param high higher part 128-bit unsigned integer
|
|
* @param low lower part 128-bit unsigned integer
|
|
*/
|
|
uint256_t(uint128_t high, uint128_t low)
|
|
: f(std::move(high)), s(std::move(low)) {}
|
|
|
|
/**
|
|
* @brief Parameterized constructor
|
|
* @param high higher part 64-bit unsigned integer
|
|
* @param low lower part 64-bit unsigned integer
|
|
*/
|
|
uint256_t(const uint64_t high, const uint64_t low) : f(high), s(low) {}
|
|
|
|
/**
|
|
* @brief Destructor for uint256_t
|
|
*/
|
|
~uint256_t() = default;
|
|
|
|
/**
|
|
* @brief Leading zeroes in binary
|
|
* @details Calculates leading zeros in 256-bit integer
|
|
* @returns Integer denoting leading zeroes
|
|
*/
|
|
inline uint32_t _lez() {
|
|
if (f) {
|
|
return f._lez();
|
|
}
|
|
return 128 + s._lez();
|
|
}
|
|
|
|
/**
|
|
* @brief Trailing zeroes in binary
|
|
* @details Calculates leading zeros in 256-bit integer
|
|
* @returns Integer denoting Trailing zeroes
|
|
*/
|
|
inline uint32_t _trz() {
|
|
if (s) {
|
|
return s._trz();
|
|
}
|
|
return 128 + f._trz();
|
|
}
|
|
|
|
/**
|
|
* @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 value
|
|
* @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 casting operator to uint128_t
|
|
* @returns returns lower 128-bit integer part
|
|
*/
|
|
inline explicit operator uint128_t() const { return s; }
|
|
|
|
/**
|
|
* @brief returns lower 128-bit integer part
|
|
* @returns returns lower 128-bit integer part
|
|
*/
|
|
inline uint128_t lower() const { return s; }
|
|
|
|
/**
|
|
* @brief returns upper 128-bit integer part
|
|
* @returns returns upper 128-bit integer part
|
|
*/
|
|
inline uint128_t upper() const { return f; }
|
|
|
|
/**
|
|
* @brief operator = for uint256_t
|
|
* @param p an 256-bit integer to assign it's value
|
|
* @returns this pointer with it's value equal to `p`
|
|
*/
|
|
inline uint256_t &operator=(const uint256_t &p) = default;
|
|
|
|
/**
|
|
* @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 uint256_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 uint256_t &operator=(const std::string &p) {
|
|
__get_integer_from_string(p);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Move assignment operator
|
|
*/
|
|
inline uint256_t &operator=(uint256_t &&p) = default;
|
|
|
|
/**
|
|
* @brief operator + for uint256_t and other integer types.
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns addition of this and p, returning uint256_t integer
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator+(const T &p) {
|
|
bool app = s + p < s;
|
|
return uint256_t(f + app, s + p);
|
|
}
|
|
|
|
/**
|
|
* @brief operator + for uint256_t and other integer types.
|
|
* @param p 256-bit unsigned integer
|
|
* @returns addition of this and p, returning uint256_t integer
|
|
*/
|
|
inline uint256_t operator+(const uint256_t &p) {
|
|
bool app = (s + p.s < s);
|
|
return {f + app + p.f, s + p.s};
|
|
}
|
|
|
|
/**
|
|
* @brief operator += for uint256_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 uint256_t &operator+=(const T &p) {
|
|
bool app = (p + s < s);
|
|
this->f += app;
|
|
this->s += p;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator += for uint256_t
|
|
* @param p 256-bit unsigned integer
|
|
* @returns addition of this and p, returning this
|
|
*/
|
|
inline uint256_t &operator+=(const uint256_t &p) {
|
|
bool app = (s + p.s < s);
|
|
f = f + app + p.f;
|
|
s = s + p.s;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief pre-increment operator
|
|
* @returns incremented value of this.
|
|
*/
|
|
inline uint256_t &operator++() {
|
|
*this += 1;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief post-increment operator
|
|
* @returns incremented value of this.
|
|
*/
|
|
inline uint256_t operator++(int) {
|
|
++*this;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator - for uint256_t and other integer types.
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns subtraction of this and p, returning uint256_t integer
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator-(const T &p) {
|
|
bool app = (p > s);
|
|
return uint256_t(f - app, s - p);
|
|
}
|
|
|
|
/**
|
|
* @brief operator - for uint256_t
|
|
* @param p a type of integer variable
|
|
* @returns subtraction of this and p, returning uint256_t integer
|
|
*/
|
|
inline uint256_t operator-(const uint256_t &p) {
|
|
bool app = s < p.s;
|
|
return {f - p.f - app, s - p.s};
|
|
}
|
|
|
|
/**
|
|
* @brief operator - using twos complement
|
|
* @returns 2's complement of this.
|
|
*/
|
|
inline uint256_t operator-() { return ~*this + uint256_t(1); }
|
|
|
|
/**
|
|
* @brief operator -- (pre-decrement)
|
|
* @returns decremented value of this
|
|
*/
|
|
inline uint256_t &operator--() {
|
|
*this -= 1;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator -- (post-decrement)
|
|
* @returns decremented value of this
|
|
*/
|
|
inline uint256_t operator--(int p) {
|
|
--*this;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator -= for uint256_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>
|
|
inline uint256_t operator-=(const T p) {
|
|
bool app = (p > s);
|
|
f = f - app;
|
|
s = s - p;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator -= for uint256_t
|
|
* @param p 256-bit unsigned integer
|
|
* @returns subtraction of this and p, returning this
|
|
*/
|
|
inline uint256_t &operator-=(const uint256_t &p) {
|
|
bool app = s < p.s;
|
|
f = f - app - p.f;
|
|
s = s - p.s;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator * for uint256_t and other integer types.
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns multiplication of this and p, returning uint256_t integer
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator*(const T &p) {
|
|
return *this * uint256_t(p);
|
|
}
|
|
|
|
/**
|
|
* @brief operator * for uint256_t and other integer types.
|
|
* @param p 256-bit unsigned integer
|
|
* @returns multiplication of this and p, returning uint256_t integer
|
|
*/
|
|
uint256_t operator*(const uint256_t &p) {
|
|
uint128_t f_first(s.upper()), f_second(s.lower()), s_first(p.s.upper()),
|
|
s_second(p.s.lower());
|
|
uint128_t fi = f_first * s_first, se = f_first * s_second,
|
|
th = s_first * f_second, fo = s_second * f_second;
|
|
uint128_t tmp = se << 64, tmp2 = th << 64;
|
|
int cc = (tmp + tmp2 < tmp);
|
|
tmp += tmp2;
|
|
cc += (tmp + fo < tmp);
|
|
return {f * p.s + s * p.f + fi + se.upper() + th.upper() + cc,
|
|
tmp + fo};
|
|
}
|
|
|
|
/**
|
|
* @brief operator *= for uint256_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 uint256_t &operator*=(const T &p) {
|
|
return (*this *= uint256_t(p));
|
|
}
|
|
|
|
/**
|
|
* @brief operator *= for uint256_t and other integer types.
|
|
* @param p 256-bit unsigned integer
|
|
* @returns multiplication of this and p, returning this
|
|
*/
|
|
uint256_t &operator*=(const uint256_t &p) {
|
|
uint128_t f_first(s.upper()), f_second(s.lower()), s_first(p.s.upper()),
|
|
s_second(p.s.lower());
|
|
uint128_t fi = f_first * s_first, se = f_first * s_second,
|
|
th = s_first * f_second, fo = s_second * f_second;
|
|
uint128_t tmp = se << 64, tmp2 = th << 64;
|
|
int cc = (tmp + tmp2 < tmp);
|
|
tmp += tmp2;
|
|
cc += (tmp + fo < tmp);
|
|
f = f * p.s + s * p.f + fi + se.upper() + th.upper() + cc;
|
|
s = tmp + fo;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief divide function for uint256_t and other integer types.
|
|
* @details divide this value and
|
|
* @param p 256-bit unsigned integer
|
|
* @returns pair denoting quotient and remainder.
|
|
*/
|
|
std::pair<uint256_t, uint256_t> divide(const uint256_t &p) {
|
|
if (*this < p) { // if this is less than divisor
|
|
return {uint256_t(0), *this};
|
|
} else if (*this == p) { // if this is equal to divisor
|
|
return {uint256_t(1), uint256_t(0)};
|
|
}
|
|
uint256_t tmp = p, tmp2 = *this;
|
|
uint16_t left = tmp._lez() - _lez();
|
|
tmp <<= left;
|
|
uint256_t quotient(0);
|
|
uint256_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 uint256_t and other integer types.
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns unsigned 256-bit quotient.
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator/(const T &p) {
|
|
uint256_t tmp = *this;
|
|
tmp /= uint256_t(p);
|
|
return tmp;
|
|
}
|
|
|
|
/**
|
|
* @brief operator / for uint256_t and other integer types.
|
|
* @param p 256-bit unsigned integer
|
|
* @returns unsigned 256-bit quotient.
|
|
*/
|
|
inline uint256_t operator/(const uint256_t &p) { return divide(p).first; }
|
|
|
|
/**
|
|
* @brief operator /= for uint256_t
|
|
* @param p 256-bit unsigned integer
|
|
* @returns this set as unsigned 256-bit quotient.
|
|
*/
|
|
inline uint256_t &operator/=(const uint256_t &p) {
|
|
*this = divide(p).first;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator /= for uint256_t and other integer types.
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns this set as unsigned 256-bit quotient.
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t &operator/=(const T &p) {
|
|
*this /= uint256_t(p);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator % for uint256_t
|
|
* @param p 256-bit unsigned integer
|
|
* @returns unsigned 256-bit remainder.
|
|
*/
|
|
inline uint256_t operator%(const uint256_t &p) { return divide(p).second; }
|
|
|
|
/**
|
|
* @brief operator % for uint256_t and other integer types.
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns unsigned 256-bit remainder.
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator%(const T &p) {
|
|
uint256_t tmp = *this;
|
|
tmp %= uint256_t(p);
|
|
return tmp;
|
|
}
|
|
|
|
/**
|
|
* @brief operator %= for uint256_t
|
|
* @param p 256-bit unsigned integer
|
|
* @returns this set as unsigned 256-bit remainder.
|
|
*/
|
|
inline uint256_t &operator%=(const uint256_t &p) {
|
|
*this = divide(p).second;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator %= for uint256_t
|
|
* @tparam T denoting integral type
|
|
* @param p a type of integer variable
|
|
* @returns this set as unsigned 256-bit remainder.
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t &operator%=(const T &p) {
|
|
*this %= uint256_t(p);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator < for uint256_t
|
|
* @param other number to be compared with this
|
|
* @returns true if this is less than other, else false
|
|
*/
|
|
inline bool operator<(const uint256_t &other) {
|
|
return f < other.f || (f == other.f && s < other.s);
|
|
}
|
|
|
|
/**
|
|
* @brief operator <= for uint256_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 uint256_t &other) {
|
|
return f < other.f || (f == other.f && s <= other.s);
|
|
}
|
|
|
|
/**
|
|
* @brief operator > for uint256_t
|
|
* @param other number to be compared with this
|
|
* @returns true if this is greater than other, else false
|
|
*/
|
|
inline bool operator>(const uint256_t &other) {
|
|
return f > other.f || (f == other.f && s > other.s);
|
|
}
|
|
|
|
/**
|
|
* @brief operator >= for uint256_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 uint256_t &other) {
|
|
return (f > other.f) || (f == other.f && s >= other.s);
|
|
}
|
|
|
|
/**
|
|
* @brief operator == for uint256_t
|
|
* @param other number to be compared with this
|
|
* @returns true if this is equal than other, else false
|
|
*/
|
|
inline bool operator==(const uint256_t &other) {
|
|
return f == other.f && s == other.s;
|
|
}
|
|
|
|
/**
|
|
* @brief operator != for uint256_t
|
|
* @param other number to be compared with this
|
|
* @returns true if this is not equal than other, else false
|
|
*/
|
|
inline bool operator!=(const uint256_t &other) {
|
|
return !((*this) == other);
|
|
}
|
|
|
|
/**
|
|
* @brief operator ! for uint256_t
|
|
* @returns true if this has zero value, else false
|
|
*/
|
|
inline bool operator!() { return !f && !s; }
|
|
|
|
/**
|
|
* @brief operator && for uint256_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 uint256_t &b) {
|
|
return (s || f) && (b.s || b.f);
|
|
}
|
|
|
|
/**
|
|
* @brief operator || for uint256_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 uint256_t &b) {
|
|
return (s || f) || (b.s || b.f);
|
|
}
|
|
|
|
/**
|
|
* @brief operator () for uint256_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>
|
|
bool operator<(const T &other) {
|
|
return *this < uint256_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>
|
|
bool operator<=(const T &other) {
|
|
return *this <= uint256_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>
|
|
bool operator>(const T &other) {
|
|
return *this > uint256_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>
|
|
bool operator>=(const T &other) {
|
|
return *this >= uint256_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>
|
|
bool operator==(const T &other) {
|
|
return *this == uint256_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>
|
|
bool operator!=(const T &other) {
|
|
return *this != uint256_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 (s || f) && (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 (s || f) || (b);
|
|
}
|
|
|
|
/**
|
|
* @brief operator ~ for uint256_t
|
|
* @returns 1's complement of this number
|
|
*/
|
|
inline uint256_t operator~() { return {~f, ~s}; }
|
|
|
|
/**
|
|
* @brief operator << for uint256_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>
|
|
uint256_t operator<<(const T &p) {
|
|
if (!p) {
|
|
return {this->f, this->s};
|
|
} else if (p >= 128) {
|
|
return uint256_t((this->s << (p - 128)), uint128_t(0));
|
|
}
|
|
return uint256_t((this->f << p) + (this->s >> (128 - p)),
|
|
(this->s << p));
|
|
}
|
|
|
|
/**
|
|
* @brief operator <<= for uint256_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>
|
|
uint256_t &operator<<=(const T &p) {
|
|
if (p) {
|
|
if (p >= 128) {
|
|
this->f = (this->s << (p - 128));
|
|
this->s = uint128_t(0);
|
|
} else {
|
|
f = ((this->s >> (128 - p)) + (this->f << p));
|
|
s = (this->s << p);
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator >> for uint256_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>
|
|
uint256_t operator>>(const T &p) {
|
|
if (!p) {
|
|
return {this->f, this->s};
|
|
} else if (p >= 128) {
|
|
return uint256_t(uint128_t(0), (this->f >> (p - 128)));
|
|
}
|
|
return uint256_t((this->f >> p),
|
|
(this->s >> p) + (this->f << (128 - p)));
|
|
}
|
|
|
|
/**
|
|
* @brief operator >>= for uint256_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>
|
|
uint256_t &operator>>=(const T &p) {
|
|
if (p) {
|
|
if (p >= 128) {
|
|
f = uint128_t(0);
|
|
s = (this->f >> (p - 128));
|
|
} else {
|
|
s = (this->s >> p) + (this->f << (128 - p));
|
|
f = (this->f >> 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 uint256_t operator&(const T &p) {
|
|
return *this & uint256_t(p);
|
|
}
|
|
|
|
/**
|
|
* @brief operator & for uint256_t (bitwise operator)
|
|
* @param p number to be operated
|
|
* @returns value of this & p (& is bit-wise operator)
|
|
*/
|
|
inline uint256_t operator&(const uint256_t &p) {
|
|
return {f & p.f, s & p.s};
|
|
}
|
|
|
|
/**
|
|
* @brief operator &= for uint256_t (bitwise operator)
|
|
* @param p number to be operated
|
|
* @returns this = this & p (& is bit-wise operator)
|
|
*/
|
|
inline uint256_t &operator&=(const uint256_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 operator)
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_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 operator)
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator|(const T &p) {
|
|
return *this | uint256_t(p);
|
|
}
|
|
|
|
/**
|
|
* @brief operator | for uint256_t (bitwise operator)
|
|
* @param p number to be operated
|
|
* @returns value of this | p (| is bit-wise OR operator)
|
|
*/
|
|
inline uint256_t operator|(const uint256_t &p) {
|
|
return {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 this = this | p (| is bit-wise OR operator)
|
|
*/
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t &operator|=(const T &p) {
|
|
s |= p;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator |= for uint256_t (bitwise operator)
|
|
* @param p number to be operated
|
|
* @returns this = this | p (| is bit-wise OR operator)
|
|
*/
|
|
inline uint256_t &operator|=(const uint256_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 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 uint256_t operator^(const T &p) {
|
|
return uint256_t(f, s ^ p);
|
|
}
|
|
|
|
/**
|
|
* @brief operator ^ for uint256_t (bitwise operator)
|
|
* @param p number to be operated
|
|
* @returns value of this ^ p (^ is bit-wise XOR operator)
|
|
*/
|
|
inline uint256_t operator^(const uint256_t &p) {
|
|
return {this->f ^ p.f, this->s ^ p.s};
|
|
}
|
|
|
|
/**
|
|
* @brief operator ^= for uint256_t (bitwise operator)
|
|
* @param p number to be operated
|
|
* @returns this = this ^ p (^ is bit-wise XOR operator)
|
|
*/
|
|
inline uint256_t &operator^=(const uint256_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 uint256_t &operator^=(const T &p) {
|
|
s ^= p;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief operator << for printing uint256_t integer
|
|
* @details Prints the uint256_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 256-bit integer
|
|
* @returns op, ostream object.
|
|
*/
|
|
friend std::ostream &operator<<(std::ostream &op, uint256_t p) {
|
|
if (!p.f) {
|
|
op << p.s;
|
|
} else {
|
|
std::string out = "0", p_2 = "1";
|
|
uint128_t L(1);
|
|
for (uint64_t i = 0; i < 128; ++i) {
|
|
if ((p.s & L)) {
|
|
out = add(out, p_2);
|
|
}
|
|
p_2 = add(p_2, p_2);
|
|
L <<= 1;
|
|
}
|
|
L = uint128_t(1);
|
|
for (int i = 0; i < 128; ++i) {
|
|
if ((p.f & L)) {
|
|
out = add(out, p_2);
|
|
}
|
|
p_2 = add(p_2, p_2);
|
|
L <<= 1;
|
|
}
|
|
op << out;
|
|
}
|
|
return op;
|
|
}
|
|
};
|
|
|
|
// Artihmetic
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator+(const T p, const uint256_t &q) {
|
|
return uint256_t(p) + q;
|
|
}
|
|
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator-(const T p, const uint256_t &q) {
|
|
return (uint256_t(p) - q);
|
|
}
|
|
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator*(const T p, const uint256_t &q) {
|
|
return uint256_t(p) * q;
|
|
}
|
|
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator/(const T p, const uint256_t &q) {
|
|
return uint256_t(p) / q;
|
|
}
|
|
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator%(const T p, const uint256_t &q) {
|
|
return uint256_t(p) % q;
|
|
}
|
|
|
|
// Bitwise operators
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator&(const T &p, const uint256_t &q) {
|
|
return uint256_t(p) & q;
|
|
}
|
|
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator|(const T p, const uint256_t &q) {
|
|
return uint256_t(p) | q;
|
|
}
|
|
|
|
template <typename T, typename = typename std::enable_if<
|
|
std::is_integral<T>::value, T>::type>
|
|
inline uint256_t operator^(const T p, const uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_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 uint256_t &q) {
|
|
return uint256_t(p) >= q;
|
|
}
|
|
|
|
#endif // CIPHERS_UINT256_T_HPP_
|