From 776ee2ea1ea147311ef9a3923c00e9a8c045c5b6 Mon Sep 17 00:00:00 2001 From: Conor Hoekstra Date: Thu, 23 Sep 2021 12:36:35 -0400 Subject: [PATCH 1/3] Fix and test --- cpp/include/cudf/fixed_point/fixed_point.hpp | 8 +++--- cpp/tests/unary/cast_tests.cpp | 26 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/cpp/include/cudf/fixed_point/fixed_point.hpp b/cpp/include/cudf/fixed_point/fixed_point.hpp index e3694dc289a..af2715d1290 100644 --- a/cpp/include/cudf/fixed_point/fixed_point.hpp +++ b/cpp/include/cudf/fixed_point/fixed_point.hpp @@ -279,9 +279,11 @@ class fixed_point { typename cuda::std::enable_if_t::value>* = nullptr> explicit constexpr operator U() const { - // Don't cast to U until converting to Rep because in certain cases casting to U before shifting - // will result in integer overflow (i.e. if U = int32_t, Rep = int64_t and _value > 2 billion) - return static_cast(detail::shift(_value, scale_type{-_scale})); + // Cast to the larger of the two types (of U and Rep) before converting to Rep because in + // certain cases casting to U before shifting will result in integer overflow (i.e. if U = + // int32_t, Rep = int64_t and _value > 2 billion) + auto const value = std::common_type_t(_value); + return static_cast(detail::shift(value, scale_type{-_scale})); } CUDA_HOST_DEVICE_CALLABLE operator scaled_integer() const diff --git a/cpp/tests/unary/cast_tests.cpp b/cpp/tests/unary/cast_tests.cpp index c71f6aa2019..f3b0a231b34 100644 --- a/cpp/tests/unary/cast_tests.cpp +++ b/cpp/tests/unary/cast_tests.cpp @@ -848,3 +848,29 @@ TYPED_TEST(FixedPointTests, FixedPointToFixedPointDifferentTypeidUpNullMask) CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); } + +TEST_F(FixedPointTestSingleType, AvoidOverflowDecimal32ToDecimal64) +{ + using namespace numeric; + using fp_wrapper32 = cudf::test::fixed_point_column_wrapper; + using fp_wrapper64 = cudf::test::fixed_point_column_wrapper; + + auto const input = fp_wrapper32{{9999999}, scale_type{3}}; + auto const expected = fp_wrapper64{{9999999}, scale_type{3}}; + auto const result = cudf::cast(input, make_fixed_point_data_type(3)); + + CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); +} + +TEST_F(FixedPointTestSingleType, AvoidOverflowDecimal32ToInt64) +{ + using namespace numeric; + using fp_wrapper32 = cudf::test::fixed_point_column_wrapper; + using fw_wrapper64 = cudf::test::fixed_width_column_wrapper; + + auto const input = fp_wrapper32{{9999999}, scale_type{3}}; + auto const expected = fw_wrapper64{{9999999000}}; + auto const result = cudf::cast(input, cudf::data_type{cudf::type_id::INT64}); + + CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, result->view()); +} From 96d3dd4e4dc60d9856bec7f91952fd533929cfff Mon Sep 17 00:00:00 2001 From: Conor Hoekstra Date: Fri, 24 Sep 2021 11:05:47 -0400 Subject: [PATCH 2/3] Python fix --- python/cudf/cudf/tests/test_decimal.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/cudf/cudf/tests/test_decimal.py b/python/cudf/cudf/tests/test_decimal.py index 51f05e1b876..488217e9fde 100644 --- a/python/cudf/cudf/tests/test_decimal.py +++ b/python/cudf/cudf/tests/test_decimal.py @@ -14,6 +14,7 @@ FLOAT_TYPES, INTEGER_TYPES, NUMERIC_TYPES, + SIGNED_TYPES, _decimal_series, assert_eq, ) @@ -228,7 +229,7 @@ def test_typecast_to_from_decimal(data, from_dtype, to_dtype): "from_dtype", [Decimal64Dtype(7, 2), Decimal64Dtype(11, 4), Decimal64Dtype(17, 10)], ) -@pytest.mark.parametrize("to_dtype", NUMERIC_TYPES) +@pytest.mark.parametrize("to_dtype", SIGNED_TYPES) def test_typecast_from_decimal(data, from_dtype, to_dtype): got = data.astype(from_dtype) pa_arr = got.to_arrow().cast(to_dtype, safe=False) From c2fdd23b6ac34fd36f1343e28298b194b3b8bdae Mon Sep 17 00:00:00 2001 From: Conor Hoekstra Date: Fri, 24 Sep 2021 11:15:23 -0400 Subject: [PATCH 3/3] unused import --- python/cudf/cudf/tests/test_decimal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/cudf/cudf/tests/test_decimal.py b/python/cudf/cudf/tests/test_decimal.py index 488217e9fde..c37381a3af9 100644 --- a/python/cudf/cudf/tests/test_decimal.py +++ b/python/cudf/cudf/tests/test_decimal.py @@ -13,7 +13,6 @@ from cudf.testing._utils import ( FLOAT_TYPES, INTEGER_TYPES, - NUMERIC_TYPES, SIGNED_TYPES, _decimal_series, assert_eq,