From f3ce7ea800ee9299ad8929474a8accf5d90214d1 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Mon, 7 Feb 2022 11:09:13 -0500 Subject: [PATCH] Fix string to decimal128 conversion handling large exponents --- .../strings/detail/convert/fixed_point.cuh | 12 ++++++++---- cpp/tests/strings/fixed_point_tests.cpp | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/cpp/include/cudf/strings/detail/convert/fixed_point.cuh b/cpp/include/cudf/strings/detail/convert/fixed_point.cuh index aa3f544202f..7af56f89449 100644 --- a/cpp/include/cudf/strings/detail/convert/fixed_point.cuh +++ b/cpp/include/cudf/strings/detail/convert/fixed_point.cuh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NVIDIA CORPORATION. + * Copyright (c) 2021-2022, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include @@ -150,9 +152,11 @@ __device__ DecimalType parse_decimal(char const* iter, char const* iter_end, int exp_ten += exp_offset; // shift the output value based on the exp_ten and the scale values - value = exp_ten < scale - ? value / static_cast(exp10(static_cast(scale - exp_ten))) - : value * static_cast(exp10(static_cast(exp_ten - scale))); + auto const shift_adjust = + abs(scale - exp_ten) > cuda::std::numeric_limits::digits10 + ? cuda::std::numeric_limits::max() + : numeric::detail::exp10(abs(scale - exp_ten)); + value = exp_ten < scale ? value / shift_adjust : value * shift_adjust; return static_cast(value) * (sign == 0 ? 1 : sign); } diff --git a/cpp/tests/strings/fixed_point_tests.cpp b/cpp/tests/strings/fixed_point_tests.cpp index 5872a9e5bb7..81122b1c5d8 100644 --- a/cpp/tests/strings/fixed_point_tests.cpp +++ b/cpp/tests/strings/fixed_point_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NVIDIA CORPORATION. + * Copyright (c) 2021-2022, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -112,6 +112,22 @@ TEST_F(StringsConvertTest, ToFixedPointDecimal128) CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(*results, expected); } +TEST_F(StringsConvertTest, ToFixedPointLargeScale) +{ + using namespace numeric; + using RepType = cudf::device_storage_type_t; + using fp_wrapper = cudf::test::fixed_point_column_wrapper; + + auto const strings = cudf::test::strings_column_wrapper({"0.05", "0.06", "0.50", "5.01"}); + + auto const scale = scale_type{-25}; + auto const type = cudf::data_type{cudf::type_to_id(), scale}; + auto const results = cudf::strings::to_fixed_point(cudf::strings_column_view(strings), type); + + auto const expected = fp_wrapper{{5, 6, 50, 501}, scale_type{-2}}; + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(*results, expected); +} + TEST_F(StringsConvertTest, FromFixedPointDecimal128) { using namespace numeric;