Merge pull request #20067 from ClickHouse/mod-negative-type-promotion

Add type promotion for modulo of division of negative number
This commit is contained in:
alexey-milovidov 2021-02-05 09:31:46 +03:00 committed by GitHub
commit 34151eea2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 11 additions and 4 deletions

View File

@ -104,11 +104,16 @@ template <typename A, typename B> struct ResultOfIntegerDivision
sizeof(A)>::Type; sizeof(A)>::Type;
}; };
/** Division with remainder you get a number with the same number of bits as in divisor. /** Division with remainder you get a number with the same number of bits as in divisor,
* or larger in case of signed type.
*/ */
template <typename A, typename B> struct ResultOfModulo template <typename A, typename B> struct ResultOfModulo
{ {
using Type0 = typename Construct<is_signed_v<A> || is_signed_v<B>, false, sizeof(B)>::Type; static constexpr bool result_is_signed = is_signed_v<A>;
/// If modulo of division can yield negative number, we need larger type to accommodate it.
/// Example: toInt32(-199) % toUInt8(200) will return -199 that does not fit in Int8, only in Int16.
static constexpr size_t size_of_result = result_is_signed ? nextSize(sizeof(B)) : sizeof(B);
using Type0 = typename Construct<result_is_signed, false, size_of_result>::Type;
using Type = std::conditional_t<std::is_floating_point_v<A> || std::is_floating_point_v<B>, Float64, Type0>; using Type = std::conditional_t<std::is_floating_point_v<A> || std::is_floating_point_v<B>, Float64, Type0>;
}; };

View File

@ -258,7 +258,7 @@ TEST(NumberTraits, Others)
ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt16, DB::Int16>::Type()), "Float64"); ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt16, DB::Int16>::Type()), "Float64");
ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt32, DB::Int16>::Type()), "Float64"); ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt32, DB::Int16>::Type()), "Float64");
ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfIntegerDivision<DB::UInt8, DB::Int16>::Type()), "Int8"); ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfIntegerDivision<DB::UInt8, DB::Int16>::Type()), "Int8");
ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfModulo<DB::UInt32, DB::Int8>::Type()), "Int8"); ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfModulo<DB::UInt32, DB::Int8>::Type()), "UInt8");
} }

View File

@ -0,0 +1 @@
SELECT toInt32(-199) % 200;