diff --git a/extensions/functions_rounding_decimal.yaml b/extensions/functions_rounding_decimal.yaml new file mode 100644 index 000000000..125ca56a7 --- /dev/null +++ b/extensions/functions_rounding_decimal.yaml @@ -0,0 +1,80 @@ +%YAML 1.2 +--- +scalar_functions: + - + name: "ceil" + description: > + Rounding to the ceiling of the value `x`. + impls: + - args: + - value: decimal + name: x + return: |- + integral_least_num_digits = P - S + 1 + precision = min(integral_least_num_digits, 38) + decimal? + - + name: "floor" + description: > + Rounding to the floor of the value `x`. + impls: + - args: + - value: decimal + name: x + return: |- + integral_least_num_digits = P - S + 1 + precision = min(integral_least_num_digits, 38) + decimal? + - + name: "round" + description: > + Rounding the value `x` to `s` decimal places. + impls: + - args: + - value: decimal + name: x + description: > + Numerical expression to be rounded. + - value: i32 + name: s + description: > + Number of decimal places to be rounded to. + + When `s` is a positive number, the rounding + is performed to a `s` number of decimal places. + + When `s` is a negative number, the rounding is + performed to the left side of the decimal point + as specified by `s`. + + The precision and scale of the resultant decimal + type will be adjusted from the input decimal type + dependent on the value of `s`. + options: + rounding: + description: > + When a boundary is computed to lie somewhere between two values, + and this value cannot be exactly represented, this specifies how + to round it. + + - TIE_TO_EVEN: round to nearest value; if exactly halfway, tie + to the even option. + - TIE_AWAY_FROM_ZERO: round to nearest value; if exactly + halfway, tie away from zero. + - TRUNCATE: always round toward zero. + - CEILING: always round toward positive infinity. + - FLOOR: always round toward negative infinity. + - AWAY_FROM_ZERO: round negative values with FLOOR rule, round positive values with CEILING rule + - TIE_DOWN: round ties with FLOOR rule + - TIE_UP: round ties with CEILING rule + - TIE_TOWARDS_ZERO: round ties with TRUNCATE rule + - TIE_TO_ODD: round to nearest value; if exactly halfway, tie + to the odd option. + values: [ TIE_TO_EVEN, TIE_AWAY_FROM_ZERO, TRUNCATE, CEILING, FLOOR, + AWAY_FROM_ZERO, TIE_DOWN, TIE_UP, TIE_TOWARDS_ZERO, TIE_TO_ODD ] + nullability: DECLARED_OUTPUT + return: |- + integral_digits = P1 - S1 + 1 + scale = s > 0 ? min(s, S1) : 0 + precision = s > 0 ? min(integral_digits + scale, 38) : min(max(integral_num_digits, 1- s), 38) + decimal? diff --git a/tests/cases/rounding_decimal/ceil_decimal.test b/tests/cases/rounding_decimal/ceil_decimal.test new file mode 100644 index 000000000..bbcf14dc4 --- /dev/null +++ b/tests/cases/rounding_decimal/ceil_decimal.test @@ -0,0 +1,7 @@ +### SUBSTRAIT_SCALAR_TEST: v1.0 +### SUBSTRAIT_INCLUDE: '/extensions/functions_rounding_decimal.yaml' + +# basic: Basic examples without any special cases +ceil(2.25::dec<8,2>) = 3::dec<7,0> +ceil(-65.5::dec<8,2>) = -65::dec<7,0> +ceil(9.9::dec<2,1>) = 10::dec<2,0> diff --git a/tests/cases/rounding_decimal/floor_decimal.test b/tests/cases/rounding_decimal/floor_decimal.test new file mode 100644 index 000000000..d37e0e175 --- /dev/null +++ b/tests/cases/rounding_decimal/floor_decimal.test @@ -0,0 +1,6 @@ +### SUBSTRAIT_SCALAR_TEST: v1.0 +### SUBSTRAIT_INCLUDE: '/extensions/functions_rounding_decimal.yaml' + +# basic: Basic examples without any special cases +floor(2.25::dec<8,2>) = 2::dec<7,0> +floor(-65.5::dec<8,2>) = -66::dec<7,0> diff --git a/tests/cases/rounding_decimal/round_decimal.test b/tests/cases/rounding_decimal/round_decimal.test new file mode 100644 index 000000000..38da8f5c4 --- /dev/null +++ b/tests/cases/rounding_decimal/round_decimal.test @@ -0,0 +1,11 @@ +### SUBSTRAIT_SCALAR_TEST: v1.0 +### SUBSTRAIT_INCLUDE: '/extensions/functions_rounding_decimal.yaml' + +# basic: Basic examples without any special cases +round(2::dec<2,0>, 2::i32) = 2::dec<3,0> +round(2.75::dec<8,2>, 1::i32) = 2.8::dec<8,1> + +# negative_rounding: Examples with negative rounding +round(2::dec<2,0>, -2::i32) = 0::dec<2,0> +round(123::dec<2,0>, -2::i32) = 100::dec<2,0> +round(8793::dec<2,0>, -2::i32) = 8800::dec<2,0>