From 7c20aa2c621e31bcad50d4bc5eb2384d8a6286bd Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Fri, 4 Sep 2020 16:33:02 +0300 Subject: [PATCH] Another 256-bit integers (strict 32 bytes) (#14229) --- base/common/arithmeticOverflow.h | 26 +- base/common/types.h | 40 +- base/common/wide_integer.h | 249 ++++ base/common/wide_integer_impl.h | 1301 +++++++++++++++++ src/Columns/ColumnDecimal.h | 2 +- src/Columns/ColumnVector.h | 17 +- src/Common/HashTable/Hash.h | 10 +- src/Common/SipHash.h | 4 +- src/Common/UInt128.h | 5 + src/Common/intExp.h | 4 +- src/Core/BigInt.h | 69 +- src/Core/DecimalComparison.h | 12 +- src/Core/Types.h | 4 +- src/DataTypes/NumberTraits.h | 30 +- src/Functions/DivisionUtils.h | 10 +- src/Functions/FunctionBinaryArithmetic.h | 18 +- src/Functions/GatherUtils/Algorithms.h | 4 +- src/Functions/abs.cpp | 7 +- src/Functions/bitRotateLeft.cpp | 2 +- src/Functions/bitRotateRight.cpp | 2 +- src/Functions/bitShiftLeft.cpp | 4 +- src/Functions/bitShiftRight.cpp | 4 +- src/Functions/bitTest.cpp | 4 +- src/Functions/gcd.cpp | 2 +- src/Functions/lcm.cpp | 4 +- src/Functions/roundToExp2.cpp | 10 +- src/IO/WriteHelpers.h | 1 + src/IO/readDecimalText.h | 4 +- src/Interpreters/Aggregator.cpp | 4 +- src/Interpreters/HashJoin.cpp | 4 +- src/Interpreters/SetVariants.cpp | 9 +- .../0_stateless/01440_big_int_shift.reference | 638 ++++++++ .../0_stateless/01440_big_int_shift.sql | 3 + .../01457_int256_hashing.reference | 24 + .../0_stateless/01457_int256_hashing.sql | 39 + 35 files changed, 2383 insertions(+), 187 deletions(-) create mode 100644 base/common/wide_integer.h create mode 100644 base/common/wide_integer_impl.h create mode 100644 tests/queries/0_stateless/01440_big_int_shift.reference create mode 100644 tests/queries/0_stateless/01440_big_int_shift.sql create mode 100644 tests/queries/0_stateless/01457_int256_hashing.reference create mode 100644 tests/queries/0_stateless/01457_int256_hashing.sql diff --git a/base/common/arithmeticOverflow.h b/base/common/arithmeticOverflow.h index 3dfbdbc1346..e228af287e2 100644 --- a/base/common/arithmeticOverflow.h +++ b/base/common/arithmeticOverflow.h @@ -38,18 +38,18 @@ namespace common } template <> - inline bool addOverflow(bInt256 x, bInt256 y, bInt256 & res) + inline bool addOverflow(wInt256 x, wInt256 y, wInt256 & res) { res = x + y; - return (y > 0 && x > std::numeric_limits::max() - y) || - (y < 0 && x < std::numeric_limits::min() - y); + return (y > 0 && x > std::numeric_limits::max() - y) || + (y < 0 && x < std::numeric_limits::min() - y); } template <> - inline bool addOverflow(bUInt256 x, bUInt256 y, bUInt256 & res) + inline bool addOverflow(wUInt256 x, wUInt256 y, wUInt256 & res) { res = x + y; - return x > std::numeric_limits::max() - y; + return x > std::numeric_limits::max() - y; } template @@ -86,15 +86,15 @@ namespace common } template <> - inline bool subOverflow(bInt256 x, bInt256 y, bInt256 & res) + inline bool subOverflow(wInt256 x, wInt256 y, wInt256 & res) { res = x - y; - return (y < 0 && x > std::numeric_limits::max() + y) || - (y > 0 && x < std::numeric_limits::min() + y); + return (y < 0 && x > std::numeric_limits::max() + y) || + (y > 0 && x < std::numeric_limits::min() + y); } template <> - inline bool subOverflow(bUInt256 x, bUInt256 y, bUInt256 & res) + inline bool subOverflow(wUInt256 x, wUInt256 y, wUInt256 & res) { res = x - y; return x < y; @@ -137,19 +137,19 @@ namespace common } template <> - inline bool mulOverflow(bInt256 x, bInt256 y, bInt256 & res) + inline bool mulOverflow(wInt256 x, wInt256 y, wInt256 & res) { res = x * y; if (!x || !y) return false; - bInt256 a = (x > 0) ? x : -x; - bInt256 b = (y > 0) ? y : -y; + wInt256 a = (x > 0) ? x : -x; + wInt256 b = (y > 0) ? y : -y; return (a * b) / b != a; } template <> - inline bool mulOverflow(bUInt256 x, bUInt256 y, bUInt256 & res) + inline bool mulOverflow(wUInt256 x, wUInt256 y, wUInt256 & res) { res = x * y; if (!x || !y) diff --git a/base/common/types.h b/base/common/types.h index 0a394de9f5c..682fe94366c 100644 --- a/base/common/types.h +++ b/base/common/types.h @@ -6,7 +6,7 @@ #include #include -#include +#include using Int8 = int8_t; using Int16 = int16_t; @@ -25,12 +25,11 @@ using UInt64 = uint64_t; using Int128 = __int128; -/// We have to use 127 and 255 bit integers to safe a bit for a sign serialization -//using bInt256 = boost::multiprecision::int256_t; -using bInt256 = boost::multiprecision::number >; -using bUInt256 = boost::multiprecision::uint256_t; +using wInt256 = std::wide_integer<256, signed>; +using wUInt256 = std::wide_integer<256, unsigned>; +static_assert(sizeof(wInt256) == 32); +static_assert(sizeof(wUInt256) == 32); using String = std::string; @@ -44,7 +43,7 @@ struct is_signed }; template <> struct is_signed { static constexpr bool value = true; }; -template <> struct is_signed { static constexpr bool value = true; }; +template <> struct is_signed { static constexpr bool value = true; }; template inline constexpr bool is_signed_v = is_signed::value; @@ -55,7 +54,7 @@ struct is_unsigned static constexpr bool value = std::is_unsigned_v; }; -template <> struct is_unsigned { static constexpr bool value = true; }; +template <> struct is_unsigned { static constexpr bool value = true; }; template inline constexpr bool is_unsigned_v = is_unsigned::value; @@ -69,8 +68,8 @@ struct is_integer }; template <> struct is_integer { static constexpr bool value = true; }; -template <> struct is_integer { static constexpr bool value = true; }; -template <> struct is_integer { static constexpr bool value = true; }; +template <> struct is_integer { static constexpr bool value = true; }; +template <> struct is_integer { static constexpr bool value = true; }; template inline constexpr bool is_integer_v = is_integer::value; @@ -93,9 +92,9 @@ struct make_unsigned typedef std::make_unsigned_t type; }; -template <> struct make_unsigned<__int128> { using type = unsigned __int128; }; -template <> struct make_unsigned { using type = bUInt256; }; -template <> struct make_unsigned { using type = bUInt256; }; +template <> struct make_unsigned { using type = unsigned __int128; }; +template <> struct make_unsigned { using type = wUInt256; }; +template <> struct make_unsigned { using type = wUInt256; }; template using make_unsigned_t = typename make_unsigned::type; @@ -105,8 +104,8 @@ struct make_signed typedef std::make_signed_t type; }; -template <> struct make_signed { typedef bInt256 type; }; -template <> struct make_signed { typedef bInt256 type; }; +template <> struct make_signed { using type = wInt256; }; +template <> struct make_signed { using type = wInt256; }; template using make_signed_t = typename make_signed::type; @@ -116,8 +115,8 @@ struct is_big_int static constexpr bool value = false; }; -template <> struct is_big_int { static constexpr bool value = true; }; -template <> struct is_big_int { static constexpr bool value = true; }; +template <> struct is_big_int { static constexpr bool value = true; }; +template <> struct is_big_int { static constexpr bool value = true; }; template inline constexpr bool is_big_int_v = is_big_int::value; @@ -125,14 +124,11 @@ inline constexpr bool is_big_int_v = is_big_int::value; template inline std::string bigintToString(const T & x) { - return x.str(); + return to_string(x); } template inline To bigint_cast(const From & x [[maybe_unused]]) { - if constexpr ((is_big_int_v && std::is_same_v) || (is_big_int_v && std::is_same_v)) - return static_cast(x); - else - return static_cast(x); + return static_cast(x); } diff --git a/base/common/wide_integer.h b/base/common/wide_integer.h new file mode 100644 index 00000000000..67d0b3f04da --- /dev/null +++ b/base/common/wide_integer.h @@ -0,0 +1,249 @@ +#pragma once + +/////////////////////////////////////////////////////////////// +// Distributed under the Boost Software License, Version 1.0. +// (See at http://www.boost.org/LICENSE_1_0.txt) +/////////////////////////////////////////////////////////////// + +/* Divide and multiply + * + * + * Copyright (c) 2008 + * Evan Teran + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appears in all copies and that both the + * copyright notice and this permission notice appear in supporting + * documentation, and that the same name not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. We make no representations about the + * suitability this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include // CHAR_BIT +#include +#include +#include +#include + +namespace std +{ +template +class wide_integer; + +template +struct common_type, wide_integer>; + +template +struct common_type, Arithmetic>; + +template +struct common_type>; + +template +class wide_integer +{ +public: + using base_type = uint8_t; + using signed_base_type = int8_t; + + // ctors + wide_integer() = default; + + template + constexpr wide_integer(T rhs) noexcept; + template + constexpr wide_integer(std::initializer_list il) noexcept; + + // assignment + template + constexpr wide_integer & operator=(const wide_integer & rhs) noexcept; + + template + constexpr wide_integer & operator=(Arithmetic rhs) noexcept; + + template + constexpr wide_integer & operator*=(const Arithmetic & rhs); + + template + constexpr wide_integer & operator/=(const Arithmetic & rhs); + + template + constexpr wide_integer & operator+=(const Arithmetic & rhs) noexcept(is_same::value); + + template + constexpr wide_integer & operator-=(const Arithmetic & rhs) noexcept(is_same::value); + + template + constexpr wide_integer & operator%=(const Integral & rhs); + + template + constexpr wide_integer & operator&=(const Integral & rhs) noexcept; + + template + constexpr wide_integer & operator|=(const Integral & rhs) noexcept; + + template + constexpr wide_integer & operator^=(const Integral & rhs) noexcept; + + constexpr wide_integer & operator<<=(int n); + constexpr wide_integer & operator>>=(int n) noexcept; + + constexpr wide_integer & operator++() noexcept(is_same::value); + constexpr wide_integer operator++(int) noexcept(is_same::value); + constexpr wide_integer & operator--() noexcept(is_same::value); + constexpr wide_integer operator--(int) noexcept(is_same::value); + + // observers + + constexpr explicit operator bool() const noexcept; + + template + using __integral_not_wide_integer_class = typename std::enable_if::value, T>::type; + + template > + constexpr operator T() const noexcept; + + constexpr operator long double() const noexcept; + constexpr operator double() const noexcept; + constexpr operator float() const noexcept; + + struct _impl; + +private: + template + friend class wide_integer; + + friend class numeric_limits>; + friend class numeric_limits>; + + base_type m_arr[_impl::arr_size]; +}; + +template +static constexpr bool ArithmeticConcept() noexcept; +template +using __only_arithmetic = typename std::enable_if() && ArithmeticConcept()>::type; + +template +static constexpr bool IntegralConcept() noexcept; +template +using __only_integer = typename std::enable_if() && IntegralConcept()>::type; + +// Unary operators +template +constexpr wide_integer operator~(const wide_integer & lhs) noexcept; + +template +constexpr wide_integer operator-(const wide_integer & lhs) noexcept(is_same::value); + +template +constexpr wide_integer operator+(const wide_integer & lhs) noexcept(is_same::value); + +// Binary operators +template +std::common_type_t, wide_integer> constexpr +operator*(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator*(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator/(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator/(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator+(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator+(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator-(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator-(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator%(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator%(const Integral & rhs, const Integral2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator&(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator&(const Integral & rhs, const Integral2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator|(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator|(const Integral & rhs, const Integral2 & lhs); + +template +std::common_type_t, wide_integer> constexpr +operator^(const wide_integer & lhs, const wide_integer & rhs); +template > +std::common_type_t constexpr operator^(const Integral & rhs, const Integral2 & lhs); + +// TODO: Integral +template +constexpr wide_integer operator<<(const wide_integer & lhs, int n) noexcept; +template +constexpr wide_integer operator>>(const wide_integer & lhs, int n) noexcept; + +template >> +constexpr wide_integer operator<<(const wide_integer & lhs, Int n) noexcept +{ + return lhs << int(n); +} +template >> +constexpr wide_integer operator>>(const wide_integer & lhs, Int n) noexcept +{ + return lhs >> int(n); +} + +template +constexpr bool operator<(const wide_integer & lhs, const wide_integer & rhs); +template > +constexpr bool operator<(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +constexpr bool operator>(const wide_integer & lhs, const wide_integer & rhs); +template > +constexpr bool operator>(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +constexpr bool operator<=(const wide_integer & lhs, const wide_integer & rhs); +template > +constexpr bool operator<=(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +constexpr bool operator>=(const wide_integer & lhs, const wide_integer & rhs); +template > +constexpr bool operator>=(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +constexpr bool operator==(const wide_integer & lhs, const wide_integer & rhs); +template > +constexpr bool operator==(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +constexpr bool operator!=(const wide_integer & lhs, const wide_integer & rhs); +template > +constexpr bool operator!=(const Arithmetic & rhs, const Arithmetic2 & lhs); + +template +std::string to_string(const wide_integer & n); + +template +struct hash>; + +} + +#include "wide_integer_impl.h" diff --git a/base/common/wide_integer_impl.h b/base/common/wide_integer_impl.h new file mode 100644 index 00000000000..c77a9120a55 --- /dev/null +++ b/base/common/wide_integer_impl.h @@ -0,0 +1,1301 @@ +/// Original is here https://github.com/cerevra/int +#pragma once + +#include "wide_integer.h" + +#include +#include + +namespace std +{ +#define CT(x) \ + std::common_type_t, std::decay_t> { x } + +// numeric limits +template +class numeric_limits> +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = is_same::value; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = true; + static constexpr std::float_denorm_style has_denorm = std::denorm_absent; + static constexpr bool has_denorm_loss = false; + static constexpr std::float_round_style round_style = std::round_toward_zero; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = Bits - (is_same::value ? 1 : 0); + static constexpr int digits10 = digits * 0.30103 /*std::log10(2)*/; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + static constexpr wide_integer min() noexcept + { + if (is_same::value) + { + using T = wide_integer; + T res{}; + res.m_arr[T::_impl::big(0)] = std::numeric_limits::signed_base_type>::min(); + return res; + } + return 0; + } + + static constexpr wide_integer max() noexcept + { + using T = wide_integer; + T res{}; + res.m_arr[T::_impl::big(0)] = is_same::value + ? std::numeric_limits::signed_base_type>::max() + : std::numeric_limits::base_type>::max(); + for (int i = 1; i < wide_integer::_impl::arr_size; ++i) + { + res.m_arr[T::_impl::big(i)] = std::numeric_limits::base_type>::max(); + } + return res; + } + + static constexpr wide_integer lowest() noexcept { return min(); } + static constexpr wide_integer epsilon() noexcept { return 0; } + static constexpr wide_integer round_error() noexcept { return 0; } + static constexpr wide_integer infinity() noexcept { return 0; } + static constexpr wide_integer quiet_NaN() noexcept { return 0; } + static constexpr wide_integer signaling_NaN() noexcept { return 0; } + static constexpr wide_integer denorm_min() noexcept { return 0; } +}; + +template +struct IsWideInteger +{ + static const constexpr bool value = false; +}; + +template +struct IsWideInteger> +{ + static const constexpr bool value = true; +}; + +template +static constexpr bool ArithmeticConcept() noexcept +{ + return std::is_arithmetic_v || IsWideInteger::value; +} + +template +static constexpr bool IntegralConcept() noexcept +{ + return std::is_integral_v || IsWideInteger::value; +} + +// type traits +template +struct common_type, wide_integer> +{ + using type = std::conditional_t < Bits == Bits2, + wide_integer< + Bits, + std::conditional_t<(std::is_same::value && std::is_same::value), signed, unsigned>>, + std::conditional_t, wide_integer>>; +}; + +template +struct common_type, Arithmetic> +{ + static_assert(ArithmeticConcept(), ""); + + using type = std::conditional_t< + std::is_floating_point::value, + Arithmetic, + std::conditional_t< + sizeof(Arithmetic) < Bits * sizeof(long), + wide_integer, + std::conditional_t< + Bits * sizeof(long) < sizeof(Arithmetic), + Arithmetic, + std::conditional_t< + Bits * sizeof(long) == sizeof(Arithmetic) && (is_same::value || std::is_signed::value), + Arithmetic, + wide_integer>>>>; +}; + +template +struct common_type> : std::common_type, Arithmetic> +{ +}; + +template +struct wide_integer::_impl +{ + static_assert(Bits % CHAR_BIT == 0, "=)"); + + // utils + static const int base_bits = sizeof(base_type) * CHAR_BIT; + static const int arr_size = Bits / base_bits; + static constexpr size_t _Bits = Bits; + static constexpr bool _is_wide_integer = true; + + // The original implementation is big-endian. We need little one. + static constexpr unsigned little(unsigned idx) { return idx; } + static constexpr unsigned big(unsigned idx) { return arr_size - 1 - idx; } + static constexpr unsigned any(unsigned idx) { return idx; } + + template + constexpr static bool is_negative(const wide_integer & n) noexcept + { + if constexpr (std::is_same_v) + return static_cast(n.m_arr[big(0)]) < 0; + else + return false; + } + + template + constexpr static wide_integer make_positive(const wide_integer & n) noexcept + { + return is_negative(n) ? operator_unary_minus(n) : n; + } + + template + constexpr static auto to_Integral(T f) noexcept + { + if constexpr (std::is_same_v) + return f; + else if constexpr (std::is_signed_v) + return static_cast(f); + else + return static_cast(f); + } + + template + constexpr static void wide_integer_from_bultin(wide_integer & self, Integral rhs) noexcept + { + auto r = _impl::to_Integral(rhs); + + int r_idx = 0; + for (; static_cast(r_idx) < sizeof(Integral) && r_idx < arr_size; ++r_idx) + { + base_type & curr = self.m_arr[little(r_idx)]; + base_type curr_rhs = (r >> (r_idx * CHAR_BIT)) & std::numeric_limits::max(); + curr = curr_rhs; + } + + for (; r_idx < arr_size; ++r_idx) + { + base_type & curr = self.m_arr[little(r_idx)]; + curr = r < 0 ? std::numeric_limits::max() : 0; + } + } + + constexpr static void wide_integer_from_bultin(wide_integer & self, double rhs) noexcept + { + if ((rhs > 0 && rhs < std::numeric_limits::max()) || (rhs < 0 && rhs > std::numeric_limits::min())) + { + self = to_Integral(rhs); + return; + } + + long double r = rhs; + if (r < 0) + r = -r; + + size_t count = r / std::numeric_limits::max(); + self = count; + self *= std::numeric_limits::max(); + long double to_diff = count; + to_diff *= std::numeric_limits::max(); + + self += to_Integral(r - to_diff); + + if (rhs < 0) + self = -self; + } + + template + constexpr static void + wide_integer_from_wide_integer(wide_integer & self, const wide_integer & rhs) noexcept + { + // int Bits_to_copy = std::min(arr_size, rhs.arr_size); + auto rhs_arr_size = wide_integer::_impl::arr_size; + int base_elems_to_copy = _impl::arr_size < rhs_arr_size ? _impl::arr_size : rhs_arr_size; + for (int i = 0; i < base_elems_to_copy; ++i) + { + self.m_arr[little(i)] = rhs.m_arr[little(i)]; + } + for (int i = 0; i < arr_size - base_elems_to_copy; ++i) + { + self.m_arr[big(i)] = is_negative(rhs) ? std::numeric_limits::max() : 0; + } + } + + template + constexpr static bool should_keep_size() + { + return sizeof(T) * CHAR_BIT <= Bits; + } + + constexpr static wide_integer shift_left(const wide_integer & rhs, int n) + { + if (static_cast(n) >= base_bits * arr_size) + return 0; + if (n <= 0) + return rhs; + + wide_integer lhs = rhs; + int bit_shift = n % base_bits; + unsigned n_bytes = n / base_bits; + if (bit_shift) + { + lhs.m_arr[big(0)] <<= bit_shift; + for (int i = 1; i < arr_size; ++i) + { + lhs.m_arr[big(i - 1)] |= lhs.m_arr[big(i)] >> (base_bits - bit_shift); + lhs.m_arr[big(i)] <<= bit_shift; + } + } + if (n_bytes) + { + for (unsigned i = 0; i < arr_size - n_bytes; ++i) + { + lhs.m_arr[big(i)] = lhs.m_arr[big(i + n_bytes)]; + } + for (unsigned i = arr_size - n_bytes; i < arr_size; ++i) + lhs.m_arr[big(i)] = 0; + } + return lhs; + } + + constexpr static wide_integer shift_left(const wide_integer & rhs, int n) + { + // static_assert(is_negative(rhs), "shift left for negative lhsbers is underfined!"); + if (is_negative(rhs)) + throw std::runtime_error("shift left for negative lhsbers is underfined!"); + + return wide_integer(shift_left(wide_integer(rhs), n)); + } + + constexpr static wide_integer shift_right(const wide_integer & rhs, int n) noexcept + { + if (static_cast(n) >= base_bits * arr_size) + return 0; + if (n <= 0) + return rhs; + + wide_integer lhs = rhs; + int bit_shift = n % base_bits; + unsigned n_bytes = n / base_bits; + if (bit_shift) + { + lhs.m_arr[little(0)] >>= bit_shift; + for (int i = 1; i < arr_size; ++i) + { + lhs.m_arr[little(i - 1)] |= lhs.m_arr[little(i)] << (base_bits - bit_shift); + lhs.m_arr[little(i)] >>= bit_shift; + } + } + if (n_bytes) + { + for (unsigned i = 0; i < arr_size - n_bytes; ++i) + { + lhs.m_arr[little(i)] = lhs.m_arr[little(i + n_bytes)]; + } + for (unsigned i = arr_size - n_bytes; i < arr_size; ++i) + lhs.m_arr[little(i)] = 0; + } + return lhs; + } + + constexpr static wide_integer shift_right(const wide_integer & rhs, int n) noexcept + { + if (static_cast(n) >= base_bits * arr_size) + return 0; + if (n <= 0) + return rhs; + + bool is_neg = is_negative(rhs); + if (!is_neg) + return shift_right(wide_integer(rhs), n); + + wide_integer lhs = rhs; + int bit_shift = n % base_bits; + unsigned n_bytes = n / base_bits; + if (bit_shift) + { + lhs = shift_right(wide_integer(lhs), bit_shift); + lhs.m_arr[big(0)] |= std::numeric_limits::max() << (base_bits - bit_shift); + } + if (n_bytes) + { + for (unsigned i = 0; i < arr_size - n_bytes; ++i) + { + lhs.m_arr[little(i)] = lhs.m_arr[little(i + n_bytes)]; + } + for (unsigned i = arr_size - n_bytes; i < arr_size; ++i) + { + lhs.m_arr[little(i)] = std::numeric_limits::max(); + } + } + return lhs; + } + + template + constexpr static wide_integer + operator_plus_T(const wide_integer & lhs, T rhs) noexcept(is_same::value) + { + if (rhs < 0) + return _operator_minus_T(lhs, -rhs); + else + return _operator_plus_T(lhs, rhs); + } + +private: + template + constexpr static wide_integer + _operator_minus_T(const wide_integer & lhs, T rhs) noexcept(is_same::value) + { + wide_integer res = lhs; + + bool is_underflow = false; + int r_idx = 0; + for (; static_cast(r_idx) < sizeof(T) && r_idx < arr_size; ++r_idx) + { + base_type & res_i = res.m_arr[little(r_idx)]; + base_type curr_rhs = (rhs >> (r_idx * CHAR_BIT)) & std::numeric_limits::max(); + + if (is_underflow) + { + --res_i; + is_underflow = res_i == std::numeric_limits::max(); + } + + if (res_i < curr_rhs) + is_underflow = true; + res_i -= curr_rhs; + } + + if (is_underflow && r_idx < arr_size) + { + --res.m_arr[little(r_idx)]; + for (int i = arr_size - 1 - r_idx - 1; i >= 0; --i) + { + if (res.m_arr[big(i + 1)] == std::numeric_limits::max()) + --res.m_arr[big(i)]; + else + break; + } + } + + return res; + } + + template + constexpr static wide_integer + _operator_plus_T(const wide_integer & lhs, T rhs) noexcept(is_same::value) + { + wide_integer res = lhs; + + bool is_overflow = false; + int r_idx = 0; + for (; static_cast(r_idx) < sizeof(T) && r_idx < arr_size; ++r_idx) + { + base_type & res_i = res.m_arr[little(r_idx)]; + base_type curr_rhs = (rhs >> (r_idx * CHAR_BIT)) & std::numeric_limits::max(); + + if (is_overflow) + { + ++res_i; + is_overflow = res_i == 0; + } + + res_i += curr_rhs; + if (res_i < curr_rhs) + is_overflow = true; + } + + if (is_overflow && r_idx < arr_size) + { + ++res.m_arr[little(r_idx)]; + for (int i = arr_size - 1 - r_idx - 1; i >= 0; --i) + { + if (res.m_arr[big(i + 1)] == 0) + ++res.m_arr[big(i)]; + else + break; + } + } + + return res; + } + +public: + constexpr static wide_integer operator_unary_tilda(const wide_integer & lhs) noexcept + { + wide_integer res{}; + + for (int i = 0; i < arr_size; ++i) + res.m_arr[any(i)] = ~lhs.m_arr[any(i)]; + return res; + } + + constexpr static wide_integer + operator_unary_minus(const wide_integer & lhs) noexcept(is_same::value) + { + return operator_plus_T(operator_unary_tilda(lhs), 1); + } + + template + constexpr static auto operator_plus(const wide_integer & lhs, const T & rhs) noexcept(is_same::value) + { + if constexpr (should_keep_size()) + { + wide_integer t = rhs; + if (is_negative(t)) + return _operator_minus_wide_integer(lhs, operator_unary_minus(t)); + else + return _operator_plus_wide_integer(lhs, t); + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, wide_integer>::_impl::operator_plus( + wide_integer(lhs), rhs); + } + } + + template + constexpr static auto operator_minus(const wide_integer & lhs, const T & rhs) noexcept(is_same::value) + { + if constexpr (should_keep_size()) + { + wide_integer t = rhs; + if (is_negative(t)) + return _operator_plus_wide_integer(lhs, operator_unary_minus(t)); + else + return _operator_minus_wide_integer(lhs, t); + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, wide_integer>::_impl::operator_minus( + wide_integer(lhs), rhs); + } + } + +private: + constexpr static wide_integer _operator_minus_wide_integer( + const wide_integer & lhs, const wide_integer & rhs) noexcept(is_same::value) + { + wide_integer res = lhs; + + bool is_underflow = false; + for (int idx = 0; idx < arr_size; ++idx) + { + base_type & res_i = res.m_arr[little(idx)]; + const base_type rhs_i = rhs.m_arr[little(idx)]; + + if (is_underflow) + { + --res_i; + is_underflow = res_i == std::numeric_limits::max(); + } + + if (res_i < rhs_i) + is_underflow = true; + + res_i -= rhs_i; + } + + return res; + } + + constexpr static wide_integer _operator_plus_wide_integer( + const wide_integer & lhs, const wide_integer & rhs) noexcept(is_same::value) + { + wide_integer res = lhs; + + bool is_overflow = false; + for (int idx = 0; idx < arr_size; ++idx) + { + base_type & res_i = res.m_arr[little(idx)]; + const base_type rhs_i = rhs.m_arr[little(idx)]; + + if (is_overflow) + { + ++res_i; + is_overflow = res_i == 0; + } + + res_i += rhs_i; + + if (res_i < rhs_i) + is_overflow = true; + } + + return res; + } + +public: + template + constexpr static auto operator_star(const wide_integer & lhs, const T & rhs) + { + if constexpr (should_keep_size()) + { + const wide_integer a = make_positive(lhs); + wide_integer t = make_positive(wide_integer(rhs)); + + wide_integer res = 0; + + for (size_t i = 0; i < arr_size * base_bits; ++i) + { + if (t.m_arr[little(0)] & 1) + res = operator_plus(res, shift_left(a, i)); + + t = shift_right(t, 1); + } + + if (is_same::value && is_negative(wide_integer(rhs)) != is_negative(lhs)) + res = operator_unary_minus(res); + + return res; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, T>::_impl::operator_star(T(lhs), rhs); + } + } + + template + constexpr static bool operator_more(const wide_integer & lhs, const T & rhs) noexcept + { + if constexpr (should_keep_size()) + { + // static_assert(Signed == std::is_signed::value, + // "warning: operator_more: comparison of integers of different signs"); + + wide_integer t = rhs; + + if (std::numeric_limits::is_signed && (is_negative(lhs) != is_negative(t))) + return is_negative(t); + + for (int i = 0; i < arr_size; ++i) + { + if (lhs.m_arr[big(i)] != t.m_arr[big(i)]) + return lhs.m_arr[big(i)] > t.m_arr[big(i)]; + } + + return false; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, T>::_impl::operator_more(T(lhs), rhs); + } + } + + template + constexpr static bool operator_less(const wide_integer & lhs, const T & rhs) noexcept + { + if constexpr (should_keep_size()) + { + // static_assert(Signed == std::is_signed::value, + // "warning: operator_less: comparison of integers of different signs"); + + wide_integer t = rhs; + + if (std::numeric_limits::is_signed && (is_negative(lhs) != is_negative(t))) + return is_negative(lhs); + + for (int i = 0; i < arr_size; ++i) + if (lhs.m_arr[big(i)] != t.m_arr[big(i)]) + return lhs.m_arr[big(i)] < t.m_arr[big(i)]; + + return false; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, T>::_impl::operator_less(T(lhs), rhs); + } + } + + template + constexpr static bool operator_eq(const wide_integer & lhs, const T & rhs) noexcept + { + if constexpr (should_keep_size()) + { + wide_integer t = rhs; + + for (int i = 0; i < arr_size; ++i) + if (lhs.m_arr[any(i)] != t.m_arr[any(i)]) + return false; + + return true; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, T>::_impl::operator_eq(T(lhs), rhs); + } + } + + template + constexpr static auto operator_pipe(const wide_integer & lhs, const T & rhs) noexcept + { + if constexpr (should_keep_size()) + { + wide_integer t = rhs; + wide_integer res = lhs; + + for (int i = 0; i < arr_size; ++i) + res.m_arr[any(i)] |= t.m_arr[any(i)]; + return res; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, T>::_impl::operator_pipe(T(lhs), rhs); + } + } + + template + constexpr static auto operator_amp(const wide_integer & lhs, const T & rhs) noexcept + { + if constexpr (should_keep_size()) + { + wide_integer t = rhs; + wide_integer res = lhs; + + for (int i = 0; i < arr_size; ++i) + res.m_arr[any(i)] &= t.m_arr[any(i)]; + return res; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, T>::_impl::operator_amp(T(lhs), rhs); + } + } + +private: + template + constexpr static void divide(const T & lhserator, const T & denominator, T & quotient, T & remainder) + { + bool is_zero = true; + for (auto c : denominator.m_arr) + { + if (c != 0) + { + is_zero = false; + break; + } + } + + if (is_zero) + throw std::domain_error("divide by zero"); + + T n = lhserator; + T d = denominator; + T x = 1; + T answer = 0; + + while (!operator_more(d, n) && operator_eq(operator_amp(shift_right(d, base_bits * arr_size - 1), 1), 0)) + { + x = shift_left(x, 1); + d = shift_left(d, 1); + } + + while (!operator_eq(x, 0)) + { + if (!operator_more(d, n)) + { + n = operator_minus(n, d); + answer = operator_pipe(answer, x); + } + + x = shift_right(x, 1); + d = shift_right(d, 1); + } + + quotient = answer; + remainder = n; + } + +public: + template + constexpr static auto operator_slash(const wide_integer & lhs, const T & rhs) + { + if constexpr (should_keep_size()) + { + wide_integer o = rhs; + wide_integer quotient{}, remainder{}; + divide(make_positive(lhs), make_positive(o), quotient, remainder); + + if (is_same::value && is_negative(o) != is_negative(lhs)) + quotient = operator_unary_minus(quotient); + + return quotient; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, wide_integer>::operator_slash(T(lhs), rhs); + } + } + + template + constexpr static auto operator_percent(const wide_integer & lhs, const T & rhs) + { + if constexpr (should_keep_size()) + { + wide_integer o = rhs; + wide_integer quotient{}, remainder{}; + divide(make_positive(lhs), make_positive(o), quotient, remainder); + + if (is_same::value && is_negative(lhs)) + remainder = operator_unary_minus(remainder); + + return remainder; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return std::common_type_t, wide_integer>::operator_percent(T(lhs), rhs); + } + } + + // ^ + template + constexpr static auto operator_circumflex(const wide_integer & lhs, const T & rhs) noexcept + { + if constexpr (should_keep_size()) + { + wide_integer t(rhs); + wide_integer res = lhs; + + for (int i = 0; i < arr_size; ++i) + res.m_arr[any(i)] ^= t.m_arr[any(i)]; + return res; + } + else + { + static_assert(T::_impl::_is_wide_integer, ""); + return T::operator_circumflex(T(lhs), rhs); + } + } + + constexpr static wide_integer from_str(const char * c) + { + wide_integer res = 0; + + bool is_neg = is_same::value && *c == '-'; + if (is_neg) + ++c; + + if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) + { // hex + ++c; + ++c; + while (*c) + { + if (*c >= '0' && *c <= '9') + { + res = operator_star(res, 16U); + res = operator_plus_T(res, *c - '0'); + ++c; + } + else if (*c >= 'a' && *c <= 'f') + { + res = operator_star(res, 16U); + res = operator_plus_T(res, *c - 'a' + 10U); + ++c; + } + else if (*c >= 'A' && *c <= 'F') + { // tolower must be used, but it is not constexpr + res = operator_star(res, 16U); + res = operator_plus_T(res, *c - 'A' + 10U); + ++c; + } + else + throw std::runtime_error("invalid char from"); + } + } + else + { // dec + while (*c) + { + if (*c < '0' || *c > '9') + throw std::runtime_error("invalid char from"); + + res = operator_star(res, 10U); + res = operator_plus_T(res, *c - '0'); + ++c; + } + } + + if (is_neg) + res = operator_unary_minus(res); + + return res; + } +}; + +// Members + +template +template +constexpr wide_integer::wide_integer(T rhs) noexcept + : m_arr{} +{ + if constexpr (IsWideInteger::value) + _impl::wide_integer_from_wide_integer(*this, rhs); + else + _impl::wide_integer_from_bultin(*this, rhs); +} + +template +template +constexpr wide_integer::wide_integer(std::initializer_list il) noexcept + : m_arr{} +{ + if (il.size() == 1) + { + if constexpr (IsWideInteger::value) + _impl::wide_integer_from_wide_integer(*this, *il.begin()); + else + _impl::wide_integer_from_bultin(*this, *il.begin()); + } + else + _impl::wide_integer_from_bultin(*this, 0); +} + +template +template +constexpr wide_integer & wide_integer::operator=(const wide_integer & rhs) noexcept +{ + _impl::wide_integer_from_wide_integer(*this, rhs); + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator=(T rhs) noexcept +{ + _impl::wide_integer_from_bultin(*this, rhs); + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator*=(const T & rhs) +{ + *this = *this * rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator/=(const T & rhs) +{ + *this = *this / rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator+=(const T & rhs) noexcept(is_same::value) +{ + *this = *this + rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator-=(const T & rhs) noexcept(is_same::value) +{ + *this = *this - rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator%=(const T & rhs) +{ + *this = *this % rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator&=(const T & rhs) noexcept +{ + *this = *this & rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator|=(const T & rhs) noexcept +{ + *this = *this | rhs; + return *this; +} + +template +template +constexpr wide_integer & wide_integer::operator^=(const T & rhs) noexcept +{ + *this = *this ^ rhs; + return *this; +} + +template +constexpr wide_integer & wide_integer::operator<<=(int n) +{ + *this = _impl::shift_left(*this, n); + return *this; +} + +template +constexpr wide_integer & wide_integer::operator>>=(int n) noexcept +{ + *this = _impl::shift_right(*this, n); + return *this; +} + +template +constexpr wide_integer & wide_integer::operator++() noexcept(is_same::value) +{ + *this = _impl::operator_plus(*this, 1); + return *this; +} + +template +constexpr wide_integer wide_integer::operator++(int) noexcept(is_same::value) +{ + auto tmp = *this; + *this = _impl::operator_plus(*this, 1); + return tmp; +} + +template +constexpr wide_integer & wide_integer::operator--() noexcept(is_same::value) +{ + *this = _impl::operator_minus(*this, 1); + return *this; +} + +template +constexpr wide_integer wide_integer::operator--(int) noexcept(is_same::value) +{ + auto tmp = *this; + *this = _impl::operator_minus(*this, 1); + return tmp; +} + +template +constexpr wide_integer::operator bool() const noexcept +{ + return !_impl::operator_eq(*this, 0); +} + +template +template +constexpr wide_integer::operator T() const noexcept +{ + static_assert(std::numeric_limits::is_integer, ""); + T res = 0; + for (size_t r_idx = 0; r_idx < _impl::arr_size && r_idx < sizeof(T); ++r_idx) + { + res |= (T(m_arr[_impl::little(r_idx)]) << (_impl::base_bits * r_idx)); + } + return res; +} + +template +constexpr wide_integer::operator long double() const noexcept +{ + if (_impl::operator_eq(*this, 0)) + return 0; + + wide_integer tmp = *this; + if (_impl::is_negative(*this)) + tmp = -tmp; + + long double res = 0; + for (size_t idx = 0; idx < _impl::arr_size; ++idx) + { + long double t = res; + res *= std::numeric_limits::max(); + res += t; + res += tmp.m_arr[_impl::big(idx)]; + } + + if (_impl::is_negative(*this)) + res = -res; + + return res; +} + +template +constexpr wide_integer::operator double() const noexcept +{ + return static_cast(*this); +} + +template +constexpr wide_integer::operator float() const noexcept +{ + return static_cast(*this); +} + +// Unary operators +template +constexpr wide_integer operator~(const wide_integer & lhs) noexcept +{ + return wide_integer::_impl::operator_unary_tilda(lhs); +} + +template +constexpr wide_integer operator-(const wide_integer & lhs) noexcept(is_same::value) +{ + return wide_integer::_impl::operator_unary_minus(lhs); +} + +template +constexpr wide_integer operator+(const wide_integer & lhs) noexcept(is_same::value) +{ + return lhs; +} + +// Binary operators +template +std::common_type_t, wide_integer> constexpr +operator*(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_star(lhs, rhs); +} + +template +std::common_type_t constexpr operator*(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) * CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator/(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_slash(lhs, rhs); +} +template +std::common_type_t constexpr operator/(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) / CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator+(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_plus(lhs, rhs); +} +template +std::common_type_t constexpr operator+(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) + CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator-(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_minus(lhs, rhs); +} +template +std::common_type_t constexpr operator-(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) - CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator%(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_percent(lhs, rhs); +} +template +std::common_type_t constexpr operator%(const Integral & lhs, const Integral2 & rhs) +{ + return CT(lhs) % CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator&(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_amp(lhs, rhs); +} +template +std::common_type_t constexpr operator&(const Integral & lhs, const Integral2 & rhs) +{ + return CT(lhs) & CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator|(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_pipe(lhs, rhs); +} +template +std::common_type_t constexpr operator|(const Integral & lhs, const Integral2 & rhs) +{ + return CT(lhs) | CT(rhs); +} + +template +std::common_type_t, wide_integer> constexpr +operator^(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_circumflex(lhs, rhs); +} +template +std::common_type_t constexpr operator^(const Integral & lhs, const Integral2 & rhs) +{ + return CT(lhs) ^ CT(rhs); +} + +template +constexpr wide_integer operator<<(const wide_integer & lhs, int n) noexcept +{ + return wide_integer::_impl::shift_left(lhs, n); +} +template +constexpr wide_integer operator>>(const wide_integer & lhs, int n) noexcept +{ + return wide_integer::_impl::shift_right(lhs, n); +} + +template +constexpr bool operator<(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_less(lhs, rhs); +} +template +constexpr bool operator<(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) < CT(rhs); +} + +template +constexpr bool operator>(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_more(lhs, rhs); +} +template +constexpr bool operator>(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) > CT(rhs); +} + +template +constexpr bool operator<=(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_less(lhs, rhs) + || std::common_type_t, wide_integer>::_impl::operator_eq(lhs, rhs); +} +template +constexpr bool operator<=(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) <= CT(rhs); +} + +template +constexpr bool operator>=(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_more(lhs, rhs) + || std::common_type_t, wide_integer>::_impl::operator_eq(lhs, rhs); +} +template +constexpr bool operator>=(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) >= CT(rhs); +} + +template +constexpr bool operator==(const wide_integer & lhs, const wide_integer & rhs) +{ + return std::common_type_t, wide_integer>::_impl::operator_eq(lhs, rhs); +} +template +constexpr bool operator==(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) == CT(rhs); +} + +template +constexpr bool operator!=(const wide_integer & lhs, const wide_integer & rhs) +{ + return !std::common_type_t, wide_integer>::_impl::operator_eq(lhs, rhs); +} +template +constexpr bool operator!=(const Arithmetic & lhs, const Arithmetic2 & rhs) +{ + return CT(lhs) != CT(rhs); +} + +template +inline std::string to_string(const wide_integer & n) +{ + std::string res; + if (wide_integer::_impl::operator_eq(n, 0U)) + return "0"; + + wide_integer t; + bool is_neg = wide_integer::_impl::is_negative(n); + if (is_neg) + t = wide_integer::_impl::operator_unary_minus(n); + else + t = n; + + while (!wide_integer::_impl::operator_eq(t, 0U)) + { + res.insert(res.begin(), '0' + char(wide_integer::_impl::operator_percent(t, 10U))); + t = wide_integer::_impl::operator_slash(t, 10U); + } + + if (is_neg) + res.insert(res.begin(), '-'); + return res; +} + +template +struct hash> +{ + std::size_t operator()(const wide_integer & lhs) const + { + static_assert(Bits % (sizeof(size_t) * 8) == 0); + + const auto * ptr = reinterpret_cast(lhs.m_arr); + unsigned count = Bits / (sizeof(size_t) * 8); + + size_t res = 0; + for (unsigned i = 0; i < count; ++i) + res ^= ptr[i]; + return hash()(res); + } +}; + +#undef CT +} diff --git a/src/Columns/ColumnDecimal.h b/src/Columns/ColumnDecimal.h index 11ab294c1a3..c33ab34b541 100644 --- a/src/Columns/ColumnDecimal.h +++ b/src/Columns/ColumnDecimal.h @@ -126,7 +126,7 @@ public: bool isNumeric() const override { return false; } bool canBeInsideNullable() const override { return true; } - bool isFixedAndContiguous() const override { return is_POD; } + bool isFixedAndContiguous() const override { return true; } size_t sizeOfValueIfFixed() const override { return sizeof(T); } size_t size() const override { return data.size(); } diff --git a/src/Columns/ColumnVector.h b/src/Columns/ColumnVector.h index d2c4846193c..1090de556a0 100644 --- a/src/Columns/ColumnVector.h +++ b/src/Columns/ColumnVector.h @@ -12,11 +12,6 @@ namespace DB { -namespace ErrorCodes -{ - extern const int NOT_IMPLEMENTED; -} - /** Stuff for comparing numbers. * Integer values are compared as usual. * Floating-point numbers are compared this way that NaNs always end up at the end @@ -298,23 +293,17 @@ public: void gather(ColumnGathererStream & gatherer_stream) override; bool canBeInsideNullable() const override { return true; } - bool isFixedAndContiguous() const override { return is_POD; } + bool isFixedAndContiguous() const override { return true; } size_t sizeOfValueIfFixed() const override { return sizeof(T); } StringRef getRawData() const override { - if constexpr (is_POD) - return StringRef(reinterpret_cast(data.data()), byteSize()); - else - throw Exception("getRawData() is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED); + return StringRef(reinterpret_cast(data.data()), byteSize()); } StringRef getDataAt(size_t n) const override { - if constexpr (is_POD) - return StringRef(reinterpret_cast(&data[n]), sizeof(data[n])); - else - throw Exception("getDataAt() is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED); + return StringRef(reinterpret_cast(&data[n]), sizeof(data[n])); } bool structureEquals(const IColumn & rhs) const override diff --git a/src/Common/HashTable/Hash.h b/src/Common/HashTable/Hash.h index 1d850ab2d32..c561933ab80 100644 --- a/src/Common/HashTable/Hash.h +++ b/src/Common/HashTable/Hash.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -89,8 +90,7 @@ template inline typename std::enable_if, DB::UInt64>::type intHashCRC32(const T & x, DB::UInt64 updated_value) { - std::vector parts; - export_bits(x, std::back_inserter(parts), sizeof(UInt64), false); + std::vector parts = DB::BigInt::toIntArray(x); for (const auto & part : parts) updated_value = intHashCRC32(part, updated_value); @@ -199,7 +199,7 @@ inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> ke { return intHash64(key.low ^ key.high); } - else if constexpr (std::is_same_v || std::is_same_v) + else if constexpr (is_big_int_v && sizeof(T) == 32) { return intHash64(static_cast(key) ^ static_cast(key >> 64) ^ @@ -256,7 +256,7 @@ inline size_t hashCRC32(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> key) { return intHashCRC32(key.low ^ key.high); } - else if constexpr (std::is_same_v || std::is_same_v) + else if constexpr (is_big_int_v && sizeof(T) == 32) { return intHashCRC32(static_cast(key) ^ static_cast(key >> 64) ^ @@ -358,7 +358,7 @@ struct IntHash32 { return intHash32(key.low ^ key.high); } - else if constexpr (std::is_same_v || std::is_same_v) + else if constexpr (is_big_int_v && sizeof(T) == 32) { return intHash32(static_cast(key) ^ static_cast(key >> 64) ^ diff --git a/src/Common/SipHash.h b/src/Common/SipHash.h index df4c09da6d9..f4f86951652 100644 --- a/src/Common/SipHash.h +++ b/src/Common/SipHash.h @@ -148,7 +148,7 @@ public: } template - std::enable_if_t, void> update(const T & x) + std::enable_if_t && !std::has_unique_object_representations_v, void> update(const T & x) { update(DB::BigInt::serialize(x)); } @@ -213,7 +213,7 @@ std::enable_if_t, UInt64> sipHash64( } template -std::enable_if_t<(std::is_floating_point_v || is_big_int_v), UInt64> sipHash64(const T & x) +std::enable_if_t<(std::is_floating_point_v || (is_big_int_v && !std::has_unique_object_representations_v)), UInt64> sipHash64(const T & x) { SipHash hash; hash.update(x); diff --git a/src/Common/UInt128.h b/src/Common/UInt128.h index 2b1177e970c..3944d8073c2 100644 --- a/src/Common/UInt128.h +++ b/src/Common/UInt128.h @@ -67,6 +67,11 @@ struct UInt128 bool inline operator <= (const Int128 rhs) const { return *this <= UInt128(rhs, rhs >> 64) && rhs >= 0; } bool inline operator < (const Int128 rhs) const { return *this < UInt128(rhs, rhs >> 64) && rhs >= 0; } + bool inline operator > (const Int256 rhs) const { return (rhs < 0) || ((Int256(high) << 64) + low) > rhs; } + bool inline operator > (const UInt256 rhs) const { return ((UInt256(high) << 64) + low) > rhs; } + bool inline operator < (const Int256 rhs) const { return (rhs >= 0) && ((Int256(high) << 64) + low) < rhs; } + bool inline operator < (const UInt256 rhs) const { return ((UInt256(high) << 64) + low) < rhs; } + template bool inline operator== (const T rhs) const { return *this == UInt128(rhs); } template bool inline operator!= (const T rhs) const { return *this != UInt128(rhs); } template bool inline operator>= (const T rhs) const { return *this >= UInt128(rhs); } diff --git a/src/Common/intExp.h b/src/Common/intExp.h index d585eaa9c67..8a52015c54a 100644 --- a/src/Common/intExp.h +++ b/src/Common/intExp.h @@ -138,9 +138,9 @@ constexpr inline Int128 exp10_i128(int x) } -inline bInt256 exp10_i256(int x) +inline wInt256 exp10_i256(int x) { - using Int256 = bInt256; + using Int256 = wInt256; static constexpr Int256 i10e18{1000000000000000000ll}; static const Int256 values[] = { static_cast(1ll), diff --git a/src/Core/BigInt.h b/src/Core/BigInt.h index f1da96d330a..5abd7110062 100644 --- a/src/Core/BigInt.h +++ b/src/Core/BigInt.h @@ -7,46 +7,15 @@ namespace DB { template -struct BigIntPayload +struct BigInt { - static_assert(!is_big_int_v); - static constexpr size_t size = 0; -}; - -template <> struct BigIntPayload { static constexpr size_t size = 32; }; - -template <> struct BigIntPayload -{ - using UnsingedType = bUInt256; + static_assert(sizeof(T) == 32); static constexpr size_t size = 32; -}; - -template -struct BigInt : BigIntPayload -{ - using BigIntPayload::size; - - static constexpr size_t lastBit() - { - return size * 8 - 1; - } static StringRef serialize(const T & x, char * pos) { - if constexpr (is_signed_v) - { - using UnsignedT = typename BigIntPayload::UnsingedType; - - if (x < 0) - { - UnsignedT unsigned_x = UnsignedT{0} - static_cast(-x); - export_bits(unsigned_x, pos, 8, false); - } - else - export_bits(x, pos, 8, false); - } - else - export_bits(x, pos, 8, false); + //unalignedStore(pos, x); + memcpy(pos, &x, size); return StringRef(pos, size); } @@ -59,24 +28,20 @@ struct BigInt : BigIntPayload static T deserialize(const char * pos) { - if constexpr (is_signed_v) - { - using UnsignedT = typename BigIntPayload::UnsingedType; + //return unalignedLoad(pos); + T res; + memcpy(&res, pos, size); + return res; + } - UnsignedT unsigned_x; - import_bits(unsigned_x, pos, pos + size, false); - - bool is_negative = bit_test(unsigned_x, lastBit()); - if (is_negative) - unsigned_x = UnsignedT{0} - unsigned_x; - return static_cast(unsigned_x); - } - else - { - T x; - import_bits(x, pos, pos + size, false); - return x; - } + static std::vector toIntArray(const T & x) + { + std::vector parts(4, 0); + parts[0] = UInt64(x); + parts[1] = UInt64(x >> 64); + parts[2] = UInt64(x >> 128); + parts[4] = UInt64(x >> 192); + return parts; } }; diff --git a/src/Core/DecimalComparison.h b/src/Core/DecimalComparison.h index a43ce8d803c..93992029634 100644 --- a/src/Core/DecimalComparison.h +++ b/src/Core/DecimalComparison.h @@ -226,25 +226,25 @@ private: static NO_INLINE UInt8 apply(A a, B b, CompareInt scale [[maybe_unused]]) { CompareInt x; - if constexpr (is_big_int_v && IsDecimalNumber) + if constexpr (IsDecimalNumber) x = a.value; else - x = bigint_cast(a); + x = a; CompareInt y; - if constexpr (is_big_int_v && IsDecimalNumber) + if constexpr (IsDecimalNumber) y = b.value; else - y = bigint_cast(b); + y = b; if constexpr (_check_overflow) { bool overflow = false; if constexpr (sizeof(A) > sizeof(CompareInt)) - overflow |= (A(x) != a); + overflow |= (bigint_cast(x) != a); if constexpr (sizeof(B) > sizeof(CompareInt)) - overflow |= (B(y) != b); + overflow |= (bigint_cast(y) != b); if constexpr (is_unsigned_v) overflow |= (x < 0); if constexpr (is_unsigned_v) diff --git a/src/Core/Types.h b/src/Core/Types.h index 39c152ce48b..c23ac4a1379 100644 --- a/src/Core/Types.h +++ b/src/Core/Types.h @@ -58,14 +58,14 @@ using UInt8 = ::UInt8; using UInt16 = ::UInt16; using UInt32 = ::UInt32; using UInt64 = ::UInt64; -using UInt256 = ::bUInt256; +using UInt256 = ::wUInt256; using Int8 = ::Int8; using Int16 = ::Int16; using Int32 = ::Int32; using Int64 = ::Int64; using Int128 = ::Int128; -using Int256 = ::bInt256; +using Int256 = ::wInt256; using Float32 = float; using Float64 = double; diff --git a/src/DataTypes/NumberTraits.h b/src/DataTypes/NumberTraits.h index 8c70306ba5d..603449150db 100644 --- a/src/DataTypes/NumberTraits.h +++ b/src/DataTypes/NumberTraits.h @@ -28,21 +28,13 @@ constexpr size_t min(size_t x, size_t y) return x < y ? x : y; } +/// @note There's no auto scale to larger big integer, only for integral ones. +/// It's cause of (U)Int64 backward compatibilty and very big performance penalties. constexpr size_t nextSize(size_t size) { - return min(size * 2, 8); -} - -template -constexpr size_t nextSize2(size_t size) -{ - // old way for built-in integers - if (size <= 8) return nextSize(size); - - if constexpr (is_signed) - return size <= 32 ? 32 : 48; - else - return size <= 32 ? 16 : 48; + if (size < 8) + return size * 2; + return size; } template @@ -55,9 +47,8 @@ template <> struct Construct { using Type = UInt8; }; template <> struct Construct { using Type = UInt16; }; template <> struct Construct { using Type = UInt32; }; template <> struct Construct { using Type = UInt64; }; -template <> struct Construct { using Type = UInt256; }; +template <> struct Construct { using Type = UInt256; }; /// TODO: we cannot use our UInt128 here template <> struct Construct { using Type = UInt256; }; -template <> struct Construct { using Type = UInt256; }; template <> struct Construct { using Type = Float32; }; template <> struct Construct { using Type = Float32; }; template <> struct Construct { using Type = Float32; }; @@ -67,8 +58,7 @@ template <> struct Construct { using Type = Int16; }; template <> struct Construct { using Type = Int32; }; template <> struct Construct { using Type = Int64; }; template <> struct Construct { using Type = Int128; }; -template <> struct Construct { using Type = Int128; }; -template <> struct Construct { using Type = Int256; }; +template <> struct Construct { using Type = Int256; }; template <> struct Construct { using Type = Float32; }; template <> struct Construct { using Type = Float32; }; template <> struct Construct { using Type = Float32; }; @@ -86,7 +76,7 @@ template struct ResultOfAdditionMultiplication using Type = typename Construct< is_signed_v || is_signed_v, std::is_floating_point_v || std::is_floating_point_v, - nextSize2< is_signed_v || is_signed_v >(max(sizeof(A), sizeof(B)))>::Type; + nextSize(max(sizeof(A), sizeof(B)))>::Type; }; template struct ResultOfSubtraction @@ -94,7 +84,7 @@ template struct ResultOfSubtraction using Type = typename Construct< true, std::is_floating_point_v || std::is_floating_point_v, - nextSize2< is_signed_v || is_signed_v >(max(sizeof(A), sizeof(B)))>::Type; + nextSize(max(sizeof(A), sizeof(B)))>::Type; }; /** When dividing, you always get a floating-point number. @@ -127,7 +117,7 @@ template struct ResultOfNegate using Type = typename Construct< true, std::is_floating_point_v, - is_signed_v ? sizeof(A) : nextSize2(sizeof(A))>::Type; + is_signed_v ? sizeof(A) : nextSize(sizeof(A))>::Type; }; template struct ResultOfAbs diff --git a/src/Functions/DivisionUtils.h b/src/Functions/DivisionUtils.h index 99fd7795bb8..7a816df70e5 100644 --- a/src/Functions/DivisionUtils.h +++ b/src/Functions/DivisionUtils.h @@ -81,8 +81,10 @@ struct DivideIntegralImpl /// NOTE: overflow is still possible when dividing large signed number to large unsigned number or vice-versa. But it's less harmful. if constexpr (is_integer_v && is_integer_v && (is_signed_v || is_signed_v)) { - return checkedDivision(make_signed_t(a), - sizeof(A) > sizeof(B) ? make_signed_t(CastB(b)) : make_signed_t(b)); + using SignedCastA = make_signed_t; + using SignedCastB = std::conditional_t, SignedCastA>; + + return bigint_cast(checkedDivision(bigint_cast(a), bigint_cast(b))); } else return bigint_cast(checkedDivision(CastA(a), CastB(b))); @@ -108,7 +110,7 @@ struct ModuloImpl if constexpr (std::is_floating_point_v) { /// This computation is similar to `fmod` but the latter is not inlined and has 40 times worse performance. - return ResultType(a) - trunc(ResultType(a) / ResultType(b)) * ResultType(b); + return bigint_cast(a) - trunc(bigint_cast(a) / bigint_cast(b)) * bigint_cast(b); } else { @@ -125,7 +127,7 @@ struct ModuloImpl if constexpr (is_big_int_v && sizeof(IntegerAType) <= sizeof(IntegerBType)) return bigint_cast(bigint_cast(int_a) % int_b); else - return bigint_cast(int_a % int_b); + return bigint_cast(int_a % bigint_cast(int_b)); } else return IntegerAType(a) % IntegerBType(b); diff --git a/src/Functions/FunctionBinaryArithmetic.h b/src/Functions/FunctionBinaryArithmetic.h index 241f7b2fae0..2a467451684 100644 --- a/src/Functions/FunctionBinaryArithmetic.h +++ b/src/Functions/FunctionBinaryArithmetic.h @@ -361,12 +361,8 @@ private: return apply(a.value, b); else if constexpr (IsDecimalNumber) return apply(a, b.value); - else if constexpr (std::is_same_v) - return apply(UInt16(a), b); - else if constexpr (std::is_same_v) - return apply(a, UInt16(b)); else - return applyNative(static_cast(a), static_cast(b)); + return applyNative(bigint_cast(a), bigint_cast(b)); } else return applyNative(a, b); @@ -381,12 +377,8 @@ private: return applyScaled(a.value, b, scale); else if constexpr (IsDecimalNumber) return applyScaled(a, b.value, scale); - else if constexpr (std::is_same_v) - return applyScaled(UInt16(a), b, scale); - else if constexpr (std::is_same_v) - return applyScaled(a, UInt16(b), scale); else - return applyNativeScaled(static_cast(a), static_cast(b), scale); + return applyNativeScaled(bigint_cast(a), bigint_cast(b), scale); } else return applyNativeScaled(a, b, scale); @@ -401,12 +393,8 @@ private: return applyScaledDiv(a.value, b, scale); else if constexpr (IsDecimalNumber) return applyScaledDiv(a, b.value, scale); - else if constexpr (std::is_same_v) - return applyScaledDiv(UInt16(a), b, scale); - else if constexpr (std::is_same_v) - return applyScaledDiv(a, UInt16(b), scale); else - return applyNativeScaledDiv(static_cast(a), static_cast(b), scale); + return applyNativeScaledDiv(bigint_cast(a), bigint_cast(b), scale); } else return applyNativeScaledDiv(a, b, scale); diff --git a/src/Functions/GatherUtils/Algorithms.h b/src/Functions/GatherUtils/Algorithms.h index bf13de0c594..e54538c76b3 100644 --- a/src/Functions/GatherUtils/Algorithms.h +++ b/src/Functions/GatherUtils/Algorithms.h @@ -558,7 +558,7 @@ bool sliceEqualElements(const NumericArraySlice & first [[maybe_unused]], { /// TODO: Decimal scale if constexpr (IsDecimalNumber && IsDecimalNumber) - return accurate::equalsOp(typename T::NativeType(first.data[first_ind]), typename U::NativeType(second.data[second_ind])); + return accurate::equalsOp(first.data[first_ind].value, second.data[second_ind].value); else if constexpr (IsDecimalNumber || IsDecimalNumber) return false; else @@ -588,7 +588,7 @@ bool insliceEqualElements(const NumericArraySlice & first [[maybe_unused]], size_t second_ind [[maybe_unused]]) { if constexpr (IsDecimalNumber) - return accurate::equalsOp(typename T::NativeType(first.data[first_ind]), typename T::NativeType(first.data[second_ind])); + return accurate::equalsOp(first.data[first_ind].value, first.data[second_ind].value); else return accurate::equalsOp(first.data[first_ind], first.data[second_ind]); } diff --git a/src/Functions/abs.cpp b/src/Functions/abs.cpp index a7d31f4e030..f0c530e0e8f 100644 --- a/src/Functions/abs.cpp +++ b/src/Functions/abs.cpp @@ -16,11 +16,10 @@ struct AbsImpl { if constexpr (IsDecimalNumber) return a < A(0) ? A(-a) : a; - else if constexpr (is_big_int_v) - // from boost/multiprecision/number.hpp - return static_cast(abs(a)); + else if constexpr (is_big_int_v && is_signed_v) + return (a < 0) ? -a : a; else if constexpr (is_integer_v && is_signed_v) - return a < 0 ? static_cast(~a) + 1 : a; + return a < 0 ? static_cast(~a) + 1 : static_cast(a); else if constexpr (is_integer_v && is_unsigned_v) return static_cast(a); else if constexpr (std::is_floating_point_v) diff --git a/src/Functions/bitRotateLeft.cpp b/src/Functions/bitRotateLeft.cpp index 3bef0bb5ff3..a6975468c1e 100644 --- a/src/Functions/bitRotateLeft.cpp +++ b/src/Functions/bitRotateLeft.cpp @@ -18,7 +18,7 @@ struct BitRotateLeftImpl template static inline NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]]) { - if constexpr (is_big_int_v) + if constexpr (is_big_int_v || is_big_int_v) throw Exception("Bit rotate is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED); else return (static_cast(a) << static_cast(b)) diff --git a/src/Functions/bitRotateRight.cpp b/src/Functions/bitRotateRight.cpp index e94e13a8e60..71d7385bbdf 100644 --- a/src/Functions/bitRotateRight.cpp +++ b/src/Functions/bitRotateRight.cpp @@ -18,7 +18,7 @@ struct BitRotateRightImpl template static inline NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]]) { - if constexpr (is_big_int_v) + if constexpr (is_big_int_v || is_big_int_v) throw Exception("Bit rotate is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED); else return (static_cast(a) >> static_cast(b)) diff --git a/src/Functions/bitShiftLeft.cpp b/src/Functions/bitShiftLeft.cpp index 1ea69af73e9..d42082d7778 100644 --- a/src/Functions/bitShiftLeft.cpp +++ b/src/Functions/bitShiftLeft.cpp @@ -19,9 +19,9 @@ struct BitShiftLeftImpl static inline NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]]) { if constexpr (is_big_int_v) - throw Exception("BitShiftLeftImpl is not implemented for big integers as second argument", ErrorCodes::NOT_IMPLEMENTED); + throw Exception("BitShiftLeft is not implemented for big integers as second argument", ErrorCodes::NOT_IMPLEMENTED); else if constexpr (is_big_int_v) - return static_cast(a) << bigint_cast(b); + return bigint_cast(a) << bigint_cast(b); else return static_cast(a) << static_cast(b); } diff --git a/src/Functions/bitShiftRight.cpp b/src/Functions/bitShiftRight.cpp index 25eb86bf353..249a86d6961 100644 --- a/src/Functions/bitShiftRight.cpp +++ b/src/Functions/bitShiftRight.cpp @@ -19,9 +19,9 @@ struct BitShiftRightImpl static inline NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]]) { if constexpr (is_big_int_v) - throw Exception("BitRotate is not implemented for big integers as second argument", ErrorCodes::NOT_IMPLEMENTED); + throw Exception("BitShiftRight is not implemented for big integers as second argument", ErrorCodes::NOT_IMPLEMENTED); else if constexpr (is_big_int_v) - return static_cast(a) >> bigint_cast(b); + return bigint_cast(a) >> bigint_cast(b); else return static_cast(a) >> static_cast(b); } diff --git a/src/Functions/bitTest.cpp b/src/Functions/bitTest.cpp index 19afa1da84b..f34e300d675 100644 --- a/src/Functions/bitTest.cpp +++ b/src/Functions/bitTest.cpp @@ -19,10 +19,8 @@ struct BitTestImpl template NO_SANITIZE_UNDEFINED static inline Result apply(A a [[maybe_unused]], B b [[maybe_unused]]) { - if constexpr (is_big_int_v) + if constexpr (is_big_int_v || is_big_int_v) throw Exception("bitTest is not implemented for big integers as second argument", ErrorCodes::NOT_IMPLEMENTED); - else if constexpr (is_big_int_v) - return bit_test(a, static_cast(b)); else return (typename NumberTraits::ToInteger::Type(a) >> typename NumberTraits::ToInteger::Type(b)) & 1; } diff --git a/src/Functions/gcd.cpp b/src/Functions/gcd.cpp index 4ee39f3f2fd..b5d1ed6e92c 100644 --- a/src/Functions/gcd.cpp +++ b/src/Functions/gcd.cpp @@ -20,7 +20,7 @@ struct GCDImpl template static inline Result apply([[maybe_unused]] A a, [[maybe_unused]] B b) { - if constexpr (is_big_int_v || is_big_int_v) + if constexpr (is_big_int_v || is_big_int_v || is_big_int_v) throw Exception("GCD is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED); else { diff --git a/src/Functions/lcm.cpp b/src/Functions/lcm.cpp index c61337c75ad..ceca495ddce 100644 --- a/src/Functions/lcm.cpp +++ b/src/Functions/lcm.cpp @@ -40,14 +40,14 @@ struct LCMImpl static const constexpr bool allow_fixed_string = false; template - static inline std::enable_if_t || is_big_int_v, Result> + static inline std::enable_if_t || is_big_int_v || is_big_int_v, Result> apply([[maybe_unused]] A a, [[maybe_unused]] B b) { throw Exception("LCM is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED); } template - static inline std::enable_if_t && !is_big_int_v, Result> + static inline std::enable_if_t && !is_big_int_v && !is_big_int_v, Result> apply([[maybe_unused]] A a, [[maybe_unused]] B b) { throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger::Type(a), typename NumberTraits::ToInteger::Type(b)); diff --git a/src/Functions/roundToExp2.cpp b/src/Functions/roundToExp2.cpp index 12856a7930e..c6b6f672c66 100644 --- a/src/Functions/roundToExp2.cpp +++ b/src/Functions/roundToExp2.cpp @@ -6,6 +6,11 @@ namespace DB { +namespace ErrorCodes +{ + extern const int NOT_IMPLEMENTED; +} + template inline std::enable_if_t && (sizeof(T) <= sizeof(UInt32)), T> roundDownToPowerOfTwo(T x) @@ -48,10 +53,9 @@ roundDownToPowerOfTwo(T x) template inline std::enable_if_t, T> -roundDownToPowerOfTwo(T x) +roundDownToPowerOfTwo(T) { - // extention from boost/multiprecision/number.hpp - return T(1) << msb(x); + throw Exception("roundToExp2() for big integers is not implemented", ErrorCodes::NOT_IMPLEMENTED); } /** For integer data types: diff --git a/src/IO/WriteHelpers.h b/src/IO/WriteHelpers.h index fb7c4e0cd80..3b9eced09bd 100644 --- a/src/IO/WriteHelpers.h +++ b/src/IO/WriteHelpers.h @@ -831,6 +831,7 @@ template <> inline void writeText(const bool & x, WriteBuffer & buf) { wri inline void writeText(const char * x, WriteBuffer & buf) { writeEscapedString(x, strlen(x), buf); } inline void writeText(const char * x, size_t size, WriteBuffer & buf) { writeEscapedString(x, size, buf); } +inline void writeText(const DayNum & x, WriteBuffer & buf) { writeDateText(LocalDate(x), buf); } inline void writeText(const LocalDate & x, WriteBuffer & buf) { writeDateText(x, buf); } inline void writeText(const LocalDateTime & x, WriteBuffer & buf) { writeDateTimeText(x, buf); } inline void writeText(const UUID & x, WriteBuffer & buf) { writeUUIDText(x, buf); } diff --git a/src/IO/readDecimalText.h b/src/IO/readDecimalText.h index c69a56dd83e..727dd67c389 100644 --- a/src/IO/readDecimalText.h +++ b/src/IO/readDecimalText.h @@ -160,7 +160,7 @@ inline void readDecimalText(ReadBuffer & buf, T & x, uint32_t precision, uint32_ " Expected to read decimal with scale {} and precision {}"; if constexpr (is_big_int_v) - throw Exception(fmt::format(pattern, digits, x.value.str(), exponent, scale, precision), ErrorCodes::ARGUMENT_OUT_OF_BOUND); + throw Exception(fmt::format(pattern, digits, bigintToString(x.value), exponent, scale, precision), ErrorCodes::ARGUMENT_OUT_OF_BOUND); else throw Exception(fmt::format(pattern, digits, x, exponent, scale, precision), ErrorCodes::ARGUMENT_OUT_OF_BOUND); } @@ -180,7 +180,7 @@ inline void readDecimalText(ReadBuffer & buf, T & x, uint32_t precision, uint32_ { /// Too many digits after point. Just cut off excessive digits. auto divisor = intExp10OfSize(divisor_exp); - assert(divisor > T(0)); /// This is for Clang Static Analyzer. It is not smart enough to infer it automatically. + assert(divisor > 0); /// This is for Clang Static Analyzer. It is not smart enough to infer it automatically. x.value /= divisor; scale = 0; return; diff --git a/src/Interpreters/Aggregator.cpp b/src/Interpreters/Aggregator.cpp index c011aac1349..86a33dccb53 100644 --- a/src/Interpreters/Aggregator.cpp +++ b/src/Interpreters/Aggregator.cpp @@ -362,7 +362,9 @@ AggregatedDataVariants::Type Aggregator::chooseAggregationMethod() return AggregatedDataVariants::Type::key64; if (size_of_field == 16) return AggregatedDataVariants::Type::keys128; - throw Exception("Logical error: numeric column has sizeOfField not in 1, 2, 4, 8, 16.", ErrorCodes::LOGICAL_ERROR); + if (size_of_field == 32) + return AggregatedDataVariants::Type::keys256; + throw Exception("Logical error: numeric column has sizeOfField not in 1, 2, 4, 8, 16, 32.", ErrorCodes::LOGICAL_ERROR); } /// If all keys fits in N bits, will use hash table with all keys packed (placed contiguously) to single N-bit key. diff --git a/src/Interpreters/HashJoin.cpp b/src/Interpreters/HashJoin.cpp index e3f265af004..9818f89d13c 100644 --- a/src/Interpreters/HashJoin.cpp +++ b/src/Interpreters/HashJoin.cpp @@ -221,7 +221,9 @@ HashJoin::Type HashJoin::chooseMethod(const ColumnRawPtrs & key_columns, Sizes & return Type::key64; if (size_of_field == 16) return Type::keys128; - throw Exception("Logical error: numeric column has sizeOfField not in 1, 2, 4, 8, 16.", ErrorCodes::LOGICAL_ERROR); + if (size_of_field == 32) + return Type::keys256; + throw Exception("Logical error: numeric column has sizeOfField not in 1, 2, 4, 8, 16, 32.", ErrorCodes::LOGICAL_ERROR); } /// If the keys fit in N bits, we will use a hash table for N-bit-packed keys diff --git a/src/Interpreters/SetVariants.cpp b/src/Interpreters/SetVariants.cpp index b026ce56705..eb21333e3ec 100644 --- a/src/Interpreters/SetVariants.cpp +++ b/src/Interpreters/SetVariants.cpp @@ -110,9 +110,8 @@ typename SetVariantsTemplate::Type SetVariantsTemplate::choose size_t size_of_field = nested_key_columns[0]->sizeOfValueIfFixed(); if ((size_of_field == 1) || (size_of_field == 2) || (size_of_field == 4) || (size_of_field == 8)) return Type::nullable_keys128; - else - throw Exception{"Logical error: numeric column has sizeOfField not in 1, 2, 4, 8.", - ErrorCodes::LOGICAL_ERROR}; + + /// Pass to more generic method } if (all_fixed) @@ -145,7 +144,9 @@ typename SetVariantsTemplate::Type SetVariantsTemplate::choose return Type::key64; if (size_of_field == 16) return Type::keys128; - throw Exception("Logical error: numeric column has sizeOfField not in 1, 2, 4, 8, 16.", ErrorCodes::LOGICAL_ERROR); + if (size_of_field == 32) + return Type::keys256; + throw Exception("Logical error: numeric column has sizeOfField not in 1, 2, 4, 8, 16, 32.", ErrorCodes::LOGICAL_ERROR); } /// If the keys fit in N bits, we will use a hash table for N-bit-packed keys diff --git a/tests/queries/0_stateless/01440_big_int_shift.reference b/tests/queries/0_stateless/01440_big_int_shift.reference new file mode 100644 index 00000000000..392a24aa7bc --- /dev/null +++ b/tests/queries/0_stateless/01440_big_int_shift.reference @@ -0,0 +1,638 @@ +1 1 Int128 Int128 +2 1 Int128 Int128 +4 1 Int128 Int128 +8 1 Int128 Int128 +16 1 Int128 Int128 +32 1 Int128 Int128 +64 1 Int128 Int128 +128 1 Int128 Int128 +256 1 Int128 Int128 +512 1 Int128 Int128 +1024 1 Int128 Int128 +2048 1 Int128 Int128 +4096 1 Int128 Int128 +8192 1 Int128 Int128 +16384 1 Int128 Int128 +32768 1 Int128 Int128 +65536 1 Int128 Int128 +131072 1 Int128 Int128 +262144 1 Int128 Int128 +524288 1 Int128 Int128 +1048576 1 Int128 Int128 +2097152 1 Int128 Int128 +4194304 1 Int128 Int128 +8388608 1 Int128 Int128 +16777216 1 Int128 Int128 +33554432 1 Int128 Int128 +67108864 1 Int128 Int128 +134217728 1 Int128 Int128 +268435456 1 Int128 Int128 +536870912 1 Int128 Int128 +1073741824 1 Int128 Int128 +2147483648 1 Int128 Int128 +4294967296 1 Int128 Int128 +8589934592 1 Int128 Int128 +17179869184 1 Int128 Int128 +34359738368 1 Int128 Int128 +68719476736 1 Int128 Int128 +137438953472 1 Int128 Int128 +274877906944 1 Int128 Int128 +549755813888 1 Int128 Int128 +1099511627776 1 Int128 Int128 +2199023255552 1 Int128 Int128 +4398046511104 1 Int128 Int128 +8796093022208 1 Int128 Int128 +17592186044416 1 Int128 Int128 +35184372088832 1 Int128 Int128 +70368744177664 1 Int128 Int128 +140737488355328 1 Int128 Int128 +281474976710656 1 Int128 Int128 +562949953421312 1 Int128 Int128 +1125899906842624 1 Int128 Int128 +2251799813685248 1 Int128 Int128 +4503599627370496 1 Int128 Int128 +9007199254740992 1 Int128 Int128 +18014398509481984 1 Int128 Int128 +36028797018963968 1 Int128 Int128 +72057594037927936 1 Int128 Int128 +144115188075855872 1 Int128 Int128 +288230376151711744 1 Int128 Int128 +576460752303423488 1 Int128 Int128 +1152921504606846976 1 Int128 Int128 +2305843009213693952 1 Int128 Int128 +4611686018427387904 1 Int128 Int128 +9223372036854775808 1 Int128 Int128 +18446744073709551616 1 Int128 Int128 +36893488147419103232 1 Int128 Int128 +73786976294838206464 1 Int128 Int128 +147573952589676412928 1 Int128 Int128 +295147905179352825856 1 Int128 Int128 +590295810358705651712 1 Int128 Int128 +1180591620717411303424 1 Int128 Int128 +2361183241434822606848 1 Int128 Int128 +4722366482869645213696 1 Int128 Int128 +9444732965739290427392 1 Int128 Int128 +18889465931478580854784 1 Int128 Int128 +37778931862957161709568 1 Int128 Int128 +75557863725914323419136 1 Int128 Int128 +151115727451828646838272 1 Int128 Int128 +302231454903657293676544 1 Int128 Int128 +604462909807314587353088 1 Int128 Int128 +1208925819614629174706176 1 Int128 Int128 +2417851639229258349412352 1 Int128 Int128 +4835703278458516698824704 1 Int128 Int128 +9671406556917033397649408 1 Int128 Int128 +19342813113834066795298816 1 Int128 Int128 +38685626227668133590597632 1 Int128 Int128 +77371252455336267181195264 1 Int128 Int128 +154742504910672534362390528 1 Int128 Int128 +309485009821345068724781056 1 Int128 Int128 +618970019642690137449562112 1 Int128 Int128 +1237940039285380274899124224 1 Int128 Int128 +2475880078570760549798248448 1 Int128 Int128 +4951760157141521099596496896 1 Int128 Int128 +9903520314283042199192993792 1 Int128 Int128 +19807040628566084398385987584 1 Int128 Int128 +39614081257132168796771975168 1 Int128 Int128 +79228162514264337593543950336 1 Int128 Int128 +158456325028528675187087900672 1 Int128 Int128 +316912650057057350374175801344 1 Int128 Int128 +633825300114114700748351602688 1 Int128 Int128 +1267650600228229401496703205376 1 Int128 Int128 +2535301200456458802993406410752 1 Int128 Int128 +5070602400912917605986812821504 1 Int128 Int128 +10141204801825835211973625643008 1 Int128 Int128 +20282409603651670423947251286016 1 Int128 Int128 +40564819207303340847894502572032 1 Int128 Int128 +81129638414606681695789005144064 1 Int128 Int128 +162259276829213363391578010288128 1 Int128 Int128 +324518553658426726783156020576256 1 Int128 Int128 +649037107316853453566312041152512 1 Int128 Int128 +1298074214633706907132624082305024 1 Int128 Int128 +2596148429267413814265248164610048 1 Int128 Int128 +5192296858534827628530496329220096 1 Int128 Int128 +10384593717069655257060992658440192 1 Int128 Int128 +20769187434139310514121985316880384 1 Int128 Int128 +41538374868278621028243970633760768 1 Int128 Int128 +83076749736557242056487941267521536 1 Int128 Int128 +166153499473114484112975882535043072 1 Int128 Int128 +332306998946228968225951765070086144 1 Int128 Int128 +664613997892457936451903530140172288 1 Int128 Int128 +1329227995784915872903807060280344576 1 Int128 Int128 +2658455991569831745807614120560689152 1 Int128 Int128 +5316911983139663491615228241121378304 1 Int128 Int128 +10633823966279326983230456482242756608 1 Int128 Int128 +21267647932558653966460912964485513216 1 Int128 Int128 +42535295865117307932921825928971026432 1 Int128 Int128 +85070591730234615865843651857942052864 1 Int128 Int128 +1 1 Int256 Int256 +2 1 Int256 Int256 +4 1 Int256 Int256 +8 1 Int256 Int256 +16 1 Int256 Int256 +32 1 Int256 Int256 +64 1 Int256 Int256 +128 1 Int256 Int256 +256 1 Int256 Int256 +512 1 Int256 Int256 +1024 1 Int256 Int256 +2048 1 Int256 Int256 +4096 1 Int256 Int256 +8192 1 Int256 Int256 +16384 1 Int256 Int256 +32768 1 Int256 Int256 +65536 1 Int256 Int256 +131072 1 Int256 Int256 +262144 1 Int256 Int256 +524288 1 Int256 Int256 +1048576 1 Int256 Int256 +2097152 1 Int256 Int256 +4194304 1 Int256 Int256 +8388608 1 Int256 Int256 +16777216 1 Int256 Int256 +33554432 1 Int256 Int256 +67108864 1 Int256 Int256 +134217728 1 Int256 Int256 +268435456 1 Int256 Int256 +536870912 1 Int256 Int256 +1073741824 1 Int256 Int256 +2147483648 1 Int256 Int256 +4294967296 1 Int256 Int256 +8589934592 1 Int256 Int256 +17179869184 1 Int256 Int256 +34359738368 1 Int256 Int256 +68719476736 1 Int256 Int256 +137438953472 1 Int256 Int256 +274877906944 1 Int256 Int256 +549755813888 1 Int256 Int256 +1099511627776 1 Int256 Int256 +2199023255552 1 Int256 Int256 +4398046511104 1 Int256 Int256 +8796093022208 1 Int256 Int256 +17592186044416 1 Int256 Int256 +35184372088832 1 Int256 Int256 +70368744177664 1 Int256 Int256 +140737488355328 1 Int256 Int256 +281474976710656 1 Int256 Int256 +562949953421312 1 Int256 Int256 +1125899906842624 1 Int256 Int256 +2251799813685248 1 Int256 Int256 +4503599627370496 1 Int256 Int256 +9007199254740992 1 Int256 Int256 +18014398509481984 1 Int256 Int256 +36028797018963968 1 Int256 Int256 +72057594037927936 1 Int256 Int256 +144115188075855872 1 Int256 Int256 +288230376151711744 1 Int256 Int256 +576460752303423488 1 Int256 Int256 +1152921504606846976 1 Int256 Int256 +2305843009213693952 1 Int256 Int256 +4611686018427387904 1 Int256 Int256 +9223372036854775808 1 Int256 Int256 +18446744073709551616 1 Int256 Int256 +36893488147419103232 1 Int256 Int256 +73786976294838206464 1 Int256 Int256 +147573952589676412928 1 Int256 Int256 +295147905179352825856 1 Int256 Int256 +590295810358705651712 1 Int256 Int256 +1180591620717411303424 1 Int256 Int256 +2361183241434822606848 1 Int256 Int256 +4722366482869645213696 1 Int256 Int256 +9444732965739290427392 1 Int256 Int256 +18889465931478580854784 1 Int256 Int256 +37778931862957161709568 1 Int256 Int256 +75557863725914323419136 1 Int256 Int256 +151115727451828646838272 1 Int256 Int256 +302231454903657293676544 1 Int256 Int256 +604462909807314587353088 1 Int256 Int256 +1208925819614629174706176 1 Int256 Int256 +2417851639229258349412352 1 Int256 Int256 +4835703278458516698824704 1 Int256 Int256 +9671406556917033397649408 1 Int256 Int256 +19342813113834066795298816 1 Int256 Int256 +38685626227668133590597632 1 Int256 Int256 +77371252455336267181195264 1 Int256 Int256 +154742504910672534362390528 1 Int256 Int256 +309485009821345068724781056 1 Int256 Int256 +618970019642690137449562112 1 Int256 Int256 +1237940039285380274899124224 1 Int256 Int256 +2475880078570760549798248448 1 Int256 Int256 +4951760157141521099596496896 1 Int256 Int256 +9903520314283042199192993792 1 Int256 Int256 +19807040628566084398385987584 1 Int256 Int256 +39614081257132168796771975168 1 Int256 Int256 +79228162514264337593543950336 1 Int256 Int256 +158456325028528675187087900672 1 Int256 Int256 +316912650057057350374175801344 1 Int256 Int256 +633825300114114700748351602688 1 Int256 Int256 +1267650600228229401496703205376 1 Int256 Int256 +2535301200456458802993406410752 1 Int256 Int256 +5070602400912917605986812821504 1 Int256 Int256 +10141204801825835211973625643008 1 Int256 Int256 +20282409603651670423947251286016 1 Int256 Int256 +40564819207303340847894502572032 1 Int256 Int256 +81129638414606681695789005144064 1 Int256 Int256 +162259276829213363391578010288128 1 Int256 Int256 +324518553658426726783156020576256 1 Int256 Int256 +649037107316853453566312041152512 1 Int256 Int256 +1298074214633706907132624082305024 1 Int256 Int256 +2596148429267413814265248164610048 1 Int256 Int256 +5192296858534827628530496329220096 1 Int256 Int256 +10384593717069655257060992658440192 1 Int256 Int256 +20769187434139310514121985316880384 1 Int256 Int256 +41538374868278621028243970633760768 1 Int256 Int256 +83076749736557242056487941267521536 1 Int256 Int256 +166153499473114484112975882535043072 1 Int256 Int256 +332306998946228968225951765070086144 1 Int256 Int256 +664613997892457936451903530140172288 1 Int256 Int256 +1329227995784915872903807060280344576 1 Int256 Int256 +2658455991569831745807614120560689152 1 Int256 Int256 +5316911983139663491615228241121378304 1 Int256 Int256 +10633823966279326983230456482242756608 1 Int256 Int256 +21267647932558653966460912964485513216 1 Int256 Int256 +42535295865117307932921825928971026432 1 Int256 Int256 +85070591730234615865843651857942052864 1 Int256 Int256 +170141183460469231731687303715884105728 1 Int256 Int256 +340282366920938463463374607431768211456 1 Int256 Int256 +680564733841876926926749214863536422912 1 Int256 Int256 +1361129467683753853853498429727072845824 1 Int256 Int256 +2722258935367507707706996859454145691648 1 Int256 Int256 +5444517870735015415413993718908291383296 1 Int256 Int256 +10889035741470030830827987437816582766592 1 Int256 Int256 +21778071482940061661655974875633165533184 1 Int256 Int256 +43556142965880123323311949751266331066368 1 Int256 Int256 +87112285931760246646623899502532662132736 1 Int256 Int256 +174224571863520493293247799005065324265472 1 Int256 Int256 +348449143727040986586495598010130648530944 1 Int256 Int256 +696898287454081973172991196020261297061888 1 Int256 Int256 +1393796574908163946345982392040522594123776 1 Int256 Int256 +2787593149816327892691964784081045188247552 1 Int256 Int256 +5575186299632655785383929568162090376495104 1 Int256 Int256 +11150372599265311570767859136324180752990208 1 Int256 Int256 +22300745198530623141535718272648361505980416 1 Int256 Int256 +44601490397061246283071436545296723011960832 1 Int256 Int256 +89202980794122492566142873090593446023921664 1 Int256 Int256 +178405961588244985132285746181186892047843328 1 Int256 Int256 +356811923176489970264571492362373784095686656 1 Int256 Int256 +713623846352979940529142984724747568191373312 1 Int256 Int256 +1427247692705959881058285969449495136382746624 1 Int256 Int256 +2854495385411919762116571938898990272765493248 1 Int256 Int256 +5708990770823839524233143877797980545530986496 1 Int256 Int256 +11417981541647679048466287755595961091061972992 1 Int256 Int256 +22835963083295358096932575511191922182123945984 1 Int256 Int256 +45671926166590716193865151022383844364247891968 1 Int256 Int256 +91343852333181432387730302044767688728495783936 1 Int256 Int256 +182687704666362864775460604089535377456991567872 1 Int256 Int256 +365375409332725729550921208179070754913983135744 1 Int256 Int256 +730750818665451459101842416358141509827966271488 1 Int256 Int256 +1461501637330902918203684832716283019655932542976 1 Int256 Int256 +2923003274661805836407369665432566039311865085952 1 Int256 Int256 +5846006549323611672814739330865132078623730171904 1 Int256 Int256 +11692013098647223345629478661730264157247460343808 1 Int256 Int256 +23384026197294446691258957323460528314494920687616 1 Int256 Int256 +46768052394588893382517914646921056628989841375232 1 Int256 Int256 +93536104789177786765035829293842113257979682750464 1 Int256 Int256 +187072209578355573530071658587684226515959365500928 1 Int256 Int256 +374144419156711147060143317175368453031918731001856 1 Int256 Int256 +748288838313422294120286634350736906063837462003712 1 Int256 Int256 +1496577676626844588240573268701473812127674924007424 1 Int256 Int256 +2993155353253689176481146537402947624255349848014848 1 Int256 Int256 +5986310706507378352962293074805895248510699696029696 1 Int256 Int256 +11972621413014756705924586149611790497021399392059392 1 Int256 Int256 +23945242826029513411849172299223580994042798784118784 1 Int256 Int256 +47890485652059026823698344598447161988085597568237568 1 Int256 Int256 +95780971304118053647396689196894323976171195136475136 1 Int256 Int256 +191561942608236107294793378393788647952342390272950272 1 Int256 Int256 +383123885216472214589586756787577295904684780545900544 1 Int256 Int256 +766247770432944429179173513575154591809369561091801088 1 Int256 Int256 +1532495540865888858358347027150309183618739122183602176 1 Int256 Int256 +3064991081731777716716694054300618367237478244367204352 1 Int256 Int256 +6129982163463555433433388108601236734474956488734408704 1 Int256 Int256 +12259964326927110866866776217202473468949912977468817408 1 Int256 Int256 +24519928653854221733733552434404946937899825954937634816 1 Int256 Int256 +49039857307708443467467104868809893875799651909875269632 1 Int256 Int256 +98079714615416886934934209737619787751599303819750539264 1 Int256 Int256 +196159429230833773869868419475239575503198607639501078528 1 Int256 Int256 +392318858461667547739736838950479151006397215279002157056 1 Int256 Int256 +784637716923335095479473677900958302012794430558004314112 1 Int256 Int256 +1569275433846670190958947355801916604025588861116008628224 1 Int256 Int256 +3138550867693340381917894711603833208051177722232017256448 1 Int256 Int256 +6277101735386680763835789423207666416102355444464034512896 1 Int256 Int256 +12554203470773361527671578846415332832204710888928069025792 1 Int256 Int256 +25108406941546723055343157692830665664409421777856138051584 1 Int256 Int256 +50216813883093446110686315385661331328818843555712276103168 1 Int256 Int256 +100433627766186892221372630771322662657637687111424552206336 1 Int256 Int256 +200867255532373784442745261542645325315275374222849104412672 1 Int256 Int256 +401734511064747568885490523085290650630550748445698208825344 1 Int256 Int256 +803469022129495137770981046170581301261101496891396417650688 1 Int256 Int256 +1606938044258990275541962092341162602522202993782792835301376 1 Int256 Int256 +3213876088517980551083924184682325205044405987565585670602752 1 Int256 Int256 +6427752177035961102167848369364650410088811975131171341205504 1 Int256 Int256 +12855504354071922204335696738729300820177623950262342682411008 1 Int256 Int256 +25711008708143844408671393477458601640355247900524685364822016 1 Int256 Int256 +51422017416287688817342786954917203280710495801049370729644032 1 Int256 Int256 +102844034832575377634685573909834406561420991602098741459288064 1 Int256 Int256 +205688069665150755269371147819668813122841983204197482918576128 1 Int256 Int256 +411376139330301510538742295639337626245683966408394965837152256 1 Int256 Int256 +822752278660603021077484591278675252491367932816789931674304512 1 Int256 Int256 +1645504557321206042154969182557350504982735865633579863348609024 1 Int256 Int256 +3291009114642412084309938365114701009965471731267159726697218048 1 Int256 Int256 +6582018229284824168619876730229402019930943462534319453394436096 1 Int256 Int256 +13164036458569648337239753460458804039861886925068638906788872192 1 Int256 Int256 +26328072917139296674479506920917608079723773850137277813577744384 1 Int256 Int256 +52656145834278593348959013841835216159447547700274555627155488768 1 Int256 Int256 +105312291668557186697918027683670432318895095400549111254310977536 1 Int256 Int256 +210624583337114373395836055367340864637790190801098222508621955072 1 Int256 Int256 +421249166674228746791672110734681729275580381602196445017243910144 1 Int256 Int256 +842498333348457493583344221469363458551160763204392890034487820288 1 Int256 Int256 +1684996666696914987166688442938726917102321526408785780068975640576 1 Int256 Int256 +3369993333393829974333376885877453834204643052817571560137951281152 1 Int256 Int256 +6739986666787659948666753771754907668409286105635143120275902562304 1 Int256 Int256 +13479973333575319897333507543509815336818572211270286240551805124608 1 Int256 Int256 +26959946667150639794667015087019630673637144422540572481103610249216 1 Int256 Int256 +53919893334301279589334030174039261347274288845081144962207220498432 1 Int256 Int256 +107839786668602559178668060348078522694548577690162289924414440996864 1 Int256 Int256 +215679573337205118357336120696157045389097155380324579848828881993728 1 Int256 Int256 +431359146674410236714672241392314090778194310760649159697657763987456 1 Int256 Int256 +862718293348820473429344482784628181556388621521298319395315527974912 1 Int256 Int256 +1725436586697640946858688965569256363112777243042596638790631055949824 1 Int256 Int256 +3450873173395281893717377931138512726225554486085193277581262111899648 1 Int256 Int256 +6901746346790563787434755862277025452451108972170386555162524223799296 1 Int256 Int256 +13803492693581127574869511724554050904902217944340773110325048447598592 1 Int256 Int256 +27606985387162255149739023449108101809804435888681546220650096895197184 1 Int256 Int256 +55213970774324510299478046898216203619608871777363092441300193790394368 1 Int256 Int256 +110427941548649020598956093796432407239217743554726184882600387580788736 1 Int256 Int256 +220855883097298041197912187592864814478435487109452369765200775161577472 1 Int256 Int256 +441711766194596082395824375185729628956870974218904739530401550323154944 1 Int256 Int256 +883423532389192164791648750371459257913741948437809479060803100646309888 1 Int256 Int256 +1766847064778384329583297500742918515827483896875618958121606201292619776 1 Int256 Int256 +3533694129556768659166595001485837031654967793751237916243212402585239552 1 Int256 Int256 +7067388259113537318333190002971674063309935587502475832486424805170479104 1 Int256 Int256 +14134776518227074636666380005943348126619871175004951664972849610340958208 1 Int256 Int256 +28269553036454149273332760011886696253239742350009903329945699220681916416 1 Int256 Int256 +56539106072908298546665520023773392506479484700019806659891398441363832832 1 Int256 Int256 +113078212145816597093331040047546785012958969400039613319782796882727665664 1 Int256 Int256 +226156424291633194186662080095093570025917938800079226639565593765455331328 1 Int256 Int256 +452312848583266388373324160190187140051835877600158453279131187530910662656 1 Int256 Int256 +904625697166532776746648320380374280103671755200316906558262375061821325312 1 Int256 Int256 +1809251394333065553493296640760748560207343510400633813116524750123642650624 1 Int256 Int256 +3618502788666131106986593281521497120414687020801267626233049500247285301248 1 Int256 Int256 +7237005577332262213973186563042994240829374041602535252466099000494570602496 1 Int256 Int256 +14474011154664524427946373126085988481658748083205070504932198000989141204992 1 Int256 Int256 +28948022309329048855892746252171976963317496166410141009864396001978282409984 1 Int256 Int256 +1 1 UInt256 UInt256 +2 1 UInt256 UInt256 +4 1 UInt256 UInt256 +8 1 UInt256 UInt256 +16 1 UInt256 UInt256 +32 1 UInt256 UInt256 +64 1 UInt256 UInt256 +128 1 UInt256 UInt256 +256 1 UInt256 UInt256 +512 1 UInt256 UInt256 +1024 1 UInt256 UInt256 +2048 1 UInt256 UInt256 +4096 1 UInt256 UInt256 +8192 1 UInt256 UInt256 +16384 1 UInt256 UInt256 +32768 1 UInt256 UInt256 +65536 1 UInt256 UInt256 +131072 1 UInt256 UInt256 +262144 1 UInt256 UInt256 +524288 1 UInt256 UInt256 +1048576 1 UInt256 UInt256 +2097152 1 UInt256 UInt256 +4194304 1 UInt256 UInt256 +8388608 1 UInt256 UInt256 +16777216 1 UInt256 UInt256 +33554432 1 UInt256 UInt256 +67108864 1 UInt256 UInt256 +134217728 1 UInt256 UInt256 +268435456 1 UInt256 UInt256 +536870912 1 UInt256 UInt256 +1073741824 1 UInt256 UInt256 +2147483648 1 UInt256 UInt256 +4294967296 1 UInt256 UInt256 +8589934592 1 UInt256 UInt256 +17179869184 1 UInt256 UInt256 +34359738368 1 UInt256 UInt256 +68719476736 1 UInt256 UInt256 +137438953472 1 UInt256 UInt256 +274877906944 1 UInt256 UInt256 +549755813888 1 UInt256 UInt256 +1099511627776 1 UInt256 UInt256 +2199023255552 1 UInt256 UInt256 +4398046511104 1 UInt256 UInt256 +8796093022208 1 UInt256 UInt256 +17592186044416 1 UInt256 UInt256 +35184372088832 1 UInt256 UInt256 +70368744177664 1 UInt256 UInt256 +140737488355328 1 UInt256 UInt256 +281474976710656 1 UInt256 UInt256 +562949953421312 1 UInt256 UInt256 +1125899906842624 1 UInt256 UInt256 +2251799813685248 1 UInt256 UInt256 +4503599627370496 1 UInt256 UInt256 +9007199254740992 1 UInt256 UInt256 +18014398509481984 1 UInt256 UInt256 +36028797018963968 1 UInt256 UInt256 +72057594037927936 1 UInt256 UInt256 +144115188075855872 1 UInt256 UInt256 +288230376151711744 1 UInt256 UInt256 +576460752303423488 1 UInt256 UInt256 +1152921504606846976 1 UInt256 UInt256 +2305843009213693952 1 UInt256 UInt256 +4611686018427387904 1 UInt256 UInt256 +9223372036854775808 1 UInt256 UInt256 +18446744073709551616 1 UInt256 UInt256 +36893488147419103232 1 UInt256 UInt256 +73786976294838206464 1 UInt256 UInt256 +147573952589676412928 1 UInt256 UInt256 +295147905179352825856 1 UInt256 UInt256 +590295810358705651712 1 UInt256 UInt256 +1180591620717411303424 1 UInt256 UInt256 +2361183241434822606848 1 UInt256 UInt256 +4722366482869645213696 1 UInt256 UInt256 +9444732965739290427392 1 UInt256 UInt256 +18889465931478580854784 1 UInt256 UInt256 +37778931862957161709568 1 UInt256 UInt256 +75557863725914323419136 1 UInt256 UInt256 +151115727451828646838272 1 UInt256 UInt256 +302231454903657293676544 1 UInt256 UInt256 +604462909807314587353088 1 UInt256 UInt256 +1208925819614629174706176 1 UInt256 UInt256 +2417851639229258349412352 1 UInt256 UInt256 +4835703278458516698824704 1 UInt256 UInt256 +9671406556917033397649408 1 UInt256 UInt256 +19342813113834066795298816 1 UInt256 UInt256 +38685626227668133590597632 1 UInt256 UInt256 +77371252455336267181195264 1 UInt256 UInt256 +154742504910672534362390528 1 UInt256 UInt256 +309485009821345068724781056 1 UInt256 UInt256 +618970019642690137449562112 1 UInt256 UInt256 +1237940039285380274899124224 1 UInt256 UInt256 +2475880078570760549798248448 1 UInt256 UInt256 +4951760157141521099596496896 1 UInt256 UInt256 +9903520314283042199192993792 1 UInt256 UInt256 +19807040628566084398385987584 1 UInt256 UInt256 +39614081257132168796771975168 1 UInt256 UInt256 +79228162514264337593543950336 1 UInt256 UInt256 +158456325028528675187087900672 1 UInt256 UInt256 +316912650057057350374175801344 1 UInt256 UInt256 +633825300114114700748351602688 1 UInt256 UInt256 +1267650600228229401496703205376 1 UInt256 UInt256 +2535301200456458802993406410752 1 UInt256 UInt256 +5070602400912917605986812821504 1 UInt256 UInt256 +10141204801825835211973625643008 1 UInt256 UInt256 +20282409603651670423947251286016 1 UInt256 UInt256 +40564819207303340847894502572032 1 UInt256 UInt256 +81129638414606681695789005144064 1 UInt256 UInt256 +162259276829213363391578010288128 1 UInt256 UInt256 +324518553658426726783156020576256 1 UInt256 UInt256 +649037107316853453566312041152512 1 UInt256 UInt256 +1298074214633706907132624082305024 1 UInt256 UInt256 +2596148429267413814265248164610048 1 UInt256 UInt256 +5192296858534827628530496329220096 1 UInt256 UInt256 +10384593717069655257060992658440192 1 UInt256 UInt256 +20769187434139310514121985316880384 1 UInt256 UInt256 +41538374868278621028243970633760768 1 UInt256 UInt256 +83076749736557242056487941267521536 1 UInt256 UInt256 +166153499473114484112975882535043072 1 UInt256 UInt256 +332306998946228968225951765070086144 1 UInt256 UInt256 +664613997892457936451903530140172288 1 UInt256 UInt256 +1329227995784915872903807060280344576 1 UInt256 UInt256 +2658455991569831745807614120560689152 1 UInt256 UInt256 +5316911983139663491615228241121378304 1 UInt256 UInt256 +10633823966279326983230456482242756608 1 UInt256 UInt256 +21267647932558653966460912964485513216 1 UInt256 UInt256 +42535295865117307932921825928971026432 1 UInt256 UInt256 +85070591730234615865843651857942052864 1 UInt256 UInt256 +170141183460469231731687303715884105728 1 UInt256 UInt256 +340282366920938463463374607431768211456 1 UInt256 UInt256 +680564733841876926926749214863536422912 1 UInt256 UInt256 +1361129467683753853853498429727072845824 1 UInt256 UInt256 +2722258935367507707706996859454145691648 1 UInt256 UInt256 +5444517870735015415413993718908291383296 1 UInt256 UInt256 +10889035741470030830827987437816582766592 1 UInt256 UInt256 +21778071482940061661655974875633165533184 1 UInt256 UInt256 +43556142965880123323311949751266331066368 1 UInt256 UInt256 +87112285931760246646623899502532662132736 1 UInt256 UInt256 +174224571863520493293247799005065324265472 1 UInt256 UInt256 +348449143727040986586495598010130648530944 1 UInt256 UInt256 +696898287454081973172991196020261297061888 1 UInt256 UInt256 +1393796574908163946345982392040522594123776 1 UInt256 UInt256 +2787593149816327892691964784081045188247552 1 UInt256 UInt256 +5575186299632655785383929568162090376495104 1 UInt256 UInt256 +11150372599265311570767859136324180752990208 1 UInt256 UInt256 +22300745198530623141535718272648361505980416 1 UInt256 UInt256 +44601490397061246283071436545296723011960832 1 UInt256 UInt256 +89202980794122492566142873090593446023921664 1 UInt256 UInt256 +178405961588244985132285746181186892047843328 1 UInt256 UInt256 +356811923176489970264571492362373784095686656 1 UInt256 UInt256 +713623846352979940529142984724747568191373312 1 UInt256 UInt256 +1427247692705959881058285969449495136382746624 1 UInt256 UInt256 +2854495385411919762116571938898990272765493248 1 UInt256 UInt256 +5708990770823839524233143877797980545530986496 1 UInt256 UInt256 +11417981541647679048466287755595961091061972992 1 UInt256 UInt256 +22835963083295358096932575511191922182123945984 1 UInt256 UInt256 +45671926166590716193865151022383844364247891968 1 UInt256 UInt256 +91343852333181432387730302044767688728495783936 1 UInt256 UInt256 +182687704666362864775460604089535377456991567872 1 UInt256 UInt256 +365375409332725729550921208179070754913983135744 1 UInt256 UInt256 +730750818665451459101842416358141509827966271488 1 UInt256 UInt256 +1461501637330902918203684832716283019655932542976 1 UInt256 UInt256 +2923003274661805836407369665432566039311865085952 1 UInt256 UInt256 +5846006549323611672814739330865132078623730171904 1 UInt256 UInt256 +11692013098647223345629478661730264157247460343808 1 UInt256 UInt256 +23384026197294446691258957323460528314494920687616 1 UInt256 UInt256 +46768052394588893382517914646921056628989841375232 1 UInt256 UInt256 +93536104789177786765035829293842113257979682750464 1 UInt256 UInt256 +187072209578355573530071658587684226515959365500928 1 UInt256 UInt256 +374144419156711147060143317175368453031918731001856 1 UInt256 UInt256 +748288838313422294120286634350736906063837462003712 1 UInt256 UInt256 +1496577676626844588240573268701473812127674924007424 1 UInt256 UInt256 +2993155353253689176481146537402947624255349848014848 1 UInt256 UInt256 +5986310706507378352962293074805895248510699696029696 1 UInt256 UInt256 +11972621413014756705924586149611790497021399392059392 1 UInt256 UInt256 +23945242826029513411849172299223580994042798784118784 1 UInt256 UInt256 +47890485652059026823698344598447161988085597568237568 1 UInt256 UInt256 +95780971304118053647396689196894323976171195136475136 1 UInt256 UInt256 +191561942608236107294793378393788647952342390272950272 1 UInt256 UInt256 +383123885216472214589586756787577295904684780545900544 1 UInt256 UInt256 +766247770432944429179173513575154591809369561091801088 1 UInt256 UInt256 +1532495540865888858358347027150309183618739122183602176 1 UInt256 UInt256 +3064991081731777716716694054300618367237478244367204352 1 UInt256 UInt256 +6129982163463555433433388108601236734474956488734408704 1 UInt256 UInt256 +12259964326927110866866776217202473468949912977468817408 1 UInt256 UInt256 +24519928653854221733733552434404946937899825954937634816 1 UInt256 UInt256 +49039857307708443467467104868809893875799651909875269632 1 UInt256 UInt256 +98079714615416886934934209737619787751599303819750539264 1 UInt256 UInt256 +196159429230833773869868419475239575503198607639501078528 1 UInt256 UInt256 +392318858461667547739736838950479151006397215279002157056 1 UInt256 UInt256 +784637716923335095479473677900958302012794430558004314112 1 UInt256 UInt256 +1569275433846670190958947355801916604025588861116008628224 1 UInt256 UInt256 +3138550867693340381917894711603833208051177722232017256448 1 UInt256 UInt256 +6277101735386680763835789423207666416102355444464034512896 1 UInt256 UInt256 +12554203470773361527671578846415332832204710888928069025792 1 UInt256 UInt256 +25108406941546723055343157692830665664409421777856138051584 1 UInt256 UInt256 +50216813883093446110686315385661331328818843555712276103168 1 UInt256 UInt256 +100433627766186892221372630771322662657637687111424552206336 1 UInt256 UInt256 +200867255532373784442745261542645325315275374222849104412672 1 UInt256 UInt256 +401734511064747568885490523085290650630550748445698208825344 1 UInt256 UInt256 +803469022129495137770981046170581301261101496891396417650688 1 UInt256 UInt256 +1606938044258990275541962092341162602522202993782792835301376 1 UInt256 UInt256 +3213876088517980551083924184682325205044405987565585670602752 1 UInt256 UInt256 +6427752177035961102167848369364650410088811975131171341205504 1 UInt256 UInt256 +12855504354071922204335696738729300820177623950262342682411008 1 UInt256 UInt256 +25711008708143844408671393477458601640355247900524685364822016 1 UInt256 UInt256 +51422017416287688817342786954917203280710495801049370729644032 1 UInt256 UInt256 +102844034832575377634685573909834406561420991602098741459288064 1 UInt256 UInt256 +205688069665150755269371147819668813122841983204197482918576128 1 UInt256 UInt256 +411376139330301510538742295639337626245683966408394965837152256 1 UInt256 UInt256 +822752278660603021077484591278675252491367932816789931674304512 1 UInt256 UInt256 +1645504557321206042154969182557350504982735865633579863348609024 1 UInt256 UInt256 +3291009114642412084309938365114701009965471731267159726697218048 1 UInt256 UInt256 +6582018229284824168619876730229402019930943462534319453394436096 1 UInt256 UInt256 +13164036458569648337239753460458804039861886925068638906788872192 1 UInt256 UInt256 +26328072917139296674479506920917608079723773850137277813577744384 1 UInt256 UInt256 +52656145834278593348959013841835216159447547700274555627155488768 1 UInt256 UInt256 +105312291668557186697918027683670432318895095400549111254310977536 1 UInt256 UInt256 +210624583337114373395836055367340864637790190801098222508621955072 1 UInt256 UInt256 +421249166674228746791672110734681729275580381602196445017243910144 1 UInt256 UInt256 +842498333348457493583344221469363458551160763204392890034487820288 1 UInt256 UInt256 +1684996666696914987166688442938726917102321526408785780068975640576 1 UInt256 UInt256 +3369993333393829974333376885877453834204643052817571560137951281152 1 UInt256 UInt256 +6739986666787659948666753771754907668409286105635143120275902562304 1 UInt256 UInt256 +13479973333575319897333507543509815336818572211270286240551805124608 1 UInt256 UInt256 +26959946667150639794667015087019630673637144422540572481103610249216 1 UInt256 UInt256 +53919893334301279589334030174039261347274288845081144962207220498432 1 UInt256 UInt256 +107839786668602559178668060348078522694548577690162289924414440996864 1 UInt256 UInt256 +215679573337205118357336120696157045389097155380324579848828881993728 1 UInt256 UInt256 +431359146674410236714672241392314090778194310760649159697657763987456 1 UInt256 UInt256 +862718293348820473429344482784628181556388621521298319395315527974912 1 UInt256 UInt256 +1725436586697640946858688965569256363112777243042596638790631055949824 1 UInt256 UInt256 +3450873173395281893717377931138512726225554486085193277581262111899648 1 UInt256 UInt256 +6901746346790563787434755862277025452451108972170386555162524223799296 1 UInt256 UInt256 +13803492693581127574869511724554050904902217944340773110325048447598592 1 UInt256 UInt256 +27606985387162255149739023449108101809804435888681546220650096895197184 1 UInt256 UInt256 +55213970774324510299478046898216203619608871777363092441300193790394368 1 UInt256 UInt256 +110427941548649020598956093796432407239217743554726184882600387580788736 1 UInt256 UInt256 +220855883097298041197912187592864814478435487109452369765200775161577472 1 UInt256 UInt256 +441711766194596082395824375185729628956870974218904739530401550323154944 1 UInt256 UInt256 +883423532389192164791648750371459257913741948437809479060803100646309888 1 UInt256 UInt256 +1766847064778384329583297500742918515827483896875618958121606201292619776 1 UInt256 UInt256 +3533694129556768659166595001485837031654967793751237916243212402585239552 1 UInt256 UInt256 +7067388259113537318333190002971674063309935587502475832486424805170479104 1 UInt256 UInt256 +14134776518227074636666380005943348126619871175004951664972849610340958208 1 UInt256 UInt256 +28269553036454149273332760011886696253239742350009903329945699220681916416 1 UInt256 UInt256 +56539106072908298546665520023773392506479484700019806659891398441363832832 1 UInt256 UInt256 +113078212145816597093331040047546785012958969400039613319782796882727665664 1 UInt256 UInt256 +226156424291633194186662080095093570025917938800079226639565593765455331328 1 UInt256 UInt256 +452312848583266388373324160190187140051835877600158453279131187530910662656 1 UInt256 UInt256 +904625697166532776746648320380374280103671755200316906558262375061821325312 1 UInt256 UInt256 +1809251394333065553493296640760748560207343510400633813116524750123642650624 1 UInt256 UInt256 +3618502788666131106986593281521497120414687020801267626233049500247285301248 1 UInt256 UInt256 +7237005577332262213973186563042994240829374041602535252466099000494570602496 1 UInt256 UInt256 +14474011154664524427946373126085988481658748083205070504932198000989141204992 1 UInt256 UInt256 +28948022309329048855892746252171976963317496166410141009864396001978282409984 1 UInt256 UInt256 +57896044618658097711785492504343953926634992332820282019728792003956564819968 1 UInt256 UInt256 diff --git a/tests/queries/0_stateless/01440_big_int_shift.sql b/tests/queries/0_stateless/01440_big_int_shift.sql new file mode 100644 index 00000000000..e24ae1ba911 --- /dev/null +++ b/tests/queries/0_stateless/01440_big_int_shift.sql @@ -0,0 +1,3 @@ +SELECT bitShiftLeft(toInt128(1), number) x, bitShiftRight(x, number) y, toTypeName(x), toTypeName(y) FROM numbers(127) ORDER BY number; +SELECT bitShiftLeft(toInt256(1), number) x, bitShiftRight(x, number) y, toTypeName(x), toTypeName(y) FROM numbers(255) ORDER BY number; +SELECT bitShiftLeft(toUInt256(1), number) x, bitShiftRight(x, number) y, toTypeName(x), toTypeName(y) FROM numbers(256) ORDER BY number; diff --git a/tests/queries/0_stateless/01457_int256_hashing.reference b/tests/queries/0_stateless/01457_int256_hashing.reference new file mode 100644 index 00000000000..e1a6a2ad341 --- /dev/null +++ b/tests/queries/0_stateless/01457_int256_hashing.reference @@ -0,0 +1,24 @@ +0 +123 +123 +[1,1,2] +0 +123 +123 +[1,1,2] +0 +123 +123 +[1,1,2] +0 +321 +321 +[1,1,2] +0 +321 +321 +[1,1,2] +0 +321 +321 +[1,1,2] diff --git a/tests/queries/0_stateless/01457_int256_hashing.sql b/tests/queries/0_stateless/01457_int256_hashing.sql new file mode 100644 index 00000000000..d6d655e80f3 --- /dev/null +++ b/tests/queries/0_stateless/01457_int256_hashing.sql @@ -0,0 +1,39 @@ +SELECT toUInt256(123) IN (NULL); +SELECT toUInt256(123) AS k GROUP BY k; +SELECT toUInt256(123) AS k FROM system.one INNER JOIN (SELECT toUInt256(123) AS k) t USING k; +SELECT arrayEnumerateUniq([toUInt256(123), toUInt256(456), toUInt256(123)]); + +SELECT toInt256(123) IN (NULL); +SELECT toInt256(123) AS k GROUP BY k; +SELECT toInt256(123) AS k FROM system.one INNER JOIN (SELECT toInt256(123) AS k) t USING k; +SELECT arrayEnumerateUniq([toInt256(123), toInt256(456), toInt256(123)]); + +-- SELECT toUInt128(123) IN (NULL); +-- SELECT toUInt128(123) AS k GROUP BY k; +-- SELECT toUInt128(123) AS k FROM system.one INNER JOIN (SELECT toUInt128(123) AS k) t USING k; +-- SELECT arrayEnumerateUniq([toUInt128(123), toUInt128(456), toUInt128(123)]); + +SELECT toInt128(123) IN (NULL); +SELECT toInt128(123) AS k GROUP BY k; +SELECT toInt128(123) AS k FROM system.one INNER JOIN (SELECT toInt128(123) AS k) t USING k; +SELECT arrayEnumerateUniq([toInt128(123), toInt128(456), toInt128(123)]); + +SELECT toNullable(toUInt256(321)) IN (NULL); +SELECT toNullable(toUInt256(321)) AS k GROUP BY k; +SELECT toNullable(toUInt256(321)) AS k FROM system.one INNER JOIN (SELECT toUInt256(321) AS k) t USING k; +SELECT arrayEnumerateUniq([toNullable(toUInt256(321)), toNullable(toUInt256(456)), toNullable(toUInt256(321))]); + +SELECT toNullable(toInt256(321)) IN (NULL); +SELECT toNullable(toInt256(321)) AS k GROUP BY k; +SELECT toNullable(toInt256(321)) AS k FROM system.one INNER JOIN (SELECT toInt256(321) AS k) t USING k; +SELECT arrayEnumerateUniq([toNullable(toInt256(321)), toNullable(toInt256(456)), toNullable(toInt256(321))]); + +-- SELECT toNullable(toUInt128(321)) IN (NULL); +-- SELECT toNullable(toUInt128(321)) AS k GROUP BY k; +-- SELECT toNullable(toUInt128(321)) AS k FROM system.one INNER JOIN (SELECT toUInt128(321) AS k) t USING k; +-- SELECT arrayEnumerateUniq([toNullable(toUInt128(321)), toNullable(toUInt128(456)), toNullable(toUInt128(321))]); + +SELECT toNullable(toInt128(321)) IN (NULL); +SELECT toNullable(toInt128(321)) AS k GROUP BY k; +SELECT toNullable(toInt128(321)) AS k FROM system.one INNER JOIN (SELECT toInt128(321) AS k) t USING k; +SELECT arrayEnumerateUniq([toNullable(toInt128(321)), toNullable(toInt128(456)), toNullable(toInt128(321))]);