From a3ac27674134a743b16e963aa5490e8077cbb297 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 4 Feb 2021 14:56:04 +0300 Subject: [PATCH 1/2] Add type promotion for modulo of division of negative number --- src/DataTypes/NumberTraits.h | 11 ++++++++--- .../01700_mod_negative_type_promotion.reference | 1 + .../0_stateless/01700_mod_negative_type_promotion.sql | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 tests/queries/0_stateless/01700_mod_negative_type_promotion.reference create mode 100644 tests/queries/0_stateless/01700_mod_negative_type_promotion.sql diff --git a/src/DataTypes/NumberTraits.h b/src/DataTypes/NumberTraits.h index 3aa00c68274..479fc37c795 100644 --- a/src/DataTypes/NumberTraits.h +++ b/src/DataTypes/NumberTraits.h @@ -104,11 +104,16 @@ template struct ResultOfIntegerDivision 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 struct ResultOfModulo { - using Type0 = typename Construct || is_signed_v, false, sizeof(B)>::Type; + static constexpr bool result_is_signed = is_signed_v; + /// If modulo of division can yield negative number, we need larger type to accomodate 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::Type; using Type = std::conditional_t || std::is_floating_point_v, Float64, Type0>; }; diff --git a/tests/queries/0_stateless/01700_mod_negative_type_promotion.reference b/tests/queries/0_stateless/01700_mod_negative_type_promotion.reference new file mode 100644 index 00000000000..b8d2624b7fe --- /dev/null +++ b/tests/queries/0_stateless/01700_mod_negative_type_promotion.reference @@ -0,0 +1 @@ +-199 diff --git a/tests/queries/0_stateless/01700_mod_negative_type_promotion.sql b/tests/queries/0_stateless/01700_mod_negative_type_promotion.sql new file mode 100644 index 00000000000..db850ba5c80 --- /dev/null +++ b/tests/queries/0_stateless/01700_mod_negative_type_promotion.sql @@ -0,0 +1 @@ +SELECT toInt32(-199) % 200; From 85b5805c3cc0c20286030cd505356c9b28c25047 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 4 Feb 2021 19:36:31 +0300 Subject: [PATCH 2/2] Fix tests --- src/DataTypes/NumberTraits.h | 2 +- src/Functions/tests/gtest_number_traits.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DataTypes/NumberTraits.h b/src/DataTypes/NumberTraits.h index 479fc37c795..c3b0d956ef5 100644 --- a/src/DataTypes/NumberTraits.h +++ b/src/DataTypes/NumberTraits.h @@ -110,7 +110,7 @@ template struct ResultOfIntegerDivision template struct ResultOfModulo { static constexpr bool result_is_signed = is_signed_v; - /// If modulo of division can yield negative number, we need larger type to accomodate it. + /// 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::Type; diff --git a/src/Functions/tests/gtest_number_traits.cpp b/src/Functions/tests/gtest_number_traits.cpp index 7664b4fcbdc..7f25c6cbeb7 100644 --- a/src/Functions/tests/gtest_number_traits.cpp +++ b/src/Functions/tests/gtest_number_traits.cpp @@ -258,7 +258,7 @@ TEST(NumberTraits, Others) ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfFloatingPointDivision::Type()), "Float64"); ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfFloatingPointDivision::Type()), "Float64"); ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfIntegerDivision::Type()), "Int8"); - ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfModulo::Type()), "Int8"); + ASSERT_EQ(getTypeString(DB::NumberTraits::ResultOfModulo::Type()), "UInt8"); }