diff --git a/include/intx/intx.hpp b/include/intx/intx.hpp index 4cc95613..bc1fce7a 100644 --- a/include/intx/intx.hpp +++ b/include/intx/intx.hpp @@ -374,8 +374,8 @@ inline constexpr uint128 operator~(uint128 x) noexcept inline constexpr uint128 operator|(uint128 x, uint128 y) noexcept { - // Clang7: perfect. - // GCC8: stupidly uses a vector instruction in all bitwise operators. + // Clang: perfect. + // GCC 8-12: stupidly uses a vector instruction in all bitwise operators. return {x[0] | y[0], x[1] | y[1]}; } @@ -1120,6 +1120,45 @@ struct uint inline constexpr uint& operator/=(const uint& y) noexcept { return *this = *this / y; } inline constexpr uint& operator%=(const uint& y) noexcept { return *this = *this % y; } + + + inline constexpr uint operator~() const noexcept + { + uint z; + for (size_t i = 0; i < num_words; ++i) + z[i] = ~words_[i]; + return z; + } + + friend inline constexpr uint operator|(const uint& x, const uint& y) noexcept + { + uint z; + for (size_t i = 0; i < num_words; ++i) + z[i] = x[i] | y[i]; + return z; + } + + inline constexpr uint& operator|=(const uint& y) noexcept { return *this = *this | y; } + + friend inline constexpr uint operator&(const uint& x, const uint& y) noexcept + { + uint z; + for (size_t i = 0; i < num_words; ++i) + z[i] = x[i] & y[i]; + return z; + } + + inline constexpr uint& operator&=(const uint& y) noexcept { return *this = *this & y; } + + friend inline constexpr uint operator^(const uint& x, const uint& y) noexcept + { + uint z; + for (size_t i = 0; i < num_words; ++i) + z[i] = x[i] ^ y[i]; + return z; + } + + inline constexpr uint& operator^=(const uint& y) noexcept { return *this = *this ^ y; } }; using uint192 = uint<192>; @@ -1282,42 +1321,6 @@ inline constexpr bool slt(const uint<N>& x, const uint<N>& y) noexcept return ((x_neg ^ y_neg) != 0) ? x_neg : x < y; } -template <unsigned N> -inline constexpr uint<N> operator|(const uint<N>& x, const uint<N>& y) noexcept -{ - uint<N> z; - for (size_t i = 0; i < uint<N>::num_words; ++i) - z[i] = x[i] | y[i]; - return z; -} - -template <unsigned N> -inline constexpr uint<N> operator&(const uint<N>& x, const uint<N>& y) noexcept -{ - uint<N> z; - for (size_t i = 0; i < uint<N>::num_words; ++i) - z[i] = x[i] & y[i]; - return z; -} - -template <unsigned N> -inline constexpr uint<N> operator^(const uint<N>& x, const uint<N>& y) noexcept -{ - uint<N> z; - for (size_t i = 0; i < uint<N>::num_words; ++i) - z[i] = x[i] ^ y[i]; - return z; -} - -template <unsigned N> -inline constexpr uint<N> operator~(const uint<N>& x) noexcept -{ - uint<N> z; - for (size_t i = 0; i < uint<N>::num_words; ++i) - z[i] = ~x[i]; - return z; -} - inline constexpr uint256 operator<<(const uint256& x, uint64_t shift) noexcept { @@ -1842,69 +1845,6 @@ inline constexpr uint<N> bswap(const uint<N>& x) noexcept // Support for type conversions for binary operators. -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N> operator|(const uint<N>& x, const T& y) noexcept -{ - return x | uint<N>(y); -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N> operator|(const T& x, const uint<N>& y) noexcept -{ - return uint<N>(x) | y; -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N> operator&(const uint<N>& x, const T& y) noexcept -{ - return x & uint<N>(y); -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N> operator&(const T& x, const uint<N>& y) noexcept -{ - return uint<N>(x) & y; -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N> operator^(const uint<N>& x, const T& y) noexcept -{ - return x ^ uint<N>(y); -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N> operator^(const T& x, const uint<N>& y) noexcept -{ - return uint<N>(x) ^ y; -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N>& operator|=(uint<N>& x, const T& y) noexcept -{ - return x = x | y; -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N>& operator&=(uint<N>& x, const T& y) noexcept -{ - return x = x & y; -} - -template <unsigned N, typename T, - typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> -inline constexpr uint<N>& operator^=(uint<N>& x, const T& y) noexcept -{ - return x = x ^ y; -} - template <unsigned N, typename T, typename = typename std::enable_if<std::is_convertible<T, uint<N>>::value>::type> inline constexpr uint<N>& operator<<=(uint<N>& x, const T& y) noexcept