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 dc2f678  ARROW-13375: [C++][Gandiva] Implement POSITIVE and NEGATIVE 
Hive functions on Gandiva
dc2f678 is described below

commit dc2f678797d70ce990d4d73551ee573965dd38aa
Author: João Pedro <jo...@simbioseventures.com>
AuthorDate: Sun Feb 6 11:38:34 2022 +0530

    ARROW-13375: [C++][Gandiva] Implement POSITIVE and NEGATIVE Hive functions 
on Gandiva
    
     Implement POSITIVE and NEGATIVE Hive functions on Gandiva
    
    Closes #10742 from jpedroantunes/feature/positive-negative
    
    Authored-by: João Pedro <jo...@simbioseventures.com>
    Signed-off-by: Pindikura Ravindra <ravin...@dremio.com>
---
 cpp/src/gandiva/function_registry_arithmetic.cc    | 17 ++++++
 cpp/src/gandiva/gdv_function_stubs_test.cc         |  2 +-
 cpp/src/gandiva/precompiled/arithmetic_ops.cc      | 41 +++++++++++++--
 cpp/src/gandiva/precompiled/arithmetic_ops_test.cc | 42 +++++++++++++++
 cpp/src/gandiva/precompiled/types.h                |  9 ++++
 cpp/src/gandiva/tests/projector_test.cc            | 60 ++++++++++++++++++++++
 6 files changed, 167 insertions(+), 4 deletions(-)

diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc 
b/cpp/src/gandiva/function_registry_arithmetic.cc
index 4dc478f..983f7fe 100644
--- a/cpp/src/gandiva/function_registry_arithmetic.cc
+++ b/cpp/src/gandiva/function_registry_arithmetic.cc
@@ -16,6 +16,7 @@
 // under the License.
 
 #include "gandiva/function_registry_arithmetic.h"
+
 #include "gandiva/function_registry_common.h"
 
 namespace gandiva {
@@ -159,6 +160,22 @@ std::vector<NativeFunction> 
GetArithmeticFunctionRegistry() {
       NativeFunction("bround", {}, DataTypeVector{float64()}, float64(),
                      kResultNullIfNull, "bround_float64"),
 
+      // positive and negative functions
+      UNARY_SAFE_NULL_IF_NULL(positive, {}, int32, int32),
+      UNARY_SAFE_NULL_IF_NULL(positive, {}, int64, int64),
+      UNARY_SAFE_NULL_IF_NULL(positive, {}, float32, float32),
+      UNARY_SAFE_NULL_IF_NULL(positive, {}, float64, float64),
+      UNARY_SAFE_NULL_IF_NULL(negative, {}, float32, float32),
+      UNARY_SAFE_NULL_IF_NULL(negative, {}, float64, float64),
+
+      NativeFunction("negative", {}, DataTypeVector{int32()}, int32(), 
kResultNullIfNull,
+                     "negative_int32",
+                     NativeFunction::kNeedsContext | 
NativeFunction::kCanReturnErrors),
+
+      NativeFunction("negative", {}, DataTypeVector{int64()}, int64(), 
kResultNullIfNull,
+                     "negative_int64",
+                     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/gdv_function_stubs_test.cc 
b/cpp/src/gandiva/gdv_function_stubs_test.cc
index 2288867..c0b938c 100644
--- a/cpp/src/gandiva/gdv_function_stubs_test.cc
+++ b/cpp/src/gandiva/gdv_function_stubs_test.cc
@@ -20,8 +20,8 @@
 #include <gandiva/precompiled/testing.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include "arrow/util/logging.h"
 
+#include "arrow/util/logging.h"
 #include "gandiva/execution_context.h"
 
 namespace gandiva {
diff --git a/cpp/src/gandiva/precompiled/arithmetic_ops.cc 
b/cpp/src/gandiva/precompiled/arithmetic_ops.cc
index b272cfc..3bae866 100644
--- a/cpp/src/gandiva/precompiled/arithmetic_ops.cc
+++ b/cpp/src/gandiva/precompiled/arithmetic_ops.cc
@@ -15,9 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include <cmath>
+#include <cstdint>
+
 extern "C" {
 
-#include <math.h>
 #include "./types.h"
 
 // Expand inner macro for all numeric types.
@@ -246,6 +248,10 @@ IS_TRUE_OR_FALSE_BOOL(isfalse, boolean, !)
 NUMERIC_TYPES(IS_TRUE_OR_FALSE_NUMERIC, istrue, +)
 NUMERIC_TYPES(IS_TRUE_OR_FALSE_NUMERIC, isfalse, !)
 
+#define NUMERIC_FUNCTION_FOR_REAL(INNER) \
+  INNER(float32)                         \
+  INNER(float64)
+
 #define NUMERIC_FUNCTION(INNER) \
   INNER(int8)                   \
   INNER(int16)                  \
@@ -255,8 +261,7 @@ NUMERIC_TYPES(IS_TRUE_OR_FALSE_NUMERIC, isfalse, !)
   INNER(uint16)                 \
   INNER(uint32)                 \
   INNER(uint64)                 \
-  INNER(float32)                \
-  INNER(float64)
+  NUMERIC_FUNCTION_FOR_REAL(INNER)
 
 #define DATE_FUNCTION(INNER) \
   INNER(date32)              \
@@ -332,6 +337,36 @@ NUMERIC_FUNCTION(DIVIDE)
 
 #undef DIVIDE
 
+#define POSITIVE(TYPE) \
+  FORCE_INLINE         \
+  gdv_##TYPE positive_##TYPE(gdv_##TYPE in) { return in; }
+
+NUMERIC_FUNCTION(POSITIVE)
+
+#undef POSITIVE
+
+#define NEGATIVE(TYPE) \
+  FORCE_INLINE         \
+  gdv_##TYPE negative_##TYPE(gdv_##TYPE in) { return 
static_cast<gdv_##TYPE>(-1 * in); }
+
+NUMERIC_FUNCTION_FOR_REAL(NEGATIVE)
+
+#define NEGATIVE_INTEGER(TYPE, SIZE)                                           
\
+  FORCE_INLINE                                                                 
\
+  gdv_##TYPE negative_##TYPE(gdv_int64 context, gdv_##TYPE in) {               
\
+    if (in <= INT##SIZE##_MIN) {                                               
\
+      gdv_fn_context_set_error_msg(context, "Overflow in negative execution"); 
\
+      return 0;                                                                
\
+    }                                                                          
\
+    return -1 * in;                                                            
\
+  }
+
+NEGATIVE_INTEGER(int32, 32)
+NEGATIVE_INTEGER(int64, 64)
+
+#undef NEGATIVE
+#undef NEGATIVE_INTEGER
+
 #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 f8448d8..4f40f2f 100644
--- a/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
+++ b/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
@@ -17,6 +17,9 @@
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+
+#include <cstdint>
+
 #include "../execution_context.h"
 #include "gandiva/precompiled/types.h"
 
@@ -77,6 +80,45 @@ TEST(TestArithmeticOps, TestMod) {
   EXPECT_FALSE(context.has_error());
 }
 
+TEST(TestArithmeticOps, TestPositiveNegative) {
+  EXPECT_EQ(positive_int32(10), 10);
+  EXPECT_EQ(positive_int64(1000), 1000);
+  EXPECT_EQ(positive_float32(1.500f), 1.500f);
+  EXPECT_EQ(positive_float64(10.500f), 10.500f);
+
+  EXPECT_EQ(negative_float32(1.500f), -1.500f);
+  EXPECT_EQ(negative_float64(10.500f), -10.500f);
+
+  EXPECT_EQ(positive_int32(-10), -10);
+  EXPECT_EQ(positive_int64(-1000), -1000);
+  EXPECT_EQ(positive_float32(-1.500f), -1.500f);
+  EXPECT_EQ(positive_float64(-10.500f), -10.500f);
+
+  EXPECT_EQ(negative_float32(-1.500f), 1.500f);
+  EXPECT_EQ(negative_float64(-10.500f), 10.500f);
+
+  gandiva::ExecutionContext ctx;
+
+  int64_t ctx_ptr = reinterpret_cast<int64_t>(&ctx);
+
+  EXPECT_EQ(negative_int32(ctx_ptr, 100), -100);
+  EXPECT_EQ(negative_int32(ctx_ptr, -100), 100);
+
+  EXPECT_EQ(negative_int64(ctx_ptr, 100L), -100L);
+  EXPECT_EQ(negative_int64(ctx_ptr, -100L), 100L);
+
+  EXPECT_EQ(negative_int32(ctx_ptr, (INT32_MIN + 1)), (INT32_MAX));
+  EXPECT_EQ(negative_int64(ctx_ptr, (INT64_MIN + 1)), (INT64_MAX));
+
+  negative_int32(ctx_ptr, INT32_MIN);
+  EXPECT_THAT(ctx.get_error(), ::testing::HasSubstr("Overflow in negative 
execution"));
+  ctx.Reset();
+
+  negative_int64(ctx_ptr, INT64_MIN);
+  EXPECT_THAT(ctx.get_error(), ::testing::HasSubstr("Overflow in negative 
execution"));
+  ctx.Reset();
+}
+
 TEST(TestArithmeticOps, TestDivide) {
   gandiva::ExecutionContext context;
   EXPECT_EQ(divide_int64_int64(reinterpret_cast<gdv_int64>(&context), 10, 0), 
0);
diff --git a/cpp/src/gandiva/precompiled/types.h 
b/cpp/src/gandiva/precompiled/types.h
index e29e782..e08dacd 100644
--- a/cpp/src/gandiva/precompiled/types.h
+++ b/cpp/src/gandiva/precompiled/types.h
@@ -185,6 +185,15 @@ gdv_float64 mod_float64_float64(gdv_int64 context, 
gdv_float64 left, gdv_float64
 
 gdv_int64 pmod_int64_int64(int64_t context, gdv_int64 left, gdv_int64 right);
 
+gdv_int32 positive_int32(gdv_int32 in);
+gdv_int64 positive_int64(gdv_int64 in);
+gdv_int32 negative_int32(gdv_int64 context, gdv_int32 in);
+gdv_int64 negative_int64(gdv_int64 context, gdv_int64 in);
+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);
+
 gdv_int64 divide_int64_int64(gdv_int64 context, gdv_int64 in1, gdv_int64 in2);
 
 gdv_int64 div_int64_int64(gdv_int64 context, gdv_int64 in1, gdv_int64 in2);
diff --git a/cpp/src/gandiva/tests/projector_test.cc 
b/cpp/src/gandiva/tests/projector_test.cc
index b3584ec..d12d4f8 100644
--- a/cpp/src/gandiva/tests/projector_test.cc
+++ b/cpp/src/gandiva/tests/projector_test.cc
@@ -943,6 +943,66 @@ TEST_F(TestProjector, TestGreatestLeast) {
   EXPECT_ARROW_ARRAY_EQUALS(exp_least, outputs_lst.at(0));
 }
 
+TEST_F(TestProjector, TestPositiveNegative) {
+  // schema for input fields
+  auto field0 = field("f0", int32());
+  auto field1 = field("f1", int64());
+  auto schema = arrow::schema({field0, field1});
+
+  // output fields
+  auto field_pos = field("positive", int32());
+  auto field_pos2 = field("positive2", int64());
+
+  // Build expression for POSITIVE function
+  auto pos_expr = TreeExprBuilder::MakeExpression("positive", {field0}, 
field_pos);
+  auto pos_expr2 = TreeExprBuilder::MakeExpression("positive", {field1}, 
field_pos2);
+
+  std::shared_ptr<Projector> projector;
+  auto status =
+      Projector::Make(schema, {pos_expr, pos_expr2}, TestConfiguration(), 
&projector);
+  EXPECT_TRUE(status.ok()) << status.message();
+
+  // Create a row-batch with some sample data
+  int num_records = 4;
+  auto array0 = MakeArrowArrayInt32({2, 3, 4, 5}, {true, true, true, true});
+  auto array1 = MakeArrowArrayInt64({100, 200, 300, 400}, {true, true, true, 
true});
+  // expected output
+  auto exp_pos = MakeArrowArrayInt32({2, 3, 4, 5}, {true, true, true, true});
+  auto exp_pos2 = MakeArrowArrayInt64({100, 200, 300, 400}, {true, true, true, 
true});
+
+  // prepare input record batch
+  auto in_batch = arrow::RecordBatch::Make(schema, num_records, {array0, 
array1});
+
+  // 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_pos, outputs.at(0));
+  EXPECT_ARROW_ARRAY_EQUALS(exp_pos2, outputs.at(1));
+
+  // Build expression for NEG function
+  auto neg_expr = TreeExprBuilder::MakeExpression("negative", {field0}, 
field_pos);
+  auto neg_expr2 = TreeExprBuilder::MakeExpression("negative", {field1}, 
field_pos2);
+
+  status =
+      Projector::Make(schema, {neg_expr, neg_expr2}, TestConfiguration(), 
&projector);
+  EXPECT_TRUE(status.ok()) << status.message();
+
+  // expected output
+  auto exp_neg = MakeArrowArrayInt32({-2, -3, -4, -5}, {true, true, true, 
true});
+  auto exp_neg2 = MakeArrowArrayInt64({-100, -200, -300, -400}, {true, true, 
true, true});
+
+  // Evaluate expression
+  status = projector->Evaluate(*in_batch, pool_, &outputs);
+  EXPECT_TRUE(status.ok()) << status.message();
+
+  // Validate results
+  EXPECT_ARROW_ARRAY_EQUALS(exp_neg, outputs.at(0));
+  EXPECT_ARROW_ARRAY_EQUALS(exp_neg2, outputs.at(1));
+}
+
 TEST_F(TestProjector, TestConcat) {
   // schema for input fields
   auto field0 = field("f0", arrow::utf8());

Reply via email to