This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
commit 091b5b503e0856a40213505a1642455b66e6a669
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 24 09:20:53 2026 +0800
branch-4.1: [fix](function) Fix decimal rounding overflow at scale
boundaries #68251 (#68415)
Cherry-picked from #68251
Co-authored-by: Mryange <[email protected]>
---
be/src/exprs/function/round.h | 248 +++++++------------------
be/test/exprs/function/function_round_test.cpp | 88 +++++++++
2 files changed, 150 insertions(+), 186 deletions(-)
diff --git a/be/src/exprs/function/round.h b/be/src/exprs/function/round.h
index 1b44ef1dfb2..2aefa906fcc 100644
--- a/be/src/exprs/function/round.h
+++ b/be/src/exprs/function/round.h
@@ -108,41 +108,42 @@ struct IntegerRoundingComputation {
static size_t prepare(size_t scale) { return scale; }
- /// Integer overflow is Ok.
static ALWAYS_INLINE T compute_impl(T x, T scale, T target_scale) {
+ T quotient = x / scale;
+ const T remainder = x - quotient * scale;
+
if constexpr (rounding_mode == RoundingMode::Trunc) {
- return target_scale > 1 ? x / scale * target_scale : x / scale;
+ return target_scale > 1 ? quotient * target_scale : quotient;
}
if constexpr (rounding_mode == RoundingMode::Floor) {
- if (x < 0) {
- x -= scale - 1;
+ if (remainder < 0) {
+ --quotient;
}
- return target_scale > 1 ? x / scale * target_scale : x / scale;
+ return target_scale > 1 ? quotient * target_scale : quotient;
}
if constexpr (rounding_mode == RoundingMode::Ceil) {
- if (x >= 0) {
- x += scale - 1;
+ if (remainder > 0) {
+ ++quotient;
}
- return target_scale > 1 ? x / scale * target_scale : x / scale;
+ return target_scale > 1 ? quotient * target_scale : quotient;
}
if constexpr (rounding_mode == RoundingMode::Round) {
- if (x < 0) {
- x -= scale;
- }
+ const T abs_remainder = remainder < 0 ? -remainder : remainder;
+ const T remainder_complement = scale - abs_remainder;
+ const T carry = remainder < 0 ? -1 : 1;
if constexpr (tie_breaking_mode == TieBreakingMode::Auto) {
- x = (x + scale / 2) / scale;
+ if (remainder != 0 && abs_remainder >= remainder_complement) {
+ quotient += carry;
+ }
}
if constexpr (tie_breaking_mode == TieBreakingMode::Bankers) {
- T quotient = (x + scale / 2) / scale;
- if (quotient * scale == x + scale / 2) {
- // round half to even
- x = (quotient + (x < 0)) & ~1;
- } else {
- // round the others as usual
- x = quotient;
+ if (remainder != 0 &&
+ (abs_remainder > remainder_complement ||
+ (abs_remainder == remainder_complement && (quotient & 1)
!= 0))) {
+ quotient += carry;
}
}
- return target_scale > 1 ? x * target_scale : x;
+ return target_scale > 1 ? quotient * target_scale : quotient;
}
}
@@ -157,7 +158,21 @@ struct IntegerRoundingComputation {
U target_scale) {
if constexpr (sizeof(T) <= sizeof(scale) && scale_mode ==
ScaleMode::Negative) {
if (scale >= std::numeric_limits<T>::max()) {
- *out = 0;
+ if constexpr (!is_decimal(Type)) {
+ *out = 0;
+ } else {
+ // A saturated divisor is larger than every valid value of
this Decimal type.
+ // Only directed rounding can produce one representable
target unit.
+ if (target_scale >= std::numeric_limits<T>::max()) {
+ *out = T(0);
+ } else if constexpr (rounding_mode == RoundingMode::Floor)
{
+ *out = *in < 0 ? -target_scale : T(0);
+ } else if constexpr (rounding_mode == RoundingMode::Ceil) {
+ *out = *in > 0 ? target_scale : T(0);
+ } else {
+ *out = T(0);
+ }
+ }
return;
}
}
@@ -176,28 +191,21 @@ private:
public:
static NO_INLINE void apply(const Container& in, UInt32 in_scale,
Container& out,
- Int16 out_scale) {
- Int16 scale_arg = in_scale - out_scale;
+ Int16 out_scale, Int16 result_scale) {
+ Int32 scale_arg = static_cast<Int32>(in_scale) - out_scale;
if (scale_arg > 0) {
auto scale = DecimalScaleParams::get_scale_factor<Type>(scale_arg);
+ auto target_scale =
+ DecimalScaleParams::get_scale_factor<Type>(result_scale -
out_scale);
- const NativeType* __restrict p_in = reinterpret_cast<const
NativeType*>(in.data());
+ const auto* __restrict p_in = reinterpret_cast<const
NativeType*>(in.data());
const NativeType* end_in = reinterpret_cast<const
NativeType*>(in.data()) + in.size();
- NativeType* __restrict p_out =
reinterpret_cast<NativeType*>(out.data());
-
- if (out_scale < 0) {
- auto negative_scale =
DecimalScaleParams::get_scale_factor<Type>(-out_scale);
- while (p_in < end_in) {
- Op::compute(p_in, scale, p_out, negative_scale);
- ++p_in;
- ++p_out;
- }
- } else {
- while (p_in < end_in) {
- Op::compute(p_in, scale, p_out, 1);
- ++p_in;
- ++p_out;
- }
+ auto* __restrict p_out = reinterpret_cast<NativeType*>(out.data());
+
+ while (p_in < end_in) {
+ Op::compute(p_in, scale, p_out, target_scale);
+ ++p_in;
+ ++p_out;
}
} else {
memcpy(out.data(), in.data(), in.size() * sizeof(T));
@@ -205,16 +213,13 @@ public:
}
static NO_INLINE void apply(const NativeType& in, UInt32 in_scale,
NativeType& out,
- Int16 out_scale) {
- Int16 scale_arg = in_scale - out_scale;
+ Int16 out_scale, Int16 result_scale) {
+ Int32 scale_arg = static_cast<Int32>(in_scale) - out_scale;
if (scale_arg > 0) {
auto scale = DecimalScaleParams::get_scale_factor<Type>(scale_arg);
- if (out_scale < 0) {
- auto negative_scale =
DecimalScaleParams::get_scale_factor<Type>(-out_scale);
- Op::compute(&in, scale, &out, negative_scale);
- } else {
- Op::compute(&in, scale, &out, 1);
- }
+ auto target_scale =
+ DecimalScaleParams::get_scale_factor<Type>(result_scale -
out_scale);
+ Op::compute(&in, scale, &out, target_scale);
} else {
memcpy(&out, &in, sizeof(NativeType));
}
@@ -486,72 +491,27 @@ struct Dispatcher {
const auto* const decimal_col =
check_and_get_column<typename
PrimitiveTypeTraits<T>::ColumnType>(col_general);
const auto& vec_src = decimal_col->get_data();
- const size_t input_rows_count = vec_src.size();
auto col_res =
PrimitiveTypeTraits<T>::ColumnType::create(vec_src.size(), result_scale);
auto& vec_res = col_res->get_data();
if (!vec_res.empty()) {
- FunctionRoundingImpl<ScaleMode::Negative>::apply(
- decimal_col->get_data(), decimal_col->get_scale(),
vec_res, scale_arg);
- }
- // We need to always make sure result decimal's scale is as
expected as its in plan
- // So we need to append enough zero to result.
-
- // Case 0: scale_arg <= -(integer part digits count)
- // do nothing, because result is 0
- // Case 1: scale_arg <= 0 && scale_arg > -(integer part digits
count)
- // decimal parts has been erased, so add them back by
multiply 10^(result_scale)
- // Case 2: scale_arg > 0 && scale_arg < result_scale
- // decimal part now has scale_arg digits, so multiply
10^(result_scale - scal_arg)
- // Case 3: scale_arg >= input_scale
- // do nothing
-
- if (scale_arg <= 0) {
- for (size_t i = 0; i < input_rows_count; ++i) {
- vec_res[i] = DecimalV2Value(vec_res[i].value() *
int_exp10(result_scale));
- }
- } else if (scale_arg > 0 && scale_arg < result_scale) {
- for (size_t i = 0; i < input_rows_count; ++i) {
- vec_res[i] = DecimalV2Value(vec_res[i].value() *
- int_exp10(result_scale -
scale_arg));
- }
+
FunctionRoundingImpl<ScaleMode::Negative>::apply(decimal_col->get_data(),
+
decimal_col->get_scale(), vec_res,
+ scale_arg,
result_scale);
}
-
return col_res;
} else if constexpr (is_decimal(T)) {
const auto* const decimal_col =
check_and_get_column<typename
PrimitiveTypeTraits<T>::ColumnType>(col_general);
const auto& vec_src = decimal_col->get_data();
- const size_t input_rows_count = vec_src.size();
auto col_res =
PrimitiveTypeTraits<T>::ColumnType::create(vec_src.size(), result_scale);
auto& vec_res = col_res->get_data();
if (!vec_res.empty()) {
- FunctionRoundingImpl<ScaleMode::Negative>::apply(
- decimal_col->get_data(), decimal_col->get_scale(),
vec_res, scale_arg);
+
FunctionRoundingImpl<ScaleMode::Negative>::apply(decimal_col->get_data(),
+
decimal_col->get_scale(), vec_res,
+ scale_arg,
result_scale);
}
- // We need to always make sure result decimal's scale is as
expected as its in plan
- // So we need to append enough zero to result.
-
- // Case 0: scale_arg <= -(integer part digits count)
- // do nothing, because result is 0
- // Case 1: scale_arg <= 0 && scale_arg > -(integer part digits
count)
- // decimal parts has been erased, so add them back by
multiply 10^(result_scale)
- // Case 2: scale_arg > 0 && scale_arg < result_scale
- // decimal part now has scale_arg digits, so multiply
10^(result_scale - scal_arg)
- // Case 3: scale_arg >= input_scale
- // do nothing
-
- if (scale_arg <= 0) {
- for (size_t i = 0; i < input_rows_count; ++i) {
- vec_res[i].value *= int_exp10(result_scale);
- }
- } else if (scale_arg > 0 && scale_arg < result_scale) {
- for (size_t i = 0; i < input_rows_count; ++i) {
- vec_res[i].value *= int_exp10(result_scale - scale_arg);
- }
- }
-
return col_res;
} else {
static_assert(false);
@@ -607,29 +567,7 @@ struct Dispatcher {
for (size_t i = 0; i < input_row_count; ++i) {
DecimalRoundingImpl<T, rounding_mode,
tie_breaking_mode>::apply(
decimal_col->get_element(i).value(), input_scale,
- col_res->get_element(i).value(),
col_scale_i32.get_data()[i]);
- }
-
- for (size_t i = 0; i < input_row_count; ++i) {
- // For func(ColumnDecimal, ColumnInt32), we should always have
same scale with source Decimal column
- // So we need this check to make sure the result have correct
digits count
- //
- // Case 0: scale_arg <= -(integer part digits count)
- // do nothing, because result is 0
- // Case 1: scale_arg <= 0 && scale_arg > -(integer part digits
count)
- // decimal parts has been erased, so add them back by
multiply 10^(scale_arg)
- // Case 2: scale_arg > 0 && scale_arg < result_scale
- // decimal part now has scale_arg digits, so multiply
10^(result_scale - scal_arg)
- // Case 3: scale_arg >= input_scale
- // do nothing
- const Int32 scale_arg = col_scale_i32.get_data()[i];
- if (scale_arg <= 0) {
- col_res->get_element(i) =
DecimalV2Value(col_res->get_element(i).value() *
-
int_exp10(result_scale));
- } else if (scale_arg > 0 && scale_arg < result_scale) {
- col_res->get_element(i) =
DecimalV2Value(col_res->get_element(i).value() *
-
int_exp10(result_scale - scale_arg));
- }
+ col_res->get_element(i).value(),
col_scale_i32.get_data()[i], result_scale);
}
return col_res;
@@ -643,27 +581,7 @@ struct Dispatcher {
for (size_t i = 0; i < input_row_count; ++i) {
DecimalRoundingImpl<T, rounding_mode,
tie_breaking_mode>::apply(
decimal_col->get_element(i).value, input_scale,
- col_res->get_element(i).value,
col_scale_i32.get_data()[i]);
- }
-
- for (size_t i = 0; i < input_row_count; ++i) {
- // For func(ColumnDecimal, ColumnInt32), we should always have
same scale with source Decimal column
- // So we need this check to make sure the result have correct
digits count
- //
- // Case 0: scale_arg <= -(integer part digits count)
- // do nothing, because result is 0
- // Case 1: scale_arg <= 0 && scale_arg > -(integer part digits
count)
- // decimal parts has been erased, so add them back by
multiply 10^(scale_arg)
- // Case 2: scale_arg > 0 && scale_arg < result_scale
- // decimal part now has scale_arg digits, so multiply
10^(result_scale - scal_arg)
- // Case 3: scale_arg >= input_scale
- // do nothing
- const Int32 scale_arg = col_scale_i32.get_data()[i];
- if (scale_arg <= 0) {
- col_res->get_element(i).value *= int_exp10(result_scale);
- } else if (scale_arg > 0 && scale_arg < result_scale) {
- col_res->get_element(i).value *= int_exp10(result_scale -
scale_arg);
- }
+ col_res->get_element(i).value,
col_scale_i32.get_data()[i], result_scale);
}
return col_res;
@@ -701,29 +619,7 @@ struct Dispatcher {
for (size_t i = 0; i < input_rows_count; ++i) {
DecimalRoundingImpl<T, rounding_mode,
tie_breaking_mode>::apply(
general_val, input_scale,
col_res->get_element(i).value(),
- col_scale_i32.get_data()[i]);
- }
-
- for (size_t i = 0; i < input_rows_count; ++i) {
- // For func(ColumnDecimal, ColumnInt32), we should always have
same scale with source Decimal column
- // So we need this check to make sure the result have correct
digits count
- //
- // Case 0: scale_arg <= -(integer part digits count)
- // do nothing, because result is 0
- // Case 1: scale_arg <= 0 && scale_arg > -(integer part digits
count)
- // decimal parts has been erased, so add them back by
multiply 10^(scale_arg)
- // Case 2: scale_arg > 0 && scale_arg < result_scale
- // decimal part now has scale_arg digits, so multiply
10^(result_scale - scal_arg)
- // Case 3: scale_arg >= input_scale
- // do nothing
- const Int32 scale_arg = col_scale_i32.get_data()[i];
- if (scale_arg <= 0) {
- col_res->get_element(i) =
DecimalV2Value(col_res->get_element(i).value() *
-
int_exp10(result_scale));
- } else if (scale_arg > 0 && scale_arg < result_scale) {
- col_res->get_element(i) =
DecimalV2Value(col_res->get_element(i).value() *
-
int_exp10(result_scale - scale_arg));
- }
+ col_scale_i32.get_data()[i], result_scale);
}
return col_res;
@@ -739,27 +635,7 @@ struct Dispatcher {
for (size_t i = 0; i < input_rows_count; ++i) {
DecimalRoundingImpl<T, rounding_mode,
tie_breaking_mode>::apply(
general_val, input_scale,
col_res->get_element(i).value,
- col_scale_i32.get_data()[i]);
- }
-
- for (size_t i = 0; i < input_rows_count; ++i) {
- // For func(ColumnDecimal, ColumnInt32), we should always have
same scale with source Decimal column
- // So we need this check to make sure the result have correct
digits count
- //
- // Case 0: scale_arg <= -(integer part digits count)
- // do nothing, because result is 0
- // Case 1: scale_arg <= 0 && scale_arg > -(integer part digits
count)
- // decimal parts has been erased, so add them back by
multiply 10^(scale_arg)
- // Case 2: scale_arg > 0 && scale_arg < result_scale
- // decimal part now has scale_arg digits, so multiply
10^(result_scale - scal_arg)
- // Case 3: scale_arg >= input_scale
- // do nothing
- const Int32 scale_arg = col_scale_i32.get_data()[i];
- if (scale_arg <= 0) {
- col_res->get_element(i).value *= int_exp10(result_scale);
- } else if (scale_arg > 0 && scale_arg < result_scale) {
- col_res->get_element(i).value *= int_exp10(result_scale -
scale_arg);
- }
+ col_scale_i32.get_data()[i], result_scale);
}
return col_res;
diff --git a/be/test/exprs/function/function_round_test.cpp
b/be/test/exprs/function/function_round_test.cpp
index 1c6b8ab8385..deb2482fb9e 100644
--- a/be/test/exprs/function/function_round_test.cpp
+++ b/be/test/exprs/function/function_round_test.cpp
@@ -59,20 +59,33 @@ using Decimal32FloorFunction =
FunctionRounding<DecimalRoundTwoImpl<FloorName, T
RoundingMode::Floor,
TieBreakingMode::Auto>;
using Decimal64FloorFunction = FunctionRounding<DecimalRoundTwoImpl<FloorName,
TYPE_DECIMAL64>,
RoundingMode::Floor,
TieBreakingMode::Auto>;
+using Decimal128FloorFunction =
FunctionRounding<DecimalRoundTwoImpl<FloorName, TYPE_DECIMAL128I>,
+ RoundingMode::Floor,
TieBreakingMode::Auto>;
+using Decimal256FloorFunction =
FunctionRounding<DecimalRoundTwoImpl<FloorName, TYPE_DECIMAL256>,
+ RoundingMode::Floor,
TieBreakingMode::Auto>;
using Decimal32CeilFunction = FunctionRounding<DecimalRoundTwoImpl<CeilName,
TYPE_DECIMAL32>,
RoundingMode::Ceil,
TieBreakingMode::Auto>;
using Decimal64CeilFunction = FunctionRounding<DecimalRoundTwoImpl<CeilName,
TYPE_DECIMAL64>,
RoundingMode::Ceil,
TieBreakingMode::Auto>;
+using Decimal128CeilFunction = FunctionRounding<DecimalRoundTwoImpl<CeilName,
TYPE_DECIMAL128I>,
+ RoundingMode::Ceil,
TieBreakingMode::Auto>;
+using Decimal256CeilFunction = FunctionRounding<DecimalRoundTwoImpl<CeilName,
TYPE_DECIMAL256>,
+ RoundingMode::Ceil,
TieBreakingMode::Auto>;
using Decimal32RoundFunction = FunctionRounding<DecimalRoundTwoImpl<RoundName,
TYPE_DECIMAL32>,
RoundingMode::Round,
TieBreakingMode::Auto>;
using Decimal64RoundFunction = FunctionRounding<DecimalRoundTwoImpl<RoundName,
TYPE_DECIMAL64>,
RoundingMode::Round,
TieBreakingMode::Auto>;
+using Decimal128RoundFunction =
FunctionRounding<DecimalRoundTwoImpl<RoundName, TYPE_DECIMAL128I>,
+ RoundingMode::Round,
TieBreakingMode::Auto>;
using Decimal32RoundBankersFunction =
FunctionRounding<DecimalRoundTwoImpl<RoundBankersName,
TYPE_DECIMAL32>, RoundingMode::Round,
TieBreakingMode::Bankers>;
using Decimal64RoundBankersFunction =
FunctionRounding<DecimalRoundTwoImpl<RoundBankersName,
TYPE_DECIMAL64>, RoundingMode::Round,
TieBreakingMode::Bankers>;
+using Decimal128RoundBankersFunction =
+ FunctionRounding<DecimalRoundTwoImpl<RoundBankersName,
TYPE_DECIMAL128I>,
+ RoundingMode::Round, TieBreakingMode::Bankers>;
using FloatTruncateFunction =
FunctionRounding<DoubleRoundTwoImpl<TruncateName>,
RoundingMode::Trunc,
TieBreakingMode::Auto>;
@@ -1022,6 +1035,44 @@ static void decimal_checker(const DecimalTestDataSet&
round_test_cases, bool dec
}
}
+template <typename FuncType, typename DecimalType>
+static void check_decimal_rounding(typename DecimalType::NativeType input, int
input_precision,
+ int input_scale, int scale_arg, int
result_precision,
+ int result_scale, typename
DecimalType::NativeType expected,
+ bool decimal_col_is_const, bool
scale_col_is_const) {
+ auto func = std::dynamic_pointer_cast<FuncType>(FuncType::create());
+ auto col_general = ColumnDecimal<DecimalType::PType>::create(1,
input_scale);
+ col_general->get_element(0) = DecimalType(input);
+ auto col_scale = ColumnInt32::create();
+ col_scale->insert(Field::create_field<TYPE_INT>(scale_arg));
+
+ Block block;
+ auto input_type =
+
std::make_shared<DataTypeDecimal<DecimalType::PType>>(input_precision,
input_scale);
+ if (decimal_col_is_const) {
+ block.insert({ColumnConst::create(std::move(col_general), 1),
std::move(input_type),
+ "col_general"});
+ } else {
+ block.insert({std::move(col_general), std::move(input_type),
"col_general"});
+ }
+ if (scale_col_is_const) {
+ block.insert({ColumnConst::create(std::move(col_scale), 1),
+ std::make_shared<DataTypeInt32>(), "col_scale"});
+ } else {
+ block.insert({std::move(col_scale), std::make_shared<DataTypeInt32>(),
"col_scale"});
+ }
+ block.insert(
+ {nullptr,
+
std::make_shared<DataTypeDecimal<DecimalType::PType>>(result_precision,
result_scale),
+ "col_res"});
+
+ const ColumnNumbers arguments = {0, 1};
+ ASSERT_TRUE(func->execute_impl(nullptr, block, arguments, 2, 1).ok());
+ const auto& result =
+ assert_cast<const
ColumnDecimal<DecimalType::PType>&>(*block.get_by_position(2).column);
+ EXPECT_EQ(result.get_element(0).value, expected);
+}
+
template <typename FuncType, PrimitiveType FloatPType>
static void float_checker(const FloatTestDataSet& round_test_cases, bool
float_col_is_const) {
using FloatType = typename PrimitiveTypeTraits<FloatPType>::CppType;
@@ -1109,6 +1160,43 @@ TEST(RoundFunctionTest, normal_decimal_const) {
decimal_checker<Decimal64RoundBankersFunction,
Decimal64>(round_decimal64_cases, true);
}
+TEST(RoundFunctionTest, decimal_scale_boundaries) {
+ check_decimal_rounding<Decimal32CeilFunction, Decimal32>(1, 9, 9, -1, 9,
0, 10, false, true);
+ check_decimal_rounding<Decimal32FloorFunction, Decimal32>(-1, 9, 9, -1, 9,
0, -10, false, true);
+
+ const Int128 scale20 = common::exp10_i128(20);
+ check_decimal_rounding<Decimal128CeilFunction, Decimal128V3>(scale20 +
scale20 / 2, 38, 20, 0,
+ 38, 20,
scale20 * 2, false, false);
+ check_decimal_rounding<Decimal128FloorFunction, Decimal128V3>(scale20 +
scale20 / 2, 38, 20, 0,
+ 38, 20,
scale20, false, false);
+ check_decimal_rounding<Decimal128CeilFunction, Decimal128V3>(scale20 +
scale20 / 2, 38, 20, 0,
+ 38, 20,
scale20 * 2, true, false);
+ check_decimal_rounding<Decimal128FloorFunction, Decimal128V3>(scale20 +
scale20 / 2, 38, 20, 0,
+ 38, 20,
scale20, true, false);
+
+ const Int128 decimal128_fraction = common::exp10_i128(37) * 9;
+ check_decimal_rounding<Decimal128CeilFunction,
Decimal128V3>(decimal128_fraction, 38, 38, 0, 38,
+ 0, 1, false,
true);
+ check_decimal_rounding<Decimal128FloorFunction,
Decimal128V3>(-decimal128_fraction, 38, 38, 0,
+ 38, 0, -1,
false, true);
+
+ const Int128 decimal128_half = common::exp10_i128(37) * 5;
+ check_decimal_rounding<Decimal128RoundFunction,
Decimal128V3>(decimal128_half, 38, 38, 0, 38, 0,
+ 1, false,
true);
+ check_decimal_rounding<Decimal128RoundFunction,
Decimal128V3>(-decimal128_half, 38, 38, 0, 38,
+ 0, -1,
false, true);
+ check_decimal_rounding<Decimal128RoundBankersFunction,
Decimal128V3>(decimal128_half, 38, 38, 0,
+ 38,
0, 0, false, true);
+ check_decimal_rounding<Decimal128RoundBankersFunction,
Decimal128V3>(-decimal128_half, 38, 38,
+ 0,
38, 0, 0, false, true);
+
+ const wide::Int256 decimal256_fraction = common::exp10_i256(75) * 9;
+ check_decimal_rounding<Decimal256CeilFunction,
Decimal256>(decimal256_fraction, 76, 76, 0, 76,
+ 0, 1, false,
true);
+ check_decimal_rounding<Decimal256FloorFunction,
Decimal256>(-decimal256_fraction, 76, 76, 0, 76,
+ 0, -1, false,
true);
+}
+
/// tests for func(Column, Column) with float input
TEST(RoundFunctionTest, normal_float) {
float_checker<FloatTruncateFunction, TYPE_FLOAT>(trunc_float32_cases,
false);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]