This is an automated email from the ASF dual-hosted git repository. ravindra pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push: new f0e1a4f ARROW-14315: [C++][Gandiva] Implement BROUND function f0e1a4f is described below commit f0e1a4f043bb0e8e0ac84467edd94f7ffa2b8ddc Author: Augusto Silva <augusto.a.si...@hotmail.com> AuthorDate: Mon Nov 15 17:21:13 2021 +0530 ARROW-14315: [C++][Gandiva] Implement BROUND function Returns the rounded BIGINT value of a using HALF_EVEN rounding mode. Also known as Gaussian rounding or bankers' rounding. Closes #11415 from augustoasilva/feature/implement-bround-function Authored-by: Augusto Silva <augusto.a.si...@hotmail.com> Signed-off-by: Pindikura Ravindra <ravin...@dremio.com> --- cpp/src/gandiva/function_registry_arithmetic.cc | 4 +++ cpp/src/gandiva/precompiled/extended_math_ops.cc | 16 ++++++++++ .../gandiva/precompiled/extended_math_ops_test.cc | 18 +++++++++++ cpp/src/gandiva/precompiled/types.h | 1 + cpp/src/gandiva/tests/projector_test.cc | 37 ++++++++++++++++++++++ 5 files changed, 76 insertions(+) diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc b/cpp/src/gandiva/function_registry_arithmetic.cc index f34289f..3901407 100644 --- a/cpp/src/gandiva/function_registry_arithmetic.cc +++ b/cpp/src/gandiva/function_registry_arithmetic.cc @@ -107,6 +107,10 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() { BINARY_GENERIC_SAFE_NULL_IF_NULL(round, {}, int32, int32, int32), BINARY_GENERIC_SAFE_NULL_IF_NULL(round, {}, int64, int32, int64), + // bround functions + NativeFunction("bround", {}, DataTypeVector{float64()}, float64(), + kResultNullIfNull, "bround_float64"), + // compare functions BINARY_RELATIONAL_BOOL_FN(equal, ({"eq", "same"})), BINARY_RELATIONAL_BOOL_FN(not_equal, {}), diff --git a/cpp/src/gandiva/precompiled/extended_math_ops.cc b/cpp/src/gandiva/precompiled/extended_math_ops.cc index 365b08a..c233197 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops.cc @@ -28,6 +28,7 @@ extern "C" { #include <stdio.h> #include <stdlib.h> #include <string.h> + #include "./types.h" // Expand the inner fn for types that support extended math. @@ -236,6 +237,21 @@ gdv_int64 round_int64(gdv_int64 num) { return num; } ROUND_DECIMAL(float32) ROUND_DECIMAL(float64) +// rounds the number to the nearest integer +FORCE_INLINE +gdv_float64 bround_float64(gdv_float64 num) { + gdv_float64 round_num = round(num); + gdv_float64 diff_num = round_num - num; + if ((diff_num != 0.5) && (diff_num != -0.5)) { + return round_num; + } + if (fmod(round_num, 2.0) == 0.0) { + return round_num; + } + + return num - diff_num; +} + // rounds the number to the given scale #define ROUND_DECIMAL_TO_SCALE(TYPE) \ FORCE_INLINE \ diff --git a/cpp/src/gandiva/precompiled/extended_math_ops_test.cc b/cpp/src/gandiva/precompiled/extended_math_ops_test.cc index 147b403..9d84734 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops_test.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops_test.cc @@ -120,6 +120,24 @@ TEST(TestExtendedMathOps, TestRoundDecimal) { VerifyFuzzyEquals(round_float64_int32((double)INT_MIN - 1, 0), (double)INT_MIN - 1); } +TEST(TestExtendedMathOps, TestBRoundDecimal) { + EXPECT_DOUBLE_EQ(bround_float64(0.0), 0); + EXPECT_DOUBLE_EQ(bround_float64(2.5), 2); + EXPECT_DOUBLE_EQ(bround_float64(3.5), 4); + EXPECT_DOUBLE_EQ(bround_float64(-2.5), -2); + EXPECT_DOUBLE_EQ(bround_float64(-3.5), -4); + EXPECT_DOUBLE_EQ(bround_float64(1.4999999), 1); + EXPECT_DOUBLE_EQ(bround_float64(1.50001), 2); + EXPECT_EQ(std::signbit(bround_float64(0)), 0); + + VerifyFuzzyEquals(bround_float64(2.5), 2); + VerifyFuzzyEquals(bround_float64(3.5), 4); + VerifyFuzzyEquals(bround_float64(-2.5), -2); + VerifyFuzzyEquals(bround_float64(-3.5), -4); + VerifyFuzzyEquals(bround_float64(1.4999999), 1); + VerifyFuzzyEquals(bround_float64(1.50001), 2); +} + TEST(TestExtendedMathOps, TestRound) { EXPECT_EQ(round_int32(21134), 21134); EXPECT_EQ(round_int32(-132422), -132422); diff --git a/cpp/src/gandiva/precompiled/types.h b/cpp/src/gandiva/precompiled/types.h index 987ee2c..2e6e9c6 100644 --- a/cpp/src/gandiva/precompiled/types.h +++ b/cpp/src/gandiva/precompiled/types.h @@ -167,6 +167,7 @@ gdv_float64 div_float64_float64(gdv_int64 context, gdv_float64 in1, gdv_float64 gdv_float32 round_float32(gdv_float32); gdv_float64 round_float64(gdv_float64); +gdv_float64 bround_float64(gdv_float64); gdv_float32 round_float32_int32(gdv_float32 number, gdv_int32 out_scale); gdv_float64 round_float64_int32(gdv_float64 number, gdv_int32 out_scale); gdv_float64 get_scale_multiplier(gdv_int32); diff --git a/cpp/src/gandiva/tests/projector_test.cc b/cpp/src/gandiva/tests/projector_test.cc index 1202077..dea66a7 100644 --- a/cpp/src/gandiva/tests/projector_test.cc +++ b/cpp/src/gandiva/tests/projector_test.cc @@ -1606,4 +1606,41 @@ TEST_F(TestProjector, TestCastNullableIntYearInterval) { EXPECT_ARROW_ARRAY_EQUALS(out_int64, outputs.at(1)); } +TEST_F(TestProjector, TestBround) { + // schema for input fields + auto field0 = field("f0", arrow::float64()); + + auto schema_bround = arrow::schema({field0}); + + // output fields + auto field_bround = field("bround", arrow::float64()); + + // Build expression + auto bround_expr = TreeExprBuilder::MakeExpression("bround", {field0}, field_bround); + + std::shared_ptr<Projector> projector; + auto status = + Projector::Make(schema_bround, {bround_expr}, TestConfiguration(), &projector); + + EXPECT_TRUE(status.ok()) << status.message(); + + // Create a row-batch with some sample data + int num_records = 4; + auto array0 = + MakeArrowArrayFloat64({0.0, 2.5, -3.5, 1.499999}, {true, true, true, true}); + // expected output + auto exp_bround = MakeArrowArrayFloat64({0, 2, -4, 1}, {true, true, true, true}); + + // prepare input record batch + auto in_batch = arrow::RecordBatch::Make(schema_bround, num_records, {array0}); + + // Evaluate expression + arrow::ArrayVector outputs; + status = projector->Evaluate(*in_batch, pool_, &outputs); + EXPECT_TRUE(status.ok()) << status.message(); + + // Validate results + EXPECT_ARROW_ARRAY_EQUALS(exp_bround, outputs.at(0)); +} + } // namespace gandiva