From 0520b05001d0a72d72bce9a83fcba0d9dcf2acf3 Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Fri, 18 Sep 2020 12:51:44 +0300 Subject: [PATCH] Speedup wide integers (#14859) --- base/common/wide_integer.h | 6 +- base/common/wide_integer_impl.h | 656 +++++++++--------- .../01440_big_int_exotic_casts.reference | 292 ++++++++ .../01440_big_int_exotic_casts.sql | 48 ++ 4 files changed, 662 insertions(+), 340 deletions(-) create mode 100644 tests/queries/0_stateless/01440_big_int_exotic_casts.reference create mode 100644 tests/queries/0_stateless/01440_big_int_exotic_casts.sql diff --git a/base/common/wide_integer.h b/base/common/wide_integer.h index 2aeac072b3f..61d88bdcaf3 100644 --- a/base/common/wide_integer.h +++ b/base/common/wide_integer.h @@ -54,8 +54,8 @@ template class integer { public: - using base_type = uint8_t; - using signed_base_type = int8_t; + using base_type = uint64_t; + using signed_base_type = int64_t; // ctors integer() = default; @@ -127,7 +127,7 @@ private: friend class std::numeric_limits>; friend class std::numeric_limits>; - base_type m_arr[_impl::arr_size]; + base_type items[_impl::item_count]; }; template diff --git a/base/common/wide_integer_impl.h b/base/common/wide_integer_impl.h index 26bd6704bdc..5673ac46c4a 100644 --- a/base/common/wide_integer_impl.h +++ b/base/common/wide_integer_impl.h @@ -3,10 +3,6 @@ #include "throwError.h" -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - namespace wide { @@ -74,7 +70,7 @@ public: { using T = wide::integer; T res{}; - res.m_arr[T::_impl::big(0)] = std::numeric_limits::signed_base_type>::min(); + res.items[T::_impl::big(0)] = std::numeric_limits::signed_base_type>::min(); return res; } return 0; @@ -84,12 +80,12 @@ public: { using T = wide::integer; T res{}; - res.m_arr[T::_impl::big(0)] = is_same::value + res.items[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) + for (unsigned i = 1; i < wide::integer::_impl::item_count; ++i) { - res.m_arr[T::_impl::big(i)] = std::numeric_limits::base_type>::max(); + res.items[T::_impl::big(i)] = std::numeric_limits::base_type>::max(); } return res; } @@ -147,28 +143,45 @@ namespace wide template struct 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; + static constexpr const unsigned byte_count = Bits / 8; + static constexpr const unsigned item_count = byte_count / sizeof(base_type); + static constexpr const unsigned base_bits = sizeof(base_type) * 8; - // The original implementation is big-endian. We need little one. + static_assert(Bits % base_bits == 0); + + /// Simple iteration in both directions static constexpr unsigned little(unsigned idx) { return idx; } - static constexpr unsigned big(unsigned idx) { return arr_size - 1 - idx; } + static constexpr unsigned big(unsigned idx) { return item_count - 1 - idx; } static constexpr unsigned any(unsigned idx) { return idx; } + template + constexpr static bool is_negative(const T & n) noexcept + { + if constexpr (std::is_signed_v) + return n < 0; + else + return false; + } + template constexpr static bool is_negative(const integer & n) noexcept { if constexpr (std::is_same_v) - return static_cast(n.m_arr[big(0)]) < 0; + return static_cast(n.items[big(0)]) < 0; else return false; } + template + constexpr static auto make_positive(const T & n) noexcept + { + if constexpr (std::is_signed_v) + return n < 0 ? -n : n; + else + return n; + } + template constexpr static integer make_positive(const integer & n) noexcept { @@ -189,21 +202,24 @@ struct integer::_impl template constexpr static void wide_integer_from_bultin(integer & self, Integral rhs) noexcept { - auto r = _impl::to_Integral(rhs); + self.items[0] = _impl::to_Integral(rhs); + if constexpr (std::is_same_v) + self.items[1] = rhs >> base_bits; - int r_idx = 0; - for (; static_cast(r_idx) < sizeof(Integral) && r_idx < arr_size; ++r_idx) + constexpr const unsigned start = (sizeof(Integral) == 16) ? 2 : 1; + + if constexpr (std::is_signed_v) { - 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; + if (rhs < 0) + { + for (unsigned i = start; i < item_count; ++i) + self.items[i] = -1; + return; + } } - for (; r_idx < arr_size; ++r_idx) - { - base_type & curr = self.m_arr[little(r_idx)]; - curr = r < 0 ? std::numeric_limits::max() : 0; - } + for (unsigned i = start; i < item_count; ++i) + self.items[i] = 0; } constexpr static void wide_integer_from_bultin(integer & self, double rhs) noexcept @@ -234,170 +250,142 @@ struct integer::_impl constexpr static void wide_integer_from_wide_integer(integer & self, const integer & rhs) noexcept { - // int Bits_to_copy = std::min(arr_size, rhs.arr_size); - auto rhs_arr_size = 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) + constexpr const unsigned min_bits = (Bits < Bits2) ? Bits : Bits2; + constexpr const unsigned to_copy = min_bits / base_bits; + + for (unsigned i = 0; i < to_copy; ++i) + self.items[i] = rhs.items[i]; + + if constexpr (Bits > Bits2) { - 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; + if constexpr (std::is_signed_v) + { + if (rhs < 0) + { + for (unsigned i = to_copy; i < item_count; ++i) + self.items[i] = -1; + return; + } + } + + for (unsigned i = to_copy; i < item_count; ++i) + self.items[i] = 0; } } template constexpr static bool should_keep_size() { - return sizeof(T) * CHAR_BIT <= Bits; + return sizeof(T) <= byte_count; } - constexpr static integer shift_left(const integer & rhs, int n) noexcept + constexpr static integer shift_left(const integer & rhs, unsigned n) noexcept { - if (static_cast(n) >= base_bits * arr_size) - return 0; - if (n <= 0) - return rhs; + integer lhs; + unsigned items_shift = n / base_bits; - integer lhs = rhs; - int bit_shift = n % base_bits; - unsigned n_bytes = n / base_bits; - if (bit_shift) + if (unsigned bit_shift = n % base_bits) { - lhs.m_arr[big(0)] <<= bit_shift; - for (int i = 1; i < arr_size; ++i) + unsigned overflow_shift = base_bits - bit_shift; + + lhs.items[big(0)] = rhs.items[big(items_shift)] << bit_shift; + for (unsigned i = 1; i < item_count - items_shift; ++i) { - lhs.m_arr[big(i - 1)] |= lhs.m_arr[big(i)] >> (base_bits - bit_shift); - lhs.m_arr[big(i)] <<= bit_shift; + lhs.items[big(i - 1)] |= rhs.items[big(items_shift + i)] >> overflow_shift; + lhs.items[big(i)] = rhs.items[big(items_shift + 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 integer shift_left(const integer & rhs, int n) noexcept - { - return integer(shift_left(integer(rhs), n)); - } - - constexpr static integer shift_right(const integer & rhs, int n) noexcept - { - if (static_cast(n) >= base_bits * arr_size) - return 0; - if (n <= 0) - return rhs; - - 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 integer shift_right(const 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(integer(rhs), n); - - integer lhs = rhs; - int bit_shift = n % base_bits; - unsigned n_bytes = n / base_bits; - if (bit_shift) - { - lhs = shift_right(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 integer - operator_plus_T(const integer & lhs, T rhs) noexcept(std::is_same_v) - { - if (rhs < 0) - return _operator_minus_T(lhs, -rhs); else - return _operator_plus_T(lhs, rhs); + { + for (unsigned i = 0; i < item_count - items_shift; ++i) + lhs.items[big(i)] = rhs.items[big(items_shift + i)]; + } + + for (unsigned i = 0; i < items_shift; ++i) + lhs.items[little(i)] = 0; + return lhs; + } + + constexpr static integer shift_right(const integer & rhs, unsigned n) noexcept + { + integer lhs; + unsigned items_shift = n / base_bits; + unsigned bit_shift = n % base_bits; + + if (bit_shift) + { + unsigned overflow_shift = base_bits - bit_shift; + + lhs.items[little(0)] = rhs.items[little(items_shift)] >> bit_shift; + for (unsigned i = 1; i < item_count - items_shift; ++i) + { + lhs.items[little(i - 1)] |= rhs.items[little(items_shift + i)] << overflow_shift; + lhs.items[little(i)] = rhs.items[little(items_shift + i)] >> bit_shift; + } + } + else + { + for (unsigned i = 0; i < item_count - items_shift; ++i) + lhs.items[little(i)] = rhs.items[little(items_shift + i)]; + } + + if (is_negative(rhs)) + { + if (bit_shift) + lhs.items[big(items_shift)] |= std::numeric_limits::max() << (base_bits - bit_shift); + + for (unsigned i = item_count - items_shift; i < items_shift; ++i) + lhs.items[little(i)] = std::numeric_limits::max(); + } + else + { + for (unsigned i = item_count - items_shift; i < items_shift; ++i) + lhs.items[little(i)] = 0; + } + + return lhs; } private: template - constexpr static integer - _operator_minus_T(const integer & lhs, T rhs) noexcept(std::is_same_v) + constexpr static base_type get_item(const T & x, unsigned number) { - integer res = lhs; + if constexpr (IsWideInteger::value) + { + if (number < T::_impl::item_count) + return x.items[number]; + return 0; + } + else + { + if (number * sizeof(base_type) < sizeof(T)) + return x >> (number * base_bits); // & std::numeric_limits::max() + return 0; + } + } + + template + constexpr static integer + op_minus(const integer & lhs, T rhs) + { + integer res; bool is_underflow = false; - int r_idx = 0; - for (; static_cast(r_idx) < sizeof(T) && r_idx < arr_size; ++r_idx) + for (unsigned i = 0; i < item_count; ++i) { - base_type & res_i = res.m_arr[little(r_idx)]; - base_type curr_rhs = (rhs >> (r_idx * CHAR_BIT)) & std::numeric_limits::max(); + base_type lhs_item = lhs.items[little(i)]; + base_type rhs_item = get_item(rhs, i); if (is_underflow) { - --res_i; - is_underflow = res_i == std::numeric_limits::max(); + is_underflow = (lhs_item == 0); + --lhs_item; } - if (res_i < curr_rhs) + if (lhs_item < rhs_item) 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; - } + res.items[little(i)] = lhs_item - rhs_item; } return res; @@ -405,37 +393,69 @@ private: template constexpr static integer - _operator_plus_T(const integer & lhs, T rhs) noexcept(std::is_same_v) + op_plus(const integer & lhs, T rhs) { - integer res = lhs; + integer res; bool is_overflow = false; - int r_idx = 0; - for (; static_cast(r_idx) < sizeof(T) && r_idx < arr_size; ++r_idx) + for (unsigned i = 0; i < item_count; ++i) { - base_type & res_i = res.m_arr[little(r_idx)]; - base_type curr_rhs = (rhs >> (r_idx * CHAR_BIT)) & std::numeric_limits::max(); + base_type lhs_item = lhs.items[little(i)]; + base_type rhs_item = get_item(rhs, i); if (is_overflow) { - ++res_i; - is_overflow = res_i == 0; + ++lhs_item; + is_overflow = (lhs_item == 0); } - res_i += curr_rhs; - if (res_i < curr_rhs) + base_type & res_item = res.items[little(i)]; + res_item = lhs_item + rhs_item; + + if (res_item < rhs_item) is_overflow = true; } - if (is_overflow && r_idx < arr_size) + return res; + } + + template + constexpr static auto op_multiply(const integer & lhs, const T & rhs) + { + integer res{}; +#if 1 + integer lhs2 = op_plus(lhs, shift_left(lhs, 1)); + integer lhs3 = op_plus(lhs2, shift_left(lhs, 2)); +#endif + for (unsigned i = 0; i < item_count; ++i) { - ++res.m_arr[little(r_idx)]; - for (int i = arr_size - 1 - r_idx - 1; i >= 0; --i) + base_type rhs_item = get_item(rhs, i); + unsigned pos = i * base_bits; + + while (rhs_item) { - if (res.m_arr[big(i + 1)] == 0) - ++res.m_arr[big(i)]; - else - break; +#if 1 /// optimization + if ((rhs_item & 0x7) == 0x7) + { + res = op_plus(res, shift_left(lhs3, pos)); + rhs_item >>= 3; + pos += 3; + continue; + } + + if ((rhs_item & 0x3) == 0x3) + { + res = op_plus(res, shift_left(lhs2, pos)); + rhs_item >>= 2; + pos += 2; + continue; + } +#endif + if (rhs_item & 1) + res = op_plus(res, shift_left(lhs, pos)); + + rhs_item >>= 1; + ++pos; } } @@ -445,17 +465,17 @@ private: public: constexpr static integer operator_unary_tilda(const integer & lhs) noexcept { - integer res{}; + integer res; - for (int i = 0; i < arr_size; ++i) - res.m_arr[any(i)] = ~lhs.m_arr[any(i)]; + for (unsigned i = 0; i < item_count; ++i) + res.items[any(i)] = ~lhs.items[any(i)]; return res; } constexpr static integer operator_unary_minus(const integer & lhs) noexcept(std::is_same_v) { - return operator_plus_T(operator_unary_tilda(lhs), 1); + return op_plus(operator_unary_tilda(lhs), 1); } template @@ -463,15 +483,14 @@ public: { if constexpr (should_keep_size()) { - integer t = rhs; - if (is_negative(t)) - return _operator_minus_wide_integer(lhs, operator_unary_minus(t)); + if (is_negative(rhs)) + return op_minus(lhs, -rhs); else - return _operator_plus_wide_integer(lhs, t); + return op_plus(lhs, rhs); } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, integer>::_impl::operator_plus( integer(lhs), rhs); } @@ -482,100 +501,44 @@ public: { if constexpr (should_keep_size()) { - integer t = rhs; - if (is_negative(t)) - return _operator_plus_wide_integer(lhs, operator_unary_minus(t)); + if (is_negative(rhs)) + return op_plus(lhs, -rhs); else - return _operator_minus_wide_integer(lhs, t); + return op_minus(lhs, rhs); } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, integer>::_impl::operator_minus( integer(lhs), rhs); } } -private: - constexpr static integer _operator_minus_wide_integer( - const integer & lhs, const integer & rhs) noexcept(std::is_same_v) - { - 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 integer _operator_plus_wide_integer( - const integer & lhs, const integer & rhs) noexcept(std::is_same_v) - { - 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 integer & lhs, const T & rhs) { if constexpr (should_keep_size()) { - const integer a = make_positive(lhs); - integer t = make_positive(integer(rhs)); + integer res; - integer res = 0; - - for (size_t i = 0; i < arr_size * base_bits; ++i) + if constexpr (std::is_signed_v) { - if (t.m_arr[little(0)] & 1) - res = operator_plus(res, shift_left(a, i)); - - t = shift_right(t, 1); + res = op_multiply((is_negative(lhs) ? make_positive(lhs) : lhs), + (is_negative(rhs) ? make_positive(rhs) : rhs)); + } + else + { + res = op_multiply(lhs, (is_negative(rhs) ? make_positive(rhs) : rhs)); } - if (std::is_same_v && is_negative(integer(rhs)) != is_negative(lhs)) + if (std::is_same_v && is_negative(lhs) != is_negative(rhs)) res = operator_unary_minus(res); return res; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, T>::_impl::operator_star(T(lhs), rhs); } } @@ -585,25 +548,22 @@ public: { if constexpr (should_keep_size()) { - // static_assert(Signed == std::is_signed::value, - // "warning: operator_more: comparison of integers of different signs"); + if (std::numeric_limits::is_signed && (is_negative(lhs) != is_negative(rhs))) + return is_negative(rhs); - 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) + for (unsigned i = 0; i < item_count; ++i) { - if (lhs.m_arr[big(i)] != t.m_arr[big(i)]) - return lhs.m_arr[big(i)] > t.m_arr[big(i)]; + base_type rhs_item = get_item(rhs, big(i)); + + if (lhs.items[big(i)] != rhs_item) + return lhs.items[big(i)] > rhs_item; } return false; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, T>::_impl::operator_more(T(lhs), rhs); } } @@ -613,23 +573,22 @@ public: { if constexpr (should_keep_size()) { - // static_assert(Signed == std::is_signed::value, - // "warning: operator_less: comparison of integers of different signs"); - - integer t = rhs; - - if (std::numeric_limits::is_signed && (is_negative(lhs) != is_negative(t))) + if (std::numeric_limits::is_signed && (is_negative(lhs) != is_negative(rhs))) 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)]; + for (unsigned i = 0; i < item_count; ++i) + { + base_type rhs_item = get_item(rhs, big(i)); + + if (lhs.items[big(i)] != rhs_item) + return lhs.items[big(i)] < rhs_item; + } return false; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, T>::_impl::operator_less(T(lhs), rhs); } } @@ -639,17 +598,19 @@ public: { if constexpr (should_keep_size()) { - integer t = rhs; + for (unsigned i = 0; i < item_count; ++i) + { + base_type rhs_item = get_item(rhs, any(i)); - for (int i = 0; i < arr_size; ++i) - if (lhs.m_arr[any(i)] != t.m_arr[any(i)]) + if (lhs.items[any(i)] != rhs_item) return false; + } return true; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, T>::_impl::operator_eq(T(lhs), rhs); } } @@ -659,16 +620,15 @@ public: { if constexpr (should_keep_size()) { - integer t = rhs; - integer res = lhs; + integer res; - for (int i = 0; i < arr_size; ++i) - res.m_arr[any(i)] |= t.m_arr[any(i)]; + for (unsigned i = 0; i < item_count; ++i) + res.items[little(i)] = lhs.items[little(i)] | get_item(rhs, i); return res; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, T>::_impl::operator_pipe(T(lhs), rhs); } } @@ -678,43 +638,48 @@ public: { if constexpr (should_keep_size()) { - integer t = rhs; - integer res = lhs; + integer res; - for (int i = 0; i < arr_size; ++i) - res.m_arr[any(i)] &= t.m_arr[any(i)]; + for (unsigned i = 0; i < item_count; ++i) + res.items[little(i)] = lhs.items[little(i)] & get_item(rhs, i); return res; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); 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) + constexpr static bool is_zero(const T & x) { bool is_zero = true; - for (auto c : denominator.m_arr) + for (auto item : x.items) { - if (c != 0) + if (item != 0) { is_zero = false; break; } } + return is_zero; + } - if (is_zero) + /// returns quotient as result and remainder in numerator. + template + constexpr static T divide(T & numerator, T && denominator) + { + if (is_zero(denominator)) throwError("divide by zero"); - T n = lhserator; - T d = denominator; + T & n = numerator; + T & d = denominator; T x = 1; - T answer = 0; + T quotient = 0; - while (!operator_more(d, n) && operator_eq(operator_amp(shift_right(d, base_bits * arr_size - 1), 1), 0)) + while (!operator_more(d, n) && operator_eq(operator_amp(shift_right(d, base_bits * item_count - 1), 1), 0)) { x = shift_left(x, 1); d = shift_left(d, 1); @@ -725,15 +690,14 @@ private: if (!operator_more(d, n)) { n = operator_minus(n, d); - answer = operator_pipe(answer, x); + quotient = operator_pipe(quotient, x); } x = shift_right(x, 1); d = shift_right(d, 1); } - quotient = answer; - remainder = n; + return quotient; } public: @@ -742,18 +706,16 @@ public: { if constexpr (should_keep_size()) { - integer o = rhs; - integer quotient{}, remainder{}; - divide(make_positive(lhs), make_positive(o), quotient, remainder); + integer numerator = make_positive(lhs); + integer quotient = divide(numerator, make_positive(integer(rhs))); - if (std::is_same_v && is_negative(o) != is_negative(lhs)) + if (std::is_same_v && is_negative(rhs) != is_negative(lhs)) quotient = operator_unary_minus(quotient); - return quotient; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, integer>::operator_slash(T(lhs), rhs); } } @@ -763,18 +725,16 @@ public: { if constexpr (should_keep_size()) { - integer o = rhs; - integer quotient{}, remainder{}; - divide(make_positive(lhs), make_positive(o), quotient, remainder); + integer remainder = make_positive(lhs); + divide(remainder, make_positive(integer(rhs))); if (std::is_same_v && is_negative(lhs)) remainder = operator_unary_minus(remainder); - return remainder; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return std::common_type_t, integer>::operator_percent(T(lhs), rhs); } } @@ -788,13 +748,13 @@ public: integer t(rhs); integer res = lhs; - for (int i = 0; i < arr_size; ++i) - res.m_arr[any(i)] ^= t.m_arr[any(i)]; + for (unsigned i = 0; i < item_count; ++i) + res.items[any(i)] ^= t.items[any(i)]; return res; } else { - static_assert(T::_impl::_is_wide_integer, ""); + static_assert(IsWideInteger::value); return T::operator_circumflex(T(lhs), rhs); } } @@ -815,20 +775,20 @@ public: { if (*c >= '0' && *c <= '9') { - res = operator_star(res, 16U); - res = operator_plus_T(res, *c - '0'); + res = op_multiply(res, 16U); + res = op_plus(res, *c - '0'); ++c; } else if (*c >= 'a' && *c <= 'f') { - res = operator_star(res, 16U); - res = operator_plus_T(res, *c - 'a' + 10U); + res = op_multiply(res, 16U); + res = op_plus(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); + res = op_multiply(res, 16U); + res = op_plus(res, *c - 'A' + 10U); ++c; } else @@ -842,8 +802,8 @@ public: if (*c < '0' || *c > '9') throwError("invalid char from"); - res = operator_star(res, 10U); - res = operator_plus_T(res, *c - '0'); + res = op_multiply(res, 10U); + res = op_plus(res, *c - '0'); ++c; } } @@ -860,7 +820,7 @@ public: template template constexpr integer::integer(T rhs) noexcept - : m_arr{} + : items{} { if constexpr (IsWideInteger::value) _impl::wide_integer_from_wide_integer(*this, rhs); @@ -871,7 +831,7 @@ constexpr integer::integer(T rhs) noexcept template template constexpr integer::integer(std::initializer_list il) noexcept - : m_arr{} + : items{} { if (il.size() == 1) { @@ -967,14 +927,25 @@ constexpr integer & integer::operator^=(const T & rh template constexpr integer & integer::operator<<=(int n) noexcept { - *this = _impl::shift_left(*this, n); + if (static_cast(n) >= Bits) + *this = 0; + else if (n > 0) + *this = _impl::shift_left(*this, n); return *this; } template constexpr integer & integer::operator>>=(int n) noexcept { - *this = _impl::shift_right(*this, n); + if (static_cast(n) >= Bits) + { + if (is_negative(*this)) + *this = -1; + else + *this = 0; + } + else if (n > 0) + *this = _impl::shift_right(*this, n); return *this; } @@ -1018,13 +989,16 @@ template template constexpr 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) + if constexpr (std::is_same_v) { - res |= (T(m_arr[_impl::little(r_idx)]) << (_impl::base_bits * r_idx)); + static_assert(Bits >= 128); + return (__int128(items[1]) << 64) | items[0]; + } + else + { + static_assert(std::numeric_limits::is_integer); + return items[0]; } - return res; } template @@ -1038,12 +1012,12 @@ constexpr integer::operator long double() const noexcept tmp = -tmp; long double res = 0; - for (size_t idx = 0; idx < _impl::arr_size; ++idx) + for (unsigned i = 0; i < _impl::item_count; ++i) { long double t = res; res *= std::numeric_limits::max(); res += t; - res += tmp.m_arr[_impl::big(idx)]; + res += tmp.items[_impl::big(i)]; } if (_impl::is_negative(*this)) @@ -1187,11 +1161,19 @@ std::common_type_t constexpr operator^(const Integral & lhs template constexpr integer operator<<(const integer & lhs, int n) noexcept { + if (static_cast(n) >= Bits) + return 0; + if (n <= 0) + return lhs; return integer::_impl::shift_left(lhs, n); } template constexpr integer operator>>(const integer & lhs, int n) noexcept { + if (static_cast(n) >= Bits) + return 0; + if (n <= 0) + return lhs; return integer::_impl::shift_right(lhs, n); } @@ -1277,7 +1259,7 @@ struct hash> { static_assert(Bits % (sizeof(size_t) * 8) == 0); - const auto * ptr = reinterpret_cast(lhs.m_arr); + const auto * ptr = reinterpret_cast(lhs.items); unsigned count = Bits / (sizeof(size_t) * 8); size_t res = 0; diff --git a/tests/queries/0_stateless/01440_big_int_exotic_casts.reference b/tests/queries/0_stateless/01440_big_int_exotic_casts.reference new file mode 100644 index 00000000000..fb3cdce7ad9 --- /dev/null +++ b/tests/queries/0_stateless/01440_big_int_exotic_casts.reference @@ -0,0 +1,292 @@ +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +1 1.0 1.00 1.000000 1.0000000 +8 8.0 8.00 8.000000 8.0000000 +27 27.0 27.00 27.000000 27.0000000 +64 64.0 64.00 64.000000 64.0000000 +125 125.0 125.00 125.000000 125.0000000 +216 216.0 216.00 216.000000 216.0000000 +343 343.0 343.00 343.000000 343.0000000 +512 512.0 512.00 512.000000 512.0000000 +729 729.0 729.00 729.000000 729.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +-0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +-0 0.0 0.00 0.000000 0.0000000 +-1 -1.0 -1.00 -1.000000 -1.0000000 +-4 -4.0 -4.00 -4.000000 -4.0000000 +-9 -9.0 -9.00 -9.000000 -9.0000000 +-16 -16.0 -16.00 -16.000000 -16.0000000 +-25 -25.0 -25.00 -25.000000 -25.0000000 +-36 -36.0 -36.00 -36.000000 -36.0000000 +-49 -49.0 -49.00 -49.000000 -49.0000000 +-64 -64.0 -64.00 -64.000000 -64.0000000 +-81 -81.0 -81.00 -81.000000 -81.0000000 +0 0 0 0 +4294967295 4294967295 4294967295 4294967295 +8589934588 8589934588 8589934588 8589934588 +12884901879 12884901879 12884901879 12884901879 +17179869168 17179869168 17179869168 17179869168 +21474836455 21474836455 21474836455 21474836455 +25769803740 25769803740 25769803740 25769803740 +30064771023 30064771023 30064771023 30064771023 +34359738304 34359738304 34359738304 34359738304 +38654705583 38654705583 38654705583 38654705583 +0 0 0 0 +18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551615 +18446744073709551612 18446744073709551612 18446744073709551612 18446744073709551612 +18446744073709551607 18446744073709551607 18446744073709551607 18446744073709551607 +18446744073709551600 18446744073709551600 18446744073709551600 18446744073709551600 +18446744073709551591 18446744073709551591 18446744073709551591 18446744073709551591 +18446744073709551580 18446744073709551580 18446744073709551580 18446744073709551580 +18446744073709551567 18446744073709551567 18446744073709551567 18446744073709551567 +18446744073709551552 18446744073709551552 18446744073709551552 18446744073709551552 +18446744073709551535 18446744073709551535 18446744073709551535 18446744073709551535 +0 0 0 0 +115792089237316195423570985008687907853269984665640564039457584007913129639935 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +115792089237316195423570985008687907853269984665640564039457584007913129639932 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +115792089237316195423570985008687907853269984665640564039457584007913129639927 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +115792089237316195423570985008687907853269984665640564039457584007913129639920 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +115792089237316195423570985008687907853269984665640564039457584007913129639911 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +115792089237316195423570985008687907853269984665640564039457584007913129639900 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +115792089237316195423570985008687907853269984665640564039457584007913129639887 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +115792089237316195423570985008687907853269984665640564039457584007913129639872 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +115792089237316195423570985008687907853269984665640564039457584007913129639855 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +-1 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +-4 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +-9 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +-16 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +-25 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +-36 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +-49 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +-64 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +-81 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +-1 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +-4 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +-9 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +-16 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +-25 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +-36 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +-49 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +-64 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +-81 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +-1 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +-4 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +-9 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +-16 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +-25 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +-36 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +-49 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +-64 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +-81 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +-1 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +-4 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +-9 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +-16 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +-25 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +-36 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +-49 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +-64 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +-81 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +-1 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +-4 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +-9 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +-16 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +-25 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +-36 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +-49 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +-64 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +-81 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +-1 -1 -1 115792089237316195423570985008687907853269984665640564039457584007913129639935 +-4 -4 -4 115792089237316195423570985008687907853269984665640564039457584007913129639932 +-9 -9 -9 115792089237316195423570985008687907853269984665640564039457584007913129639927 +-16 -16 -16 115792089237316195423570985008687907853269984665640564039457584007913129639920 +-25 -25 -25 115792089237316195423570985008687907853269984665640564039457584007913129639911 +-36 -36 -36 115792089237316195423570985008687907853269984665640564039457584007913129639900 +-49 -49 -49 115792089237316195423570985008687907853269984665640564039457584007913129639887 +-64 -64 -64 115792089237316195423570985008687907853269984665640564039457584007913129639872 +-81 -81 -81 115792089237316195423570985008687907853269984665640564039457584007913129639855 +0 0 0 0 +1 0 0 0 +2 0 0 0 +3 0 0 0 +4 0 0 0 +5 0 0 0 +6 0 0 0 +7 0 0 0 +8 0 0 0 +9 0 0 0 +0 0 0 0 +-1 0 0 0 +-2 0 0 0 +-3 0 0 0 +-4 0 0 0 +-5 0 0 0 +-6 0 0 0 +-7 0 0 0 +-8 0 0 0 +-9 0 0 0 +2499500025000000 2499500025000000 2499500025000000 2499500025000000.00 +0 0 0 0.00 diff --git a/tests/queries/0_stateless/01440_big_int_exotic_casts.sql b/tests/queries/0_stateless/01440_big_int_exotic_casts.sql new file mode 100644 index 00000000000..42fde9da01b --- /dev/null +++ b/tests/queries/0_stateless/01440_big_int_exotic_casts.sql @@ -0,0 +1,48 @@ +SELECT toUInt32(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toUInt64(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toUInt256(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt32(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt64(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt128(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt256(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toFloat32(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toFloat64(number * number) * number y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; + +SELECT toUInt32(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toUInt64(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toUInt256(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt32(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt64(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt128(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toInt256(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toFloat32(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; +SELECT toFloat64(number * number) * -1 y, toDecimal32(y, 1), toDecimal64(y, 2), toDecimal128(y, 6), toDecimal256(y, 7) FROM numbers_mt(10) ORDER BY number; + +SELECT toUInt32(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toUInt64(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toUInt256(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toInt32(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toInt64(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toInt128(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toInt256(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toFloat32(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; +SELECT toFloat64(number * -1) * number y, toInt128(y), toInt256(y), toUInt256(y) FROM numbers_mt(10) ORDER BY number; + +SELECT number y, toInt128(number) - y, toInt256(number) - y, toUInt256(number) - y FROM numbers_mt(10) ORDER BY number; +SELECT -number y, toInt128(number) + y, toInt256(number) + y, toUInt256(number) + y FROM numbers_mt(10) ORDER BY number; + + +SET allow_experimental_bigint_types = 1; + +DROP TABLE IF EXISTS t; +CREATE TABLE t (x UInt64, i256 Int256, u256 UInt256, d256 Decimal256(2)) ENGINE = Memory; + +INSERT INTO t SELECT number * number * number AS x, x AS i256, x AS u256, x AS d256 FROM numbers(10000); + +SELECT sum(x), sum(i256), sum(u256), sum(d256) FROM t; + +INSERT INTO t SELECT -number * number * number AS x, x AS i256, x AS u256, x AS d256 FROM numbers(10000); + +SELECT sum(x), sum(i256), sum(u256), sum(d256) FROM t; + +DROP TABLE t;