You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ra...@apache.org on 2021/11/15 11:52:46 UTC
[arrow] branch master updated: ARROW-14315: [C++][Gandiva] Implement BROUND function
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 <au...@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 <au...@hotmail.com>
Signed-off-by: Pindikura Ravindra <ra...@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