diff --git a/cpp/src/gandiva/function_registry_math_ops.cc b/cpp/src/gandiva/function_registry_math_ops.cc index 722b908f2eb7a..b3201c1f888c5 100644 --- a/cpp/src/gandiva/function_registry_math_ops.cc +++ b/cpp/src/gandiva/function_registry_math_ops.cc @@ -64,6 +64,9 @@ std::vector GetMathOpsFunctionRegistry() { UNARY_SAFE_NULL_IF_NULL(abs, {}, float32, float32), UNARY_SAFE_NULL_IF_NULL(abs, {}, float64, float64), + BINARY_GENERIC_SAFE_NULL_IF_NULL(round, {}, float64, int32, float64), + BINARY_GENERIC_SAFE_NULL_IF_NULL(round, {}, float64, int64, float64), + // decimal functions UNARY_SAFE_NULL_IF_NULL(abs, {}, decimal128, decimal128), UNARY_SAFE_NULL_IF_NULL(ceil, {}, decimal128, decimal128), diff --git a/cpp/src/gandiva/precompiled/extended_math_ops.cc b/cpp/src/gandiva/precompiled/extended_math_ops.cc index 7f482f95b26b6..5ae431bc3fda0 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops.cc @@ -21,6 +21,7 @@ extern "C" { #include #include +#include #include #include #include "./types.h" @@ -90,6 +91,23 @@ ABS_TYPES_UNARY(int64, uint64) ABS_FTYPES_UNARY(float32, float32) ABS_FTYPES_UNARY(float64, float64) +// round +#define ROUND_TYPES_UNARY(IN_TYPE1, IN_TYPE2, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE round_##IN_TYPE1##_##IN_TYPE2(gdv_##IN_TYPE1 val, gdv_##IN_TYPE2 dp) { \ + int charsNeeded = 1 + snprintf(NULL, 0, "%.*f", (int) dp, val); \ + char* buffer = reinterpret_cast(malloc(charsNeeded)); \ + snprintf(buffer, charsNeeded, "%.*f", (int) dp, nextafter(val, val*2)); \ + double result = atof(buffer); \ + free(buffer); \ + return static_cast(result); \ + } + +ROUND_TYPES_UNARY(float64, int32, float64) +ROUND_TYPES_UNARY(float64, int64, float64) + +#undef ROUND_TYPES_UNARY + FORCE_INLINE void set_error_for_logbase(int64_t execution_context, double base) { char const* prefix = "divide by zero error with log of base"; diff --git a/cpp/src/gandiva/precompiled/extended_math_ops_test.cc b/cpp/src/gandiva/precompiled/extended_math_ops_test.cc index 67ee6f5b3124b..a487e6a477714 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops_test.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops_test.cc @@ -96,4 +96,11 @@ TEST(TestExtendedMathOps, TestTruncate) { EXPECT_EQ(truncate_int64_int32(8124674407369523212, -2), 8124674407369523200); } +TEST(TestExtendedMathOps, TestRound) { + EXPECT_EQ(round_float64_int32(1234.56789, 4), 1234.5679); + EXPECT_EQ(round_float64_int64(1234.56789, 4), 1234.5679); + EXPECT_EQ(round_float64_int32(-1234.56789, 4), -1234.5679); + EXPECT_EQ(round_float64_int64(-1234.56789, 4), -1234.5679); +} + } // namespace gandiva diff --git a/cpp/src/gandiva/precompiled/types.h b/cpp/src/gandiva/precompiled/types.h index ee03b227e07c5..9e9343284d4f2 100644 --- a/cpp/src/gandiva/precompiled/types.h +++ b/cpp/src/gandiva/precompiled/types.h @@ -157,6 +157,9 @@ gdv_uint64 abs_int64(gdv_int64); gdv_float32 abs_float32(gdv_float32); gdv_float64 abs_float64(gdv_float64); +gdv_float64 round_float64_int32(gdv_float64 in1, gdv_int32 in2); +gdv_float64 round_float64_int64(gdv_float64 in1, gdv_int64 in2); + gdv_int32 bitwise_and_int32_int32(gdv_int32 in1, gdv_int32 in2); gdv_int64 bitwise_and_int64_int64(gdv_int64 in1, gdv_int64 in2); gdv_int32 bitwise_or_int32_int32(gdv_int32 in1, gdv_int32 in2);