Attempt to normalize big integers

This commit is contained in:
Alexey Milovidov 2021-04-25 12:30:43 +03:00
parent 60be962dca
commit 649550c5ab
44 changed files with 414 additions and 560 deletions

View File

@ -0,0 +1,199 @@
#pragma once
#include <cstdint>
#include <cstring>
#include <common/extended_types.h>
/// Allows to check the internals of IEEE-754 floating point number.
template <typename T> struct FloatTraits;
template <>
struct FloatTraits<float>
{
using UInt = uint32_t;
static constexpr size_t bits = 32;
static constexpr size_t exponent_bits = 8;
static constexpr size_t mantissa_bits = bits - exponent_bits - 1;
};
template <>
struct FloatTraits<double>
{
using UInt = uint64_t;
static constexpr size_t bits = 64;
static constexpr size_t exponent_bits = 11;
static constexpr size_t mantissa_bits = bits - exponent_bits - 1;
};
/// x = sign * (2 ^ normalized_exponent) * (1 + mantissa * 2 ^ -mantissa_bits)
/// x = sign * (2 ^ normalized_exponent + mantissa * 2 ^ (normalized_exponent - mantissa_bits))
template <typename T>
struct DecomposedFloat
{
using Traits = FloatTraits<T>;
DecomposedFloat(T x)
{
memcpy(&x_uint, &x, sizeof(x));
}
typename Traits::UInt x_uint;
bool sign() const
{
return x_uint >> (Traits::bits - 1);
}
uint16_t exponent() const
{
return (x_uint >> (Traits::mantissa_bits)) & (((1ull << (Traits::exponent_bits + 1)) - 1) >> 1);
}
int16_t normalized_exponent() const
{
return int16_t(exponent()) - ((1ull << (Traits::exponent_bits - 1)) - 1);
}
uint64_t mantissa() const
{
return x_uint & ((1ull << Traits::mantissa_bits) - 1);
}
int64_t mantissa_with_sign() const
{
return sign() ? -mantissa() : mantissa();
}
/// NOTE Probably floating point instructions can be better.
bool is_integer_in_representable_range() const
{
return x_uint == 0
|| (normalized_exponent() >= 0 /// The number is not less than one
/// The number is inside the range where every integer has exact representation in float
&& normalized_exponent() <= static_cast<int16_t>(Traits::mantissa_bits)
/// After multiplying by 2^exp, the fractional part becomes zero, means the number is integer
&& ((mantissa() & ((1ULL << (Traits::mantissa_bits - normalized_exponent())) - 1)) == 0));
}
template <typename Int>
bool equals(Int rhs)
{
/// Different signs
if ((rhs < 0) != sign())
return false;
if (rhs == 0 && x_uint == 0)
return true;
/// Fractional number
if (normalized_exponent() < 0)
return false;
/// Too large number
if (normalized_exponent() >= static_cast<int16_t>(8 * sizeof(Int) + is_signed_v<Int>))
return false;
using UInt = make_unsigned_t<Int>;
UInt uint_rhs = rhs < 0 ? -rhs : rhs;
/// Smaller octave
if (uint_rhs < (static_cast<UInt>(1) << normalized_exponent()))
return false;
/// Larger octave
if (normalized_exponent() + 1 < static_cast<int16_t>(8 * sizeof(Int) + is_signed_v<Int>)
&& uint_rhs >= (static_cast<UInt>(1) << (normalized_exponent() + 1)))
return false;
/// The same octave
/// uint_rhs == 2 ^ normalized_exponent + mantissa * 2 ^ (normalized_exponent - mantissa_bits)
/// After multiplying by 2^exp, the fractional part becomes zero, means the number is integer
if ((mantissa() & ((1ULL << (Traits::mantissa_bits - normalized_exponent())) - 1)) != 0)
return false;
/// uint_rhs - 2 ^ normalized_exponent == mantissa * 2 ^ (normalized_exponent - mantissa_bits)
return uint_rhs - (static_cast<UInt>(1) << normalized_exponent()) == (mantissa() >> (Traits::mantissa_bits - normalized_exponent()));
}
template <typename Int>
bool less(Int rhs)
{
/// Different signs
if (sign() && rhs >= 0)
return true;
if (!sign() && rhs < 0)
return false;
if (rhs == 0)
return sign();
/// Fractional number
if (normalized_exponent() < 0)
{
if (!sign())
return rhs > 0;
else
return rhs >= 0;
}
/// Too large number
if (normalized_exponent() >= static_cast<int16_t>(8 * sizeof(Int) + is_signed_v<Int>))
return sign();
using UInt = make_unsigned_t<Int>;
UInt uint_rhs = rhs < 0 ? -rhs : rhs;
/// Smaller octave
if (uint_rhs < (static_cast<UInt>(1) << normalized_exponent()))
return !sign();
/// Larger octave
if (normalized_exponent() + 1 < static_cast<int16_t>(8 * sizeof(Int) + is_signed_v<Int>)
&& uint_rhs >= (static_cast<UInt>(1) << (normalized_exponent() + 1)))
return sign();
/// The same octave
/// uint_rhs == 2 ^ normalized_exponent + mantissa * 2 ^ (normalized_exponent - mantissa_bits)
typename Traits::UInt a = mantissa() >> (Traits::mantissa_bits - normalized_exponent());
typename Traits::UInt b = uint_rhs - (static_cast<UInt>(1) << normalized_exponent());
if (a < b)
return !sign();
if (a > b)
return sign();
if ((mantissa() & ((1ULL << (Traits::mantissa_bits - normalized_exponent())) - 1)) == 0)
return !sign();
else
return sign();
}
template <typename Int>
bool greaterOrEquals(Int rhs)
{
return !less(rhs);
}
template <typename Int>
bool lessOrEquals(Int rhs)
{
return less(rhs) || equals(rhs);
}
template <typename Int>
bool greater(Int rhs)
{
return !lessOrEquals(rhs);
}
};
using DecomposedFloat64 = DecomposedFloat<double>;
using DecomposedFloat32 = DecomposedFloat<float>;

View File

@ -56,12 +56,18 @@ namespace common
}
template <>
inline bool addOverflow(__int128 x, __int128 y, __int128 & res)
inline bool addOverflow(Int128 x, Int128 y, Int128 & res)
{
static constexpr __int128 min_int128 = minInt128();
static constexpr __int128 max_int128 = maxInt128();
res = addIgnoreOverflow(x, y);
return (y > 0 && x > max_int128 - y) || (y < 0 && x < min_int128 - y);
return (y > 0 && x > std::numeric_limits<Int128>::max() - y) ||
(y < 0 && x < std::numeric_limits<Int128>::min() - y);
}
template <>
inline bool addOverflow(UInt128 x, UInt128 y, UInt128 & res)
{
res = addIgnoreOverflow(x, y);
return x > std::numeric_limits<UInt128>::max() - y;
}
template <>
@ -104,12 +110,18 @@ namespace common
}
template <>
inline bool subOverflow(__int128 x, __int128 y, __int128 & res)
inline bool subOverflow(Int128 x, Int128 y, Int128 & res)
{
static constexpr __int128 min_int128 = minInt128();
static constexpr __int128 max_int128 = maxInt128();
res = subIgnoreOverflow(x, y);
return (y < 0 && x > max_int128 + y) || (y > 0 && x < min_int128 + y);
return (y < 0 && x > std::numeric_limits<Int128>::max() + y) ||
(y > 0 && x < std::numeric_limits<Int128>::min() + y);
}
template <>
inline bool subOverflow(UInt128 x, UInt128 y, UInt128 & res)
{
res = subIgnoreOverflow(x, y);
return x < y;
}
template <>

View File

@ -433,7 +433,7 @@ private:
for (unsigned i = 1; i < item_count; ++i)
{
if (underflows[i-1])
if (underflows[i - 1])
{
base_type & res_item = res.items[little(i)];
if (res_item == 0)
@ -466,7 +466,7 @@ private:
for (unsigned i = 1; i < item_count; ++i)
{
if (overflows[i-1])
if (overflows[i - 1])
{
base_type & res_item = res.items[little(i)];
++res_item;

View File

@ -40,10 +40,10 @@ public:
return l == r;
if constexpr (isDecimalField<T>() && std::is_arithmetic_v<U>)
return accurate::equalsOp(l.getValue(), r);
return l == DecimalField<Decimal256>(Decimal256(r), 0);
if constexpr (std::is_arithmetic_v<T> && isDecimalField<U>())
return accurate::equalsOp(l, r.getValue());
return DecimalField<Decimal256>(Decimal256(l), 0) == r;
if constexpr (std::is_same_v<T, String> && std::is_arithmetic_v<U>)
{
@ -94,10 +94,10 @@ public:
return l < r;
if constexpr (isDecimalField<T>() && std::is_arithmetic_v<U>)
return accurate::lessOp(l.getValue(), r);
return l < DecimalField<Decimal256>(Decimal256(r), 0);
if constexpr (std::is_arithmetic_v<T> && isDecimalField<U>())
return accurate::lessOp(l, r.getValue());
return DecimalField<Decimal256>(Decimal256(l), 0) < r;
if constexpr (std::is_same_v<T, String> && std::is_arithmetic_v<U>)
{

View File

@ -180,6 +180,28 @@ inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) <= sizeof(UInt64)), T> k
}
template <typename T>
inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> key)
{
if constexpr (is_big_int_v<T> && sizeof(T) == 16)
{
/// TODO This is classical antipattern.
return intHash64(
static_cast<UInt64>(key) ^
static_cast<UInt64>(key >> 64));
}
else if constexpr (is_big_int_v<T> && sizeof(T) == 32)
{
return intHash64(
static_cast<UInt64>(key) ^
static_cast<UInt64>(key >> 64) ^
static_cast<UInt64>(key >> 128) ^
static_cast<UInt64>(key >> 256));
}
__builtin_unreachable();
}
template <typename T, typename Enable = void>
struct DefaultHash;
@ -197,7 +219,7 @@ struct DefaultHash<T, std::enable_if_t<DB::IsDecimalNumber<T>>>
{
size_t operator() (T key) const
{
return DefaultHash64<typename T::NativeType>(key);
return DefaultHash64<typename T::NativeType>(key.value);
}
};
@ -322,28 +344,6 @@ template <>
struct DefaultHash<DB::UInt256> : public UInt256Hash {};
template <typename T>
inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> key)
{
if constexpr (std::is_same_v<T, DB::Int128>)
{
return intHash64(static_cast<UInt64>(key) ^ static_cast<UInt64>(key >> 64));
}
if constexpr (std::is_same_v<T, DB::UInt128>)
{
return intHash64(key.low ^ key.high); /// TODO This is classical antipattern.
}
else if constexpr (is_big_int_v<T> && sizeof(T) == 32)
{
return intHash64(static_cast<UInt64>(key) ^
static_cast<UInt64>(key >> 64) ^
static_cast<UInt64>(key >> 128) ^
static_cast<UInt64>(key >> 256));
}
__builtin_unreachable();
}
/// It is reasonable to use for UInt8, UInt16 with sufficient hash table size.
struct TrivialHash
{

View File

@ -1093,7 +1093,7 @@ INSTANTIATE_TEST_SUITE_P(RandomishFloat,
);
// Double delta overflow case, deltas are out of bounds for target type
INSTANTIATE_TEST_SUITE_P(OverfloInt,
INSTANTIATE_TEST_SUITE_P(OverflowInt,
CodecTest,
::testing::Combine(
::testing::Values(

View File

@ -2,8 +2,9 @@
#include <cmath>
#include <limits>
#include "Defines.h"
#include "Types.h"
#include <common/DecomposedFloat.h>
#include <Core/Defines.h>
#include <Core/Types.h>
#include <common/extended_types.h>
#include <Common/NaNUtils.h>
@ -16,403 +17,124 @@ namespace accurate
using namespace DB;
/** Cases:
1) Safe conversion (in case of default C++ operators)
a) int vs any int
b) uint vs any uint
c) float vs any float
2) int vs uint
a) sizeof(int) <= sizeof(uint). Accurate comparison with MAX_INT tresholds
b) sizeof(int) > sizeof(uint). Casting to int
3) integral_type vs floating_type
a) sizeof(integral_type) <= 4. Comparison via casting arguments to Float64
b) sizeof(integral_type) == 8. Accurate comparison. Consider 3 sets of intervals:
1) interval between adjacent floats less or equal 1
2) interval between adjacent floats greater then 2
3) float is outside [MIN_INT64; MAX_INT64]
*/
// Case 1. Is pair of floats or pair of ints or pair of uints
template <typename A, typename B>
constexpr bool is_safe_conversion = (std::is_floating_point_v<A> && std::is_floating_point_v<B>)
|| (is_integer_v<A> && is_integer_v<B> && !(is_signed_v<A> ^ is_signed_v<B>));
bool lessOp(A a, B b)
{
/// float vs float
if constexpr (std::is_floating_point_v<A> && std::is_floating_point_v<B>)
return a < b;
/// anything vs NaN
if constexpr (std::is_floating_point_v<A> || std::is_floating_point_v<B>)
if (isNaN(a) || isNaN(b))
return false;
/// int vs int
if constexpr (is_integer_v<A> && is_integer_v<B>)
{
/// same signedness
if constexpr (is_signed_v<A> == is_signed_v<B>)
return a < b;
/// different signedness
if constexpr (is_signed_v<A> && !is_signed_v<B>)
return a < 0 || static_cast<B>(a) < b;
if constexpr (!is_signed_v<A> && is_signed_v<B>)
return b >= 0 && a < static_cast<A>(b);
}
/// int vs float
if constexpr (is_integer_v<A> && std::is_floating_point_v<B>)
{
if constexpr (sizeof(A) <= 4)
return static_cast<double>(a) < static_cast<double>(b);
return DecomposedFloat<B>(b).greater(a);
}
if constexpr (std::is_floating_point_v<A> && is_integer_v<B>)
{
if constexpr (sizeof(B) <= 4)
return static_cast<double>(a) < static_cast<double>(b);
return DecomposedFloat<A>(a).less(b);
}
}
template <typename A, typename B>
using bool_if_safe_conversion = std::enable_if_t<is_safe_conversion<A, B>, bool>;
bool greaterOp(A a, B b)
{
return lessOp(b, a);
}
template <typename A, typename B>
using bool_if_not_safe_conversion = std::enable_if_t<!is_safe_conversion<A, B>, bool>;
/// Case 2. Are params IntXX and UIntYY ?
template <typename TInt, typename TUInt>
constexpr bool is_any_int_vs_uint
= is_integer_v<TInt> && is_integer_v<TUInt> && is_signed_v<TInt> && is_unsigned_v<TUInt>;
// Case 2a. Are params IntXX and UIntYY and sizeof(IntXX) <= sizeof(UIntYY) (in such case will use accurate compare)
template <typename TInt, typename TUInt>
constexpr bool is_le_int_vs_uint = is_any_int_vs_uint<TInt, TUInt> && (sizeof(TInt) <= sizeof(TUInt));
static_assert(is_le_int_vs_uint<Int128, UInt128>);
static_assert(is_le_int_vs_uint<Int128, UInt256>);
template <typename TInt, typename TUInt>
using bool_if_le_int_vs_uint_t = std::enable_if_t<is_le_int_vs_uint<TInt, TUInt>, bool>;
template <typename TInt, typename TUInt>
inline bool_if_le_int_vs_uint_t<TInt, TUInt> greaterOpTmpl(TInt a, TUInt b)
bool greaterOrEqualsOp(A a, B b)
{
return static_cast<TUInt>(a) > b && a >= 0 && b <= static_cast<TUInt>(std::numeric_limits<TInt>::max());
return !lessOp(a, b);
}
template <typename TUInt, typename TInt>
inline bool_if_le_int_vs_uint_t<TInt, TUInt> greaterOpTmpl(TUInt a, TInt b)
template <typename A, typename B>
bool lessOrEqualsOp(A a, B b)
{
return a > static_cast<TUInt>(b) || b < 0 || a > static_cast<TUInt>(std::numeric_limits<TInt>::max());
return !lessOp(b, a);
}
template <typename TInt, typename TUInt>
inline bool_if_le_int_vs_uint_t<TInt, TUInt> equalsOpTmpl(TInt a, TUInt b)
template <typename A, typename B>
bool equalsOp(A a, B b)
{
return static_cast<TUInt>(a) == b && a >= 0 && b <= static_cast<TUInt>(std::numeric_limits<TInt>::max());
}
/// float vs float
if constexpr (std::is_floating_point_v<A> && std::is_floating_point_v<B>)
return a == b;
template <typename TUInt, typename TInt>
inline bool_if_le_int_vs_uint_t<TInt, TUInt> equalsOpTmpl(TUInt a, TInt b)
{
return a == static_cast<TUInt>(b) && b >= 0 && a <= static_cast<TUInt>(std::numeric_limits<TInt>::max());
}
/// anything vs NaN
if constexpr (std::is_floating_point_v<A> || std::is_floating_point_v<B>)
if (isNaN(a) || isNaN(b))
return false;
/// int vs int
if constexpr (is_integer_v<A> && is_integer_v<B>)
{
/// same signedness
if constexpr (is_signed_v<A> == is_signed_v<B>)
return a == b;
// Case 2b. Are params IntXX and UIntYY and sizeof(IntXX) > sizeof(UIntYY) (in such case will cast UIntYY to IntXX and compare)
template <typename TInt, typename TUInt>
constexpr bool is_gt_int_vs_uint = is_any_int_vs_uint<TInt, TUInt> && (sizeof(TInt) > sizeof(TUInt));
/// different signedness
template <typename TInt, typename TUInt>
using bool_if_gt_int_vs_uint = std::enable_if_t<is_gt_int_vs_uint<TInt, TUInt>, bool>;
if constexpr (is_signed_v<A> && !is_signed_v<B>)
return a >= 0 && static_cast<B>(a) == b;
template <typename TInt, typename TUInt>
inline bool_if_gt_int_vs_uint<TInt, TUInt> greaterOpTmpl(TInt a, TUInt b)
{
return static_cast<TInt>(a) > static_cast<TInt>(b);
}
if constexpr (!is_signed_v<A> && is_signed_v<B>)
return b >= 0 && a == static_cast<A>(b);
}
template <typename TInt, typename TUInt>
inline bool_if_gt_int_vs_uint<TInt, TUInt> greaterOpTmpl(TUInt a, TInt b)
{
return static_cast<TInt>(a) > static_cast<TInt>(b);
}
template <typename TInt, typename TUInt>
inline bool_if_gt_int_vs_uint<TInt, TUInt> equalsOpTmpl(TInt a, TUInt b)
{
return static_cast<TInt>(a) == static_cast<TInt>(b);
}
template <typename TInt, typename TUInt>
inline bool_if_gt_int_vs_uint<TInt, TUInt> equalsOpTmpl(TUInt a, TInt b)
{
return static_cast<TInt>(a) == static_cast<TInt>(b);
}
// Case 3a. Comparison via conversion to double.
template <typename TAInt, typename TAFloat>
using bool_if_double_can_be_used
= std::enable_if_t<is_integer_v<TAInt> && (sizeof(TAInt) <= 4) && std::is_floating_point_v<TAFloat>, bool>;
template <typename TAInt, typename TAFloat>
inline bool_if_double_can_be_used<TAInt, TAFloat> greaterOpTmpl(TAInt a, TAFloat b)
{
return static_cast<double>(a) > static_cast<double>(b);
}
template <typename TAInt, typename TAFloat>
inline bool_if_double_can_be_used<TAInt, TAFloat> greaterOpTmpl(TAFloat a, TAInt b)
{
return static_cast<double>(a) > static_cast<double>(b);
}
template <typename TAInt, typename TAFloat>
inline bool_if_double_can_be_used<TAInt, TAFloat> equalsOpTmpl(TAInt a, TAFloat b)
{
/// int vs float
if constexpr (is_integer_v<A> && std::is_floating_point_v<B>)
{
if constexpr (sizeof(A) <= 4)
return static_cast<double>(a) == static_cast<double>(b);
}
template <typename TAInt, typename TAFloat>
inline bool_if_double_can_be_used<TAInt, TAFloat> equalsOpTmpl(TAFloat a, TAInt b)
{
return DecomposedFloat<B>(b).equals(a);
}
if constexpr (std::is_floating_point_v<A> && is_integer_v<B>)
{
if constexpr (sizeof(B) <= 4)
return static_cast<double>(a) == static_cast<double>(b);
}
// Big integers vs Float (not equal in any case for now, until big floats are introduced?)
template <typename TABigInt, typename TAFloat>
constexpr bool if_big_int_vs_float = (is_big_int_v<TABigInt> && std::is_floating_point_v<TAFloat>);
template <typename TABigInt, typename TAFloat>
using bool_if_big_int_vs_float = std::enable_if_t<if_big_int_vs_float<TABigInt, TAFloat>, bool>;
template <typename TABigInt, typename TAFloat>
inline bool_if_big_int_vs_float<TABigInt, TAFloat> greaterOpTmpl(TAFloat, TABigInt)
{
return false;
}
template <typename TABigInt, typename TAFloat>
inline bool_if_big_int_vs_float<TABigInt, TAFloat> greaterOpTmpl(TABigInt, TAFloat)
{
return false;
}
template <typename TABigInt, typename TAFloat>
inline bool_if_big_int_vs_float<TABigInt, TAFloat> equalsOpTmpl(TAFloat, TABigInt)
{
return false;
}
template <typename TABigInt, typename TAFloat>
inline bool_if_big_int_vs_float<TABigInt, TAFloat> equalsOpTmpl(TABigInt, TAFloat)
{
return false;
}
/* Final implementations */
template <typename A, typename B>
inline bool greaterOp(A a, B b)
{
return greaterOpTmpl(a, b);
}
// Case 3b. 64-bit integers vs floats comparison.
// See hint at https://github.com/JuliaLang/julia/issues/257 (but it doesn't work properly for -2**63)
constexpr Int64 MAX_INT64_WITH_EXACT_FLOAT64_REPR = 9007199254740992LL; // 2^53
template <>
inline bool greaterOp<Float64, Int64>(Float64 f, Int64 i)
{
if (-MAX_INT64_WITH_EXACT_FLOAT64_REPR <= i && i <= MAX_INT64_WITH_EXACT_FLOAT64_REPR)
return f > static_cast<Float64>(i);
return (f >= static_cast<Float64>(std::numeric_limits<Int64>::max())) // rhs is 2**63 (not 2^63 - 1)
|| (f > static_cast<Float64>(std::numeric_limits<Int64>::min()) && static_cast<Int64>(f) > i);
}
template <>
inline bool greaterOp<Int64, Float64>(Int64 i, Float64 f)
{
if (-MAX_INT64_WITH_EXACT_FLOAT64_REPR <= i && i <= MAX_INT64_WITH_EXACT_FLOAT64_REPR)
return f < static_cast<Float64>(i);
return (f < static_cast<Float64>(std::numeric_limits<Int64>::min()))
|| (f < static_cast<Float64>(std::numeric_limits<Int64>::max()) && i > static_cast<Int64>(f));
}
template <>
inline bool greaterOp<Float64, UInt64>(Float64 f, UInt64 u)
{
if (u <= static_cast<UInt64>(MAX_INT64_WITH_EXACT_FLOAT64_REPR))
return f > static_cast<Float64>(u);
return (f >= static_cast<Float64>(std::numeric_limits<UInt64>::max()))
|| (f >= 0 && static_cast<UInt64>(f) > u);
}
template <>
inline bool greaterOp<UInt64, Float64>(UInt64 u, Float64 f)
{
if (u <= static_cast<UInt64>(MAX_INT64_WITH_EXACT_FLOAT64_REPR))
return static_cast<Float64>(u) > f;
return (f < 0)
|| (f < static_cast<Float64>(std::numeric_limits<UInt64>::max()) && u > static_cast<UInt64>(f));
}
// Case 3b for float32
template <> inline bool greaterOp<Float32, Int64>(Float32 f, Int64 i) { return greaterOp(static_cast<Float64>(f), i); }
template <> inline bool greaterOp<Float32, Int128>(Float32 f, Int128 i) { return greaterOp(static_cast<Float64>(f), i); }
template <> inline bool greaterOp<Float32, Int256>(Float32 f, Int256 i) { return greaterOp(static_cast<Float64>(f), i); }
template <> inline bool greaterOp<Float32, UInt64>(Float32 f, UInt64 i) { return greaterOp(static_cast<Float64>(f), i); }
template <> inline bool greaterOp<Float32, UInt128>(Float32 f, UInt128 i) { return greaterOp(static_cast<Float64>(f), i); }
template <> inline bool greaterOp<Float32, UInt256>(Float32 f, UInt256 i) { return greaterOp(static_cast<Float64>(f), i); }
template <> inline bool greaterOp<Int64, Float32>(Int64 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
template <> inline bool greaterOp<Int128, Float32>(Int128 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
template <> inline bool greaterOp<Int256, Float32>(Int256 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
template <> inline bool greaterOp<UInt64, Float32>(UInt64 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
template <> inline bool greaterOp<UInt128, Float32>(UInt128 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
template <> inline bool greaterOp<UInt256, Float32>(UInt256 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
template <typename A, typename B>
inline bool_if_not_safe_conversion<A, B> equalsOp(A a, B b)
{
return equalsOpTmpl(a, b);
return DecomposedFloat<A>(a).equals(b);
}
}
template <typename A, typename B>
inline bool_if_safe_conversion<A, B> equalsOp(A a, B b)
{
using LargestType = std::conditional_t<(sizeof(A) >= sizeof(B)), A, B>;
return static_cast<LargestType>(a) == static_cast<LargestType>(b);
}
template <>
inline bool equalsOp<DB::Float64, DB::UInt64>(DB::Float64 f, DB::UInt64 u)
{
/// Maximum exactly representable integer.
return u <= (1ULL << std::numeric_limits<DB::Float64>::digits)
&& f == static_cast<DB::Float64>(u);
}
template <>
inline bool equalsOp<DB::UInt64, DB::Float64>(DB::UInt64 u, DB::Float64 f)
{
return equalsOp(f, u);
}
template <>
inline bool equalsOp<DB::Float64, DB::Int64>(DB::Float64 f, DB::Int64 u)
{
return u <= (1LL << std::numeric_limits<DB::Float64>::digits)
&& u >= -(1LL << std::numeric_limits<DB::Float64>::digits)
&& f == static_cast<DB::Float64>(u);
}
template <>
inline bool equalsOp<DB::Int64, DB::Float64>(DB::Int64 u, DB::Float64 f)
{
return equalsOp(f, u);
}
template <>
inline bool equalsOp<DB::Float32, DB::UInt64>(DB::Float32 f, DB::UInt64 u)
{
return u <= (1ULL << std::numeric_limits<DB::Float32>::digits)
&& f == static_cast<DB::Float32>(u);
}
template <>
inline bool equalsOp<DB::UInt64, DB::Float32>(DB::UInt64 u, DB::Float32 f)
{
return equalsOp(f, u);
}
template <>
inline bool equalsOp<DB::Float32, DB::Int64>(DB::Float32 f, DB::Int64 u)
{
return u <= (1LL << std::numeric_limits<DB::Float32>::digits)
&& u >= -(1LL << std::numeric_limits<DB::Float32>::digits)
&& f == static_cast<DB::Float32>(u);
}
template <>
inline bool equalsOp<DB::Int64, DB::Float32>(DB::Int64 u, DB::Float32 f)
{
return equalsOp(f, u);
}
template <>
inline bool equalsOp<DB::UInt128, DB::Float64>(DB::UInt128 u, DB::Float64 f)
{
/// TODO: This is wrong.
return u.items[0] == 0 && equalsOp(static_cast<UInt64>(u.items[1]), f);
}
template <>
inline bool equalsOp<UInt128, Float32>(UInt128 u, Float32 f)
{
return equalsOp(u, static_cast<Float64>(f));
}
template <>
inline bool equalsOp<Float64, UInt128>(Float64 f, UInt128 u)
{
return equalsOp(u, f);
}
template <>
inline bool equalsOp<Float32, UInt128>(Float32 f, UInt128 u)
{
return equalsOp(static_cast<Float64>(f), u);
}
inline bool NO_SANITIZE_UNDEFINED greaterOp(Int128 i, Float64 f)
{
static constexpr Int128 min_int128 = minInt128();
static constexpr Int128 max_int128 = maxInt128();
if (-MAX_INT64_WITH_EXACT_FLOAT64_REPR <= i && i <= MAX_INT64_WITH_EXACT_FLOAT64_REPR)
return static_cast<Float64>(i) > f;
return (f < static_cast<Float64>(min_int128))
|| (f < static_cast<Float64>(max_int128) && i > static_cast<Int128>(f));
}
inline bool NO_SANITIZE_UNDEFINED greaterOp(Float64 f, Int128 i)
{
static constexpr Int128 min_int128 = minInt128();
static constexpr Int128 max_int128 = maxInt128();
if (-MAX_INT64_WITH_EXACT_FLOAT64_REPR <= i && i <= MAX_INT64_WITH_EXACT_FLOAT64_REPR)
return f > static_cast<Float64>(i);
return (f >= static_cast<Float64>(max_int128))
|| (f > static_cast<Float64>(min_int128) && static_cast<Int128>(f) > i);
}
inline bool greaterOp(Int128 i, Float32 f) { return greaterOp(i, static_cast<Float64>(f)); }
inline bool greaterOp(Float32 f, Int128 i) { return greaterOp(static_cast<Float64>(f), i); }
inline bool NO_SANITIZE_UNDEFINED equalsOp(Int128 i, Float64 f) { return i == static_cast<Int128>(f) && static_cast<Float64>(i) == f; }
inline bool NO_SANITIZE_UNDEFINED equalsOp(Int128 i, Float32 f) { return i == static_cast<Int128>(f) && static_cast<Float32>(i) == f; }
inline bool equalsOp(Float64 f, Int128 i) { return equalsOp(i, f); }
inline bool equalsOp(Float32 f, Int128 i) { return equalsOp(i, f); }
template <typename A, typename B>
inline bool notEqualsOp(A a, B b)
bool notEqualsOp(A a, B b)
{
return !equalsOp(a, b);
}
template <typename A, typename B>
inline bool lessOp(A a, B b)
{
return greaterOp(b, a);
}
template <typename A, typename B>
inline bool_if_not_safe_conversion<A, B> lessOrEqualsOp(A a, B b)
{
if (isNaN(a) || isNaN(b))
return false;
return !greaterOp(a, b);
}
template <typename A, typename B>
inline bool_if_safe_conversion<A, B> lessOrEqualsOp(A a, B b)
{
return a <= b;
}
template <typename A, typename B>
inline bool_if_not_safe_conversion<A, B> greaterOrEqualsOp(A a, B b)
{
if (isNaN(a) || isNaN(b))
return false;
return !greaterOp(b, a);
}
template <typename A, typename B>
inline bool_if_safe_conversion<A, B> greaterOrEqualsOp(A a, B b)
{
return a >= b;
}
/// Converts numeric to an equal numeric of other type.
template <typename From, typename To>
inline bool NO_SANITIZE_UNDEFINED convertNumeric(From value, To & result)

View File

@ -845,6 +845,8 @@ decltype(auto) castToNearestFieldType(T && x)
using U = NearestFieldType<std::decay_t<T>>;
if constexpr (std::is_same_v<std::decay_t<T>, U>)
return std::forward<T>(x);
else if constexpr (std::is_same_v<std::decay_t<T>, UUID>)
return U(x.toUnderType());
else
return U(x);
}

View File

@ -180,6 +180,8 @@ struct Decimal
template <typename T> inline bool operator< (const Decimal<T> & x, const Decimal<T> & y) { return x.value < y.value; }
template <typename T> inline bool operator> (const Decimal<T> & x, const Decimal<T> & y) { return x.value > y.value; }
template <typename T> inline bool operator<= (const Decimal<T> & x, const Decimal<T> & y) { return x.value <= y.value; }
template <typename T> inline bool operator>= (const Decimal<T> & x, const Decimal<T> & y) { return x.value >= y.value; }
template <typename T> inline bool operator== (const Decimal<T> & x, const Decimal<T> & y) { return x.value == y.value; }
template <typename T> inline bool operator!= (const Decimal<T> & x, const Decimal<T> & y) { return x.value != y.value; }

View File

@ -290,7 +290,7 @@ namespace
if (value.type() == Poco::MongoDB::ElementTraits<String>::TypeId)
{
String string = static_cast<const Poco::MongoDB::ConcreteElement<String> &>(value).value();
assert_cast<ColumnUInt128 &>(column).getData().push_back(parse<UUID>(string));
assert_cast<ColumnUInt128 &>(column).getData().push_back(parse<UUID>(string).toUnderType());
}
else
throw Exception{"Type mismatch, expected String (UUID), got type id = " + toString(value.type()) + " for column "

View File

@ -113,15 +113,15 @@ public:
T maxWholeValue() const { return getScaleMultiplier(precision - scale) - T(1); }
template<typename U>
template <typename U>
bool canStoreWhole(U x) const
{
static_assert(std::is_signed_v<typename T::NativeType>);
static_assert(is_signed_v<typename T::NativeType>);
T max = maxWholeValue();
if constexpr (std::is_signed_v<U>)
return -max <= x && x <= max;
if constexpr (is_signed_v<U>)
return -max.value <= x && x <= max.value;
else
return x <= static_cast<std::make_unsigned_t<typename T::NativeType>>(max.value);
return x <= static_cast<make_unsigned_t<typename T::NativeType>>(max.value);
}
/// @returns multiplier for U to become T with correct scale

View File

@ -235,9 +235,9 @@ convertToDecimalImpl(const typename FromDataType::FieldType & value, UInt32 scal
if constexpr (is_big_int_v<FromFieldType>)
return ReturnType(convertDecimalsImpl<DataTypeDecimal<Decimal256>, ToDataType, ReturnType>(static_cast<Int256>(value), 0, scale, result));
else if constexpr (std::is_same_v<FromFieldType, UInt64>)
return ReturnType(convertDecimalsImpl<DataTypeDecimal<Decimal128>, ToDataType, ReturnType>(value, 0, scale, result));
return ReturnType(convertDecimalsImpl<DataTypeDecimal<Decimal128>, ToDataType, ReturnType>(static_cast<Int128>(value), 0, scale, result));
else
return ReturnType(convertDecimalsImpl<DataTypeDecimal<Decimal64>, ToDataType, ReturnType>(value, 0, scale, result));
return ReturnType(convertDecimalsImpl<DataTypeDecimal<Decimal64>, ToDataType, ReturnType>(static_cast<Int64>(value), 0, scale, result));
}
}

View File

@ -18,7 +18,7 @@ void SerializationUUID::deserializeText(IColumn & column, ReadBuffer & istr, con
{
UUID x;
readText(x, istr);
assert_cast<ColumnUInt128 &>(column).getData().push_back(x);
assert_cast<ColumnUInt128 &>(column).getData().push_back(x.toUnderType());
}
void SerializationUUID::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const
@ -44,7 +44,7 @@ void SerializationUUID::deserializeTextQuoted(IColumn & column, ReadBuffer & ist
assertChar('\'', istr);
readText(x, istr);
assertChar('\'', istr);
assert_cast<ColumnUInt128 &>(column).getData().push_back(x); /// It's important to do this at the end - for exception safety.
assert_cast<ColumnUInt128 &>(column).getData().push_back(x.toUnderType()); /// It's important to do this at the end - for exception safety.
}
void SerializationUUID::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
@ -60,7 +60,7 @@ void SerializationUUID::deserializeTextJSON(IColumn & column, ReadBuffer & istr,
assertChar('"', istr);
readText(x, istr);
assertChar('"', istr);
assert_cast<ColumnUInt128 &>(column).getData().push_back(x);
assert_cast<ColumnUInt128 &>(column).getData().push_back(x.toUnderType());
}
void SerializationUUID::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
@ -74,7 +74,7 @@ void SerializationUUID::deserializeTextCSV(IColumn & column, ReadBuffer & istr,
{
UUID value;
readCSV(value, istr);
assert_cast<ColumnUInt128 &>(column).getData().push_back(value);
assert_cast<ColumnUInt128 &>(column).getData().push_back(value.toUnderType());
}
}

View File

@ -782,7 +782,7 @@ class FunctionBinaryArithmetic : public IFunction
return function->execute(new_arguments, result_type, input_rows_count);
}
template <class T, class ResultDataType, class CC, class C>
template <typename T, typename ResultDataType, typename CC, typename C>
static auto helperGetOrConvert(const CC & col_const, const C & col)
{
using ResultType = typename ResultDataType::FieldType;
@ -790,12 +790,14 @@ class FunctionBinaryArithmetic : public IFunction
if constexpr (IsFloatingPoint<ResultDataType> && IsDecimalNumber<T>)
return DecimalUtils::convertTo<NativeResultType>(col_const->template getValue<T>(), col.getScale());
else if constexpr (IsDecimalNumber<T>)
return col_const->template getValue<T>().value;
else
return col_const->template getValue<T>();
}
template <OpCase op_case, bool left_decimal, bool right_decimal, class OpImpl, class OpImplCheck,
class L, class R, class VR, class SA, class SB>
template <OpCase op_case, bool left_decimal, bool right_decimal, typename OpImpl, typename OpImplCheck,
typename L, typename R, typename VR, typename SA, typename SB>
void helperInvokeEither(const L& left, const R& right, VR& vec_res, SA scale_a, SB scale_b) const
{
if (check_decimal_overflow)

View File

@ -784,7 +784,7 @@ inline void parseImpl<DataTypeUUID>(DataTypeUUID::FieldType & x, ReadBuffer & rb
{
UUID tmp;
readUUIDText(tmp, rb);
x = tmp;
x = tmp.toUnderType();
}
@ -824,7 +824,7 @@ inline bool tryParseImpl<DataTypeUUID>(DataTypeUUID::FieldType & x, ReadBuffer &
if (!tryReadUUIDText(tmp, rb))
return false;
x = tmp;
x = tmp.toUnderType();
return true;
}

View File

@ -45,11 +45,7 @@ void writeSlice(const NumericArraySlice<T> & slice, NumericArraySink<U> & sink)
if constexpr (OverBigInt<T> || OverBigInt<U>)
{
if constexpr (std::is_same_v<U, UInt128>)
{
throw Exception("No conversion between UInt128 and " + demangle(typeid(T).name()), ErrorCodes::NOT_IMPLEMENTED);
}
else if constexpr (IsDecimalNumber<T>)
if constexpr (IsDecimalNumber<T>)
dst = static_cast<NativeU>(src.value);
else
dst = static_cast<NativeU>(src);

View File

@ -14,7 +14,7 @@ struct GenericArraySink;
template <typename ArraySink>
struct NullableArraySink;
using NumericArraySinks = typename TypeListMap<NumericArraySink, TypeListNumbersAndUInt128>::Type;
using NumericArraySinks = typename TypeListMap<NumericArraySink, TypeListNumbers>::Type;
using BasicArraySinks = typename AppendToTypeList<GenericArraySink, NumericArraySinks>::Type;
using NullableArraySinks = typename TypeListMap<NullableArraySink, BasicArraySinks>::Type;
using TypeListArraySinks = typename TypeListConcat<BasicArraySinks, NullableArraySinks>::Type;

View File

@ -17,7 +17,7 @@ struct NullableArraySource;
template <typename Base>
struct ConstSource;
using NumericArraySources = typename TypeListMap<NumericArraySource, TypeListNumbersAndUInt128>::Type;
using NumericArraySources = typename TypeListMap<NumericArraySource, TypeListNumbers>::Type;
using BasicArraySources = typename AppendToTypeList<GenericArraySource, NumericArraySources>::Type;
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, BasicArraySources>::Type

View File

@ -17,7 +17,7 @@ struct NullableValueSource;
template <typename Base>
struct ConstSource;
using NumericValueSources = typename TypeListMap<NumericValueSource, TypeListNumbersAndUInt128>::Type;
using NumericValueSources = typename TypeListMap<NumericValueSource, TypeListNumbers>::Type;
using BasicValueSources = typename AppendToTypeList<GenericValueSource, NumericValueSources>::Type;
using NullableValueSources = typename TypeListMap<NullableValueSource, BasicValueSources>::Type;
using BasicAndNullableValueSources = typename TypeListConcat<BasicValueSources, NullableValueSources>::Type;

View File

@ -55,7 +55,7 @@ struct ArraySinkCreator<>
std::unique_ptr<IArraySink> createArraySink(ColumnArray & col, size_t column_size)
{
using Creator = ApplyTypeListForClass<ArraySinkCreator, TypeListNumbersAndUInt128>::Type;
using Creator = ApplyTypeListForClass<ArraySinkCreator, TypeListNumbers>::Type;
return Creator::create(col.getData(), col.getOffsets(), column_size);
}
}

View File

@ -58,7 +58,7 @@ struct ArraySourceCreator<>
std::unique_ptr<IArraySource> createArraySource(const ColumnArray & col, bool is_const, size_t total_rows)
{
using Creator = typename ApplyTypeListForClass<ArraySourceCreator, TypeListNumbersAndUInt128>::Type;
using Creator = typename ApplyTypeListForClass<ArraySourceCreator, TypeListNumbers>::Type;
if (const auto * column_nullable = typeid_cast<const ColumnNullable *>(&col.getData()))
{
auto column = ColumnArray::create(column_nullable->getNestedColumnPtr(), col.getOffsetsPtr());

View File

@ -58,7 +58,7 @@ struct ValueSourceCreator<>
std::unique_ptr<IValueSource> createValueSource(const IColumn & col, bool is_const, size_t total_rows)
{
using Creator = typename ApplyTypeListForClass<ValueSourceCreator, TypeListNumbersAndUInt128>::Type;
using Creator = typename ApplyTypeListForClass<ValueSourceCreator, TypeListNumbers>::Type;
if (const auto * column_nullable = typeid_cast<const ColumnNullable *>(&col))
{
return Creator::create(column_nullable->getNestedColumn(), &column_nullable->getNullMapData(), is_const, total_rows);

View File

@ -167,7 +167,7 @@ struct ArrayAggregateImpl
{
size_t array_size = offsets[i] - pos;
/// Just multiply the value by array size.
res[i] = x * array_size;
res[i] = x * Result(array_size);
}
else if constexpr (aggregate_operation == AggregateOperation::min ||
aggregate_operation == AggregateOperation::max)
@ -206,11 +206,14 @@ struct ArrayAggregateImpl
size_t pos = 0;
for (size_t i = 0; i < offsets.size(); ++i)
{
AggregationType s = 0;
AggregationType s{};
/// Array is empty
if (offsets[i] == pos)
{
if constexpr (IsDecimalNumber<AggregationType>)
res[i] = s.value;
else
res[i] = s;
continue;
}
@ -250,7 +253,7 @@ struct ArrayAggregateImpl
{
if constexpr (IsDecimalNumber<Element>)
{
s = s / count;
s = s / AggregationType(count);
res[i] = DecimalUtils::convertTo<Result>(s, data.getScale());
}
else

View File

@ -60,8 +60,8 @@ struct ArrayCumSumNonNegativeImpl
for (; pos < offset; ++pos)
{
accumulated += src_values[pos];
if (accumulated < 0)
accumulated = 0;
if (accumulated < Dst{})
accumulated = {};
res_values[pos] = accumulated;
}
}

View File

@ -57,7 +57,7 @@ struct ArrayDifferenceImpl
{
if (pos == begin)
{
dst[pos] = 0;
dst[pos] = {};
prev = src[pos];
}
else

View File

@ -518,7 +518,9 @@ ColumnPtr FunctionArrayIntersect::execute(const UnpackedArrays & arrays, Mutable
typename Map::mapped_type * value = nullptr;
if constexpr (is_numeric_column)
{
value = &map[columns[arg_num]->getElement(i)];
}
else if constexpr (std::is_same<ColumnType, ColumnString>::value || std::is_same<ColumnType, ColumnFixedString>::value)
value = &map[columns[arg_num]->getDataAt(i)];
else

View File

@ -45,8 +45,8 @@ public:
{
/** https://tools.ietf.org/html/rfc4122#section-4.4
*/
uuid.low = (uuid.low & 0xffffffffffff0fffull) | 0x0000000000004000ull;
uuid.high = (uuid.high & 0x3fffffffffffffffull) | 0x8000000000000000ull;
uuid.items[0] = (uuid.items[0] & 0xffffffffffff0fffull) | 0x0000000000004000ull;
uuid.items[1] = (uuid.items[1] & 0x3fffffffffffffffull) | 0x8000000000000000ull;
}
return col_res;

View File

@ -27,18 +27,6 @@ roundDownToPowerOfTwo(T x)
return x <= 0 ? 0 : (T(1) << (63 - __builtin_clzll(x)));
}
template <typename T>
inline std::enable_if_t<std::is_same_v<T, Int128>, T>
roundDownToPowerOfTwo(T x)
{
if (x <= 0)
return 0;
if (Int64 x64 = Int64(x >> 64))
return Int128(roundDownToPowerOfTwo(x64)) << 64;
return roundDownToPowerOfTwo(Int64(x));
}
template <typename T>
inline std::enable_if_t<std::is_same_v<T, Float32>, T>
roundDownToPowerOfTwo(T x)

View File

@ -1,8 +1,9 @@
#pragma once
#include <Core/Types.h>
#include <Common/HashTable/Hash.h>
#include <Common/LRUCache.h>
#include <Common/SipHash.h>
#include <Common/UInt128.h>
#include <Common/ProfileEvents.h>
#include <IO/MMappedFile.h>
@ -39,8 +40,7 @@ public:
hash.update(offset);
hash.update(length);
hash.get128(key.low, key.high);
hash.get128(key);
return key;
}

View File

@ -303,7 +303,7 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
case '8': [[fallthrough]];
case '9':
{
if constexpr (check_overflow == ReadIntTextCheckOverflow::CHECK_OVERFLOW)
if constexpr (check_overflow == ReadIntTextCheckOverflow::CHECK_OVERFLOW && !is_big_int_v<T>)
{
/// Perform relativelly slow overflow check only when
/// number of decimal digits so far is close to the max for given type.

View File

@ -14,6 +14,7 @@
#include <common/find_symbols.h>
#include <common/StringRef.h>
#include <common/wide_integer_to_string.h>
#include <common/DecomposedFloat.h>
#include <Core/DecimalFunctions.h>
#include <Core/Types.h>
@ -137,81 +138,6 @@ inline void writeBoolText(bool x, WriteBuffer & buf)
}
struct DecomposedFloat64
{
DecomposedFloat64(double x)
{
memcpy(&x_uint, &x, sizeof(x));
}
uint64_t x_uint;
bool sign() const
{
return x_uint >> 63;
}
uint16_t exponent() const
{
return (x_uint >> 52) & 0x7FF;
}
int16_t normalized_exponent() const
{
return int16_t(exponent()) - 1023;
}
uint64_t mantissa() const
{
return x_uint & 0x5affffffffffffful;
}
/// NOTE Probably floating point instructions can be better.
bool is_inside_int64() const
{
return x_uint == 0
|| (normalized_exponent() >= 0 && normalized_exponent() <= 52
&& ((mantissa() & ((1ULL << (52 - normalized_exponent())) - 1)) == 0));
}
};
struct DecomposedFloat32
{
DecomposedFloat32(float x)
{
memcpy(&x_uint, &x, sizeof(x));
}
uint32_t x_uint;
bool sign() const
{
return x_uint >> 31;
}
uint16_t exponent() const
{
return (x_uint >> 23) & 0xFF;
}
int16_t normalized_exponent() const
{
return int16_t(exponent()) - 127;
}
uint32_t mantissa() const
{
return x_uint & 0x7fffff;
}
bool is_inside_int32() const
{
return x_uint == 0
|| (normalized_exponent() >= 0 && normalized_exponent() <= 23
&& ((mantissa() & ((1ULL << (23 - normalized_exponent())) - 1)) == 0));
}
};
template <typename T>
inline size_t writeFloatTextFastPath(T x, char * buffer)
{
@ -222,14 +148,14 @@ inline size_t writeFloatTextFastPath(T x, char * buffer)
/// The library Ryu has low performance on integers.
/// This workaround improves performance 6..10 times.
if (DecomposedFloat64(x).is_inside_int64())
if (DecomposedFloat64(x).is_integer_in_representable_range())
result = itoa(Int64(x), buffer) - buffer;
else
result = jkj::dragonbox::to_chars_n(x, buffer) - buffer;
}
else
{
if (DecomposedFloat32(x).is_inside_int32())
if (DecomposedFloat32(x).is_integer_in_representable_range())
result = itoa(Int32(x), buffer) - buffer;
else
result = jkj::dragonbox::to_chars_n(x, buffer) - buffer;
@ -909,6 +835,7 @@ inline void writeBinary(const Decimal128 & x, WriteBuffer & buf) { writePODBinar
inline void writeBinary(const Decimal256 & x, WriteBuffer & buf) { writePODBinary(x.value, buf); }
inline void writeBinary(const LocalDate & x, WriteBuffer & buf) { writePODBinary(x, buf); }
inline void writeBinary(const LocalDateTime & x, WriteBuffer & buf) { writePODBinary(x, buf); }
inline void writeBinary(const UUID & x, WriteBuffer & buf) { writePODBinary(x, buf); }
/// Methods for outputting the value in text form for a tab-separated format.
template <typename T>

View File

@ -10,6 +10,7 @@
# include <Interpreters/Context.h>
# include <Interpreters/ExpressionActions.h>
# include <Common/LRUCache.h>
# include <Common/HashTable/Hash.h>
namespace DB

View File

@ -384,7 +384,7 @@ template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<HashJoin:
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<HashJoin::Type::keys256, Value, Mapped>
{
using Type = ColumnsHashing::HashMethodKeysFixed<Value, UInt256, Mapped, false, false, false>;
using Type = ColumnsHashing::HashMethodKeysFixed<Value, UInt256, Mapped, false, false, false, use_offset>;
};
template <typename Value, typename Mapped> struct KeyGetterForTypeImpl<HashJoin::Type::hashed, Value, Mapped>
{

View File

@ -80,7 +80,7 @@ static Field convertIntToDecimalType(const Field & from, const DataTypeDecimal<T
if (!type.canStoreWhole(value))
throw Exception("Number is too much to place in " + type.getName(), ErrorCodes::ARGUMENT_OUT_OF_BOUND);
T scaled_value = type.getScaleMultiplier() * value;
T scaled_value = type.getScaleMultiplier() * static_cast<T>(value);
return DecimalField<T>(scaled_value, type.getScale());
}

View File

@ -33,7 +33,7 @@ void LimitByTransform::transform(Chunk & chunk)
for (UInt64 row = 0; row < num_rows; ++row)
{
UInt128 key(0, 0);
UInt128 key{};
SipHash hash;
for (auto position : key_positions)

View File

@ -1,7 +1,7 @@
#pragma once
#include <Processors/ISimpleTransform.h>
#include <Common/HashTable/HashMap.h>
#include <Common/UInt128.h>
namespace DB
{

View File

@ -3,6 +3,7 @@
#include <AggregateFunctions/AggregateFunctionFactory.h>
#include <Common/Arena.h>
#include <Common/FieldVisitorsAccurateComparison.h>
#include <common/arithmeticOverflow.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/getLeastSupertype.h>
#include <Interpreters/ExpressionActions.h>
@ -67,15 +68,9 @@ static int compareValuesWithOffset(const IColumn * _compared_column,
bool is_overflow;
if (offset_is_preceding)
{
is_overflow = __builtin_sub_overflow(reference_value, offset,
&reference_value);
}
is_overflow = common::subOverflow(reference_value, offset, reference_value);
else
{
is_overflow = __builtin_add_overflow(reference_value, offset,
&reference_value);
}
is_overflow = common::addOverflow(reference_value, offset, reference_value);
// fmt::print(stderr,
// "compared [{}] = {}, old ref {}, shifted ref [{}] = {}, offset {} preceding {} overflow {} to negative {}\n",

View File

@ -8,6 +8,7 @@
#include <deque>
namespace DB
{

View File

@ -1,5 +1,7 @@
#include <vector>
#include <Storages/MergeTree/MergeTreeDataPartUUID.h>
namespace DB
{

View File

@ -80,7 +80,7 @@ void StorageSystemQuotas::fillData(MutableColumns & res_columns, ContextPtr cont
const RolesOrUsersSet & apply_to)
{
column_name.insertData(name.data(), name.length());
column_id.push_back(id);
column_id.push_back(id.toUnderType());
column_storage.insertData(storage_name.data(), storage_name.length());
if (key_type != KeyType::NONE)

View File

@ -39,7 +39,7 @@ void StorageSystemRoles::fillData(MutableColumns & res_columns, ContextPtr conte
const String & storage_name)
{
column_name.insertData(name.data(), name.length());
column_id.push_back(id);
column_id.push_back(id.toUnderType());
column_storage.insertData(storage_name.data(), storage_name.length());
};

View File

@ -93,7 +93,7 @@ void StorageSystemRowPolicies::fillData(MutableColumns & res_columns, ContextPtr
column_short_name.insertData(name_parts.short_name.data(), name_parts.short_name.length());
column_database.insertData(name_parts.database.data(), name_parts.database.length());
column_table.insertData(name_parts.table_name.data(), name_parts.table_name.length());
column_id.push_back(id);
column_id.push_back(id.toUnderType());
column_storage.insertData(storage_name.data(), storage_name.length());
for (auto condition_type : ext::range(MAX_CONDITION_TYPE))

View File

@ -54,7 +54,7 @@ void StorageSystemSettingsProfiles::fillData(MutableColumns & res_columns, Conte
const RolesOrUsersSet & apply_to)
{
column_name.insertData(name.data(), name.length());
column_id.push_back(id);
column_id.push_back(id.toUnderType());
column_storage.insertData(storage_name.data(), storage_name.length());
column_num_elements.push_back(elements.size());

View File

@ -95,7 +95,7 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, ContextPtr conte
const RolesOrUsersSet & grantees)
{
column_name.insertData(name.data(), name.length());
column_id.push_back(id);
column_id.push_back(id.toUnderType());
column_storage.insertData(storage_name.data(), storage_name.length());
column_auth_type.push_back(static_cast<Int8>(authentication.getType()));