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/27 11:51:45 UTC
[arrow] branch master updated: ARROW-15744: [Gandiva][C++] Add NEGATIVE function for interval types
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 e9481532e9 ARROW-15744: [Gandiva][C++] Add NEGATIVE function for interval types
e9481532e9 is described below
commit e9481532e93e4f29a1c2c322e00f268d6cd9f534
Author: Johnnathan <jo...@gmail.com>
AuthorDate: Wed Apr 27 17:21:33 2022 +0530
ARROW-15744: [Gandiva][C++] Add NEGATIVE function for interval types
There are two interval types:
YEAR_MONTH
DAY_TIME
This implementation is based on java implementation.
Closes #12480 from Johnnathanalmeida/feature/add-negative-function-interval-types
Authored-by: Johnnathan <jo...@gmail.com>
Signed-off-by: Pindikura Ravindra <ra...@dremio.com>
---
cpp/src/gandiva/function_registry_arithmetic.cc | 8 ++
cpp/src/gandiva/precompiled/arithmetic_ops.cc | 24 ++++++
cpp/src/gandiva/precompiled/arithmetic_ops_test.cc | 60 ++++++++++++++
cpp/src/gandiva/precompiled/types.h | 5 ++
cpp/src/gandiva/tests/projector_test.cc | 96 ++++++++++++++++++++++
5 files changed, 193 insertions(+)
diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc b/cpp/src/gandiva/function_registry_arithmetic.cc
index 6d10fd920d..4c16fc2a84 100644
--- a/cpp/src/gandiva/function_registry_arithmetic.cc
+++ b/cpp/src/gandiva/function_registry_arithmetic.cc
@@ -180,6 +180,14 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
kResultNullIfNull, "negative_decimal",
NativeFunction::kNeedsContext | NativeFunction::kCanReturnErrors),
+ NativeFunction("negative", {}, DataTypeVector{month_interval()}, month_interval(),
+ kResultNullIfNull, "negative_month_interval",
+ NativeFunction::kNeedsContext | NativeFunction::kCanReturnErrors),
+
+ NativeFunction("negative", {}, DataTypeVector{day_time_interval()},
+ day_time_interval(), kResultNullIfNull, "negative_daytimeinterval",
+ 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 3fdc4d0b6a..55994ce733 100644
--- a/cpp/src/gandiva/precompiled/arithmetic_ops.cc
+++ b/cpp/src/gandiva/precompiled/arithmetic_ops.cc
@@ -386,6 +386,30 @@ NUMERIC_FUNCTION_FOR_REAL(NEGATIVE)
NEGATIVE_INTEGER(int32, 32)
NEGATIVE_INTEGER(int64, 64)
+NEGATIVE_INTEGER(month_interval, 32)
+
+const int64_t INT_MAX_TO_NEGATIVE_INTERVAL_DAY_TIME = 9223372034707292159;
+const int64_t INT_MIN_TO_NEGATIVE_INTERVAL_DAY_TIME = -9223372030412324863;
+
+gdv_int64 negative_daytimeinterval(gdv_int64 context, gdv_day_time_interval interval) {
+ if (interval > INT_MAX_TO_NEGATIVE_INTERVAL_DAY_TIME ||
+ interval < INT_MIN_TO_NEGATIVE_INTERVAL_DAY_TIME) {
+ gdv_fn_context_set_error_msg(
+ context, "Interval day time is out of boundaries for the negative function");
+ return 0;
+ }
+
+ int64_t left = interval >> 32;
+ int64_t right = interval & 0x00000000FFFFFFFF;
+
+ left = -1 * left;
+ right = -1 * right;
+
+ gdv_int64 out = (left & 0x00000000FFFFFFFF) << 32;
+ out |= (right & 0x00000000FFFFFFFF);
+
+ return out;
+}
#undef NEGATIVE
#undef NEGATIVE_INTEGER
diff --git a/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc b/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
index 1cca0cb9c4..532a9a9fc3 100644
--- a/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
+++ b/cpp/src/gandiva/precompiled/arithmetic_ops_test.cc
@@ -179,6 +179,66 @@ TEST(TestArithmeticOps, TestPositiveNegative) {
ctx.Reset();
}
+TEST(TestArithmeticOps, TestNegativeIntervalTypes) {
+ gandiva::ExecutionContext ctx;
+ int64_t ctx_ptr = reinterpret_cast<int64_t>(&ctx);
+
+ // Input: 8589934594; Mean: 2 time & 2 days
+ // Response: -4294967298; Mean: -2 time & -2 days
+ gdv_int64 result = negative_daytimeinterval(ctx_ptr, 8589934594);
+ EXPECT_EQ(result, -4294967298);
+
+ // Input: -4294967298; Mean: -2 time & -2 days
+ // Response: 8589934594; Mean: 2 time & 2 days
+ result = negative_daytimeinterval(ctx_ptr, -4294967298);
+ EXPECT_EQ(result, 8589934594);
+
+ // Input: -12884903388; Mean: -4 time & -1500 days
+ // Response: 17179870684; Mean: 4 time & 1500 days
+ result = negative_daytimeinterval(ctx_ptr, -12884903388);
+ EXPECT_EQ(result, 17179870684);
+
+ // Input: 44023418384000; Mean: 10250 time & 3600000 days
+ // Response: -44019123416704; Mean: -10250 time & -3600000 days
+ result = negative_daytimeinterval(ctx_ptr, 44023418384000);
+ EXPECT_EQ(result, -44019123416704);
+
+ // Input: 9223372034707292159; Mean: 2147483647 time & 2147483647 days
+ // Response: -9223372030412324863; Mean: -2147483647 time & -2147483647 days
+ const int64_t INT_MAX_TO_NEGATIVE_INTERVAL_DAY_TIME = 9223372034707292159;
+ result = negative_daytimeinterval(ctx_ptr, INT_MAX_TO_NEGATIVE_INTERVAL_DAY_TIME);
+ EXPECT_EQ(result, -9223372030412324863);
+
+ result = negative_daytimeinterval(ctx_ptr, INT64_MAX);
+ EXPECT_EQ(ctx.has_error(), true);
+ EXPECT_EQ(ctx.get_error(),
+ "Interval day time is out of boundaries for the negative function");
+ ctx.Reset();
+
+ const int64_t INT_MIN_TO_NEGATIVE_INTERVAL_DAY_TIME = -9223372030412324863;
+ result = negative_daytimeinterval(ctx_ptr, INT_MIN_TO_NEGATIVE_INTERVAL_DAY_TIME);
+ EXPECT_EQ(result, INT_MAX_TO_NEGATIVE_INTERVAL_DAY_TIME);
+
+ result = negative_daytimeinterval(ctx_ptr, INT64_MIN);
+ EXPECT_EQ(ctx.has_error(), true);
+ EXPECT_EQ(ctx.get_error(),
+ "Interval day time is out of boundaries for the negative function");
+ ctx.Reset();
+
+ // Month interval
+ gdv_month_interval result2 = negative_month_interval(ctx_ptr, 2);
+ EXPECT_EQ(result2, -2);
+
+ result2 = negative_month_interval(ctx_ptr, -2);
+ EXPECT_EQ(result2, 2);
+
+ result2 = negative_month_interval(ctx_ptr, 510);
+ EXPECT_EQ(result2, -510);
+
+ result2 = negative_month_interval(ctx_ptr, INT32_MAX);
+ EXPECT_EQ(result2, -INT32_MAX);
+}
+
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 fde23cdd02..1b492fcfdf 100644
--- a/cpp/src/gandiva/precompiled/types.h
+++ b/cpp/src/gandiva/precompiled/types.h
@@ -207,11 +207,16 @@ 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_month_interval negative_month_interval(gdv_int64 context,
+ gdv_month_interval interval);
+gdv_int64 negative_daytimeinterval(gdv_int64 context, gdv_day_time_interval interval);
+
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 86c35af4bf..06c1dbdf08 100644
--- a/cpp/src/gandiva/tests/projector_test.cc
+++ b/cpp/src/gandiva/tests/projector_test.cc
@@ -1042,6 +1042,102 @@ TEST_F(TestProjector, TestPositiveNegative) {
EXPECT_ARROW_ARRAY_EQUALS(exp_neg2, outputs.at(1));
}
+TEST_F(TestProjector, TestNegativeMonthInterval) {
+ // schema for input fields
+ auto field0 = field("f0", arrow::month_interval());
+ auto schema = arrow::schema({field0});
+
+ // output fields
+ auto field_pos = field("result", arrow::month_interval());
+
+ // Build expression for NEGATIVE function
+ auto pos_expr = TreeExprBuilder::MakeExpression("negative", {field0}, field_pos);
+
+ std::shared_ptr<Projector> projector;
+ auto status = Projector::Make(schema, {pos_expr}, TestConfiguration(), &projector);
+ EXPECT_TRUE(status.ok()) << status.message();
+
+ // Create a row-batch with some sample data
+ int num_records = 6;
+
+ std::shared_ptr<arrow::Array> array0, exp_pos;
+ arrow::ArrayFromVector<arrow::MonthIntervalType>(
+ arrow::month_interval(), {true, true, true, true, true, true},
+ {2, -2, 10250, 2147483647, 4, -4}, &array0);
+
+ // expected output
+ arrow::ArrayFromVector<arrow::MonthIntervalType>(
+ arrow::month_interval(), {true, true, true, true, true, true},
+ {-2, 2, -10250, -2147483647, -4, 4}, &exp_pos);
+
+ // prepare input record batch
+ auto in_batch = arrow::RecordBatch::Make(schema, 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_pos, outputs.at(0));
+}
+
+TEST_F(TestProjector, TestNegativeIntervalTypeDayTime) {
+ // schema for input fields
+ auto field0 = field("f1", arrow::day_time_interval());
+ auto schema = arrow::schema({field0});
+
+ // output fields
+ auto output_negative = field("result", arrow::day_time_interval());
+
+ // Build expression for POSITIVE function
+ auto pos_expr = TreeExprBuilder::MakeExpression("negative", {field0}, output_negative);
+
+ std::shared_ptr<Projector> projector;
+ auto status = Projector::Make(schema, {pos_expr}, TestConfiguration(), &projector);
+ EXPECT_TRUE(status.ok()) << status.message();
+
+ // Create a row-batch with some sample data
+ int num_records = 7;
+
+ std::shared_ptr<arrow::Array> array_day_interval, array_day_interval_output;
+ arrow::ArrayFromVector<arrow::DayTimeIntervalType,
+ arrow::DayTimeIntervalType::DayMilliseconds>(
+ arrow::day_time_interval(), {true, true, true, true, true, true, true},
+ {{2, 2},
+ {-2, -2},
+ {10250, 3600000},
+ {2147483647, 2147483647},
+ {4, 1500},
+ {-4, -1500},
+ {-2147483647, -2147483647}},
+ &array_day_interval);
+
+ // expected output
+ arrow::ArrayFromVector<arrow::DayTimeIntervalType,
+ arrow::DayTimeIntervalType::DayMilliseconds>(
+ arrow::day_time_interval(), {true, true, true, true, true, true, true},
+ {{-2, -2},
+ {2, 2},
+ {-10250, -3600000},
+ {-2147483647, -2147483647},
+ {-4, -1500},
+ {4, 1500},
+ {2147483647, 2147483647}},
+ &array_day_interval_output);
+
+ // prepare input record batch
+ auto in_batch = arrow::RecordBatch::Make(schema, num_records, {array_day_interval});
+
+ // Evaluate expression
+ arrow::ArrayVector outputs;
+ status = projector->Evaluate(*in_batch, pool_, &outputs);
+ EXPECT_TRUE(status.ok()) << status.message();
+
+ // Validate results
+ EXPECT_ARROW_ARRAY_EQUALS(array_day_interval_output, outputs.at(0));
+}
+
TEST_F(TestProjector, TestConcat) {
// schema for input fields
auto field0 = field("f0", arrow::utf8());