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 2022/04/26 11:02:18 UTC
[arrow] branch master updated: ARROW-15940: [Gandiva][C++] Add NEGATIVE function for decimal data type
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 3e56a949c7 ARROW-15940: [Gandiva][C++] Add NEGATIVE function for decimal data type
3e56a949c7 is described below
commit 3e56a949c73168d789612a9022cdceae6088e2b7
Author: Johnnathan <jo...@gmail.com>
AuthorDate: Tue Apr 26 16:32:01 2022 +0530
ARROW-15940: [Gandiva][C++] Add NEGATIVE function for decimal data type
This PR implements the NEGATIVE function for decimal data type.
The function receive a decimal128() and return a negative decimal128().
Closes #12581 from Johnnathanalmeida/feature/negative-function-for-decimal
Authored-by: Johnnathan <jo...@gmail.com>
Signed-off-by: Pindikura Ravindra <ra...@dremio.com>
---
cpp/src/gandiva/function_registry_arithmetic.cc | 4 ++
cpp/src/gandiva/precompiled/arithmetic_ops.cc | 11 ++++
cpp/src/gandiva/precompiled/arithmetic_ops_test.cc | 60 ++++++++++++++++++++++
cpp/src/gandiva/precompiled/types.h | 4 ++
cpp/src/gandiva/tests/decimal_test.cc | 45 ++++++++++++++++
5 files changed, 124 insertions(+)
diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc b/cpp/src/gandiva/function_registry_arithmetic.cc
index 5baf84bfd8..6d10fd920d 100644
--- a/cpp/src/gandiva/function_registry_arithmetic.cc
+++ b/cpp/src/gandiva/function_registry_arithmetic.cc
@@ -176,6 +176,10 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
"negative_int64",
NativeFunction::kNeedsContext | NativeFunction::kCanReturnErrors),
+ NativeFunction("negative", {}, DataTypeVector{decimal128()}, decimal128(),
+ kResultNullIfNull, "negative_decimal",
+ NativeFunction::kNeedsContext | NativeFunction::kCanReturnErrors),
+
// compare functions
BINARY_RELATIONAL_BOOL_FN(equal, ({"eq", "same"})),
BINARY_RELATIONAL_BOOL_FN(not_equal, {}),
diff --git a/cpp/src/gandiva/precompiled/arithmetic_ops.cc b/cpp/src/gandiva/precompiled/arithmetic_ops.cc
index ccc09ab873..3fdc4d0b6a 100644
--- a/cpp/src/gandiva/precompiled/arithmetic_ops.cc
+++ b/cpp/src/gandiva/precompiled/arithmetic_ops.cc
@@ -17,6 +17,7 @@
#include <cmath>
#include <cstdint>
+#include "arrow/util/basic_decimal.h"
extern "C" {
@@ -389,6 +390,16 @@ NEGATIVE_INTEGER(int64, 64)
#undef NEGATIVE
#undef NEGATIVE_INTEGER
+void negative_decimal(gdv_int64 context, int64_t high_bits, uint64_t low_bits,
+ int32_t /*precision*/, int32_t /*scale*/, int32_t /*out_precision*/,
+ int32_t /*out_scale*/, int64_t* out_high_bits,
+ uint64_t* out_low_bits) {
+ arrow::BasicDecimal128 res = arrow::BasicDecimal128(high_bits, low_bits).Negate();
+
+ *out_high_bits = res.high_bits();
+ *out_low_bits = res.low_bits();
+}
+
#define DIV(TYPE) \
FORCE_INLINE \
gdv_##TYPE div_##TYPE##_##TYPE(gdv_int64 context, gdv_##TYPE in1, gdv_##TYPE in2) { \
diff --git a/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc b/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
index 91a1ae7f70..1cca0cb9c4 100644
--- a/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
+++ b/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
@@ -21,6 +21,9 @@
#include <cstdint>
#include "../execution_context.h"
+#include "arrow/testing/gtest_util.h"
+#include "arrow/util/decimal.h"
+#include "gandiva/decimal_scalar.h"
#include "gandiva/precompiled/types.h"
namespace gandiva {
@@ -80,6 +83,63 @@ TEST(TestArithmeticOps, TestMod) {
EXPECT_FALSE(context.has_error());
}
+TEST(TestArithmeticOps, TestNegativeDecimal) {
+ gandiva::ExecutionContext ctx;
+ int64_t ctx_ptr = reinterpret_cast<int64_t>(&ctx);
+
+ int64_t out_high_bits = 0;
+ uint64_t out_low_bits = 0;
+
+ arrow::Decimal128 input_decimal("-10.5");
+ negative_decimal(ctx_ptr, input_decimal.high_bits(), input_decimal.low_bits(), 3, 1, 3,
+ 1, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal("10.5");
+ EXPECT_EQ(output_decimal.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal.low_bits(), out_low_bits);
+
+ arrow::Decimal128 input_decimal2("10.5");
+ negative_decimal(ctx_ptr, input_decimal2.high_bits(), input_decimal2.low_bits(), 3, 1,
+ 3, 1, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal2("-10.5");
+ EXPECT_EQ(output_decimal2.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal2.low_bits(), out_low_bits);
+
+ arrow::Decimal128 input_decimal3("-23049223942343.532412");
+ negative_decimal(ctx_ptr, input_decimal3.high_bits(), input_decimal3.low_bits(), 20, 6,
+ 20, 6, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal3("23049223942343.532412");
+ EXPECT_EQ(output_decimal3.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal3.low_bits(), out_low_bits);
+
+ arrow::Decimal128 input_decimal4("15.001");
+ negative_decimal(ctx_ptr, input_decimal4.high_bits(), input_decimal4.low_bits(), 2, 3,
+ 2, 3, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal4("-15.001");
+ EXPECT_EQ(output_decimal4.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal4.low_bits(), out_low_bits);
+
+ arrow::Decimal128 input_decimal5("17");
+ negative_decimal(ctx_ptr, input_decimal5.high_bits(), input_decimal5.low_bits(), 2, 0,
+ 2, 0, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal5("-17");
+ EXPECT_EQ(output_decimal5.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal5.low_bits(), out_low_bits);
+
+ arrow::Decimal128 input_decimal6("-99917");
+ negative_decimal(ctx_ptr, input_decimal6.high_bits(), input_decimal6.low_bits(), 5, 0,
+ 5, 0, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal6("99917");
+ EXPECT_EQ(output_decimal6.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal6.low_bits(), out_low_bits);
+
+ arrow::Decimal128 input_decimal7("0.99917");
+ negative_decimal(ctx_ptr, input_decimal7.high_bits(), input_decimal7.low_bits(), 0, 5,
+ 0, 5, &out_high_bits, &out_low_bits);
+ arrow::Decimal128 output_decimal7("-0.99917");
+ EXPECT_EQ(output_decimal7.high_bits(), out_high_bits);
+ EXPECT_EQ(output_decimal7.low_bits(), out_low_bits);
+}
+
TEST(TestArithmeticOps, TestPositiveNegative) {
EXPECT_EQ(positive_int32(10), 10);
EXPECT_EQ(positive_int64(1000), 1000);
diff --git a/cpp/src/gandiva/precompiled/types.h b/cpp/src/gandiva/precompiled/types.h
index 1f1e42deb6..f3bd51ae80 100644
--- a/cpp/src/gandiva/precompiled/types.h
+++ b/cpp/src/gandiva/precompiled/types.h
@@ -207,6 +207,10 @@ gdv_float32 positive_float32(gdv_float32 in);
gdv_float64 positive_float64(gdv_float64 in);
gdv_float32 negative_float32(gdv_float32 in);
gdv_float64 negative_float64(gdv_float64 in);
+void negative_decimal(gdv_int64 context, int64_t high_bits, uint64_t low_bits,
+ int32_t /*precision*/, int32_t /*scale*/, int32_t /*out_precision*/,
+ int32_t /*out_scale*/, int64_t* out_high_bits,
+ uint64_t* out_low_bits);
gdv_int64 divide_int64_int64(gdv_int64 context, gdv_int64 in1, gdv_int64 in2);
diff --git a/cpp/src/gandiva/tests/decimal_test.cc b/cpp/src/gandiva/tests/decimal_test.cc
index 31f2dedf5c..1924f5b408 100644
--- a/cpp/src/gandiva/tests/decimal_test.cc
+++ b/cpp/src/gandiva/tests/decimal_test.cc
@@ -301,6 +301,51 @@ TEST_F(TestDecimal, TestCompare) {
outputs[5]); // greater_than_or_equal_to
}
+TEST_F(TestDecimal, TestNegative) {
+ // schema for input fields
+ constexpr int32_t precision = 3;
+ constexpr int32_t scale = 1;
+
+ auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale);
+
+ auto field_a = field("a", decimal_type);
+ auto schema = arrow::schema({field_a});
+
+ // build expressions
+ auto exprs = std::vector<ExpressionPtr>{
+ TreeExprBuilder::MakeExpression("negative", {field_a},
+ field("res_negative", decimal_type)),
+ };
+
+ // Build a projector for the expression.
+ std::shared_ptr<Projector> projector;
+ auto status = Projector::Make(schema, exprs, TestConfiguration(), &projector);
+ DCHECK_OK(status);
+
+ // Create a row-batch with some sample data
+ int num_records = 4;
+ auto validity = {true, true, true, true};
+ auto array_a = MakeArrowArrayDecimal(
+ decimal_type, MakeDecimalVector({"10.5", "-10.5", "-50.2", "50.2"}, scale),
+ validity);
+
+ // prepare input record batch
+ auto in_batch = arrow::RecordBatch::Make(schema, num_records, {array_a});
+
+ // Evaluate expression
+ arrow::ArrayVector outputs;
+ status = projector->Evaluate(*in_batch, pool_, &outputs);
+ DCHECK_OK(status);
+
+ // Validate results
+ // negative(x)
+ EXPECT_ARROW_ARRAY_EQUALS(
+ MakeArrowArrayDecimal(decimal_type,
+ MakeDecimalVector({"-10.5", "10.5", "50.2", "-50.2"}, scale),
+ validity),
+ outputs[0]);
+}
+
// ARROW-9092: This test is conditionally disabled when building with LLVM 9
// because it hangs.
#if GANDIVA_LLVM_VERSION != 9