You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ap...@apache.org on 2022/02/08 12:34:56 UTC

[arrow] branch master updated: ARROW-14098: [C++] subtract(time, time) -> duration kernel

This is an automated email from the ASF dual-hosted git repository.

apitrou 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 75bcece  ARROW-14098: [C++] subtract(time, time) -> duration kernel
75bcece is described below

commit 75bcece383b583daeb6000a77819eee35c1a8f70
Author: Rok <ro...@mihevc.org>
AuthorDate: Tue Feb 8 13:33:01 2022 +0100

    ARROW-14098: [C++] subtract(time, time) -> duration kernel
    
    This is to resolve [ARROW-14098](https://issues.apache.org/jira/browse/ARROW-14098).
    
    Closes #12105 from rok/ARROW-14098
    
    Authored-by: Rok <ro...@mihevc.org>
    Signed-off-by: Antoine Pitrou <an...@python.org>
---
 cpp/src/arrow/compute/kernels/codegen_internal.cc  |  9 ++++-
 .../arrow/compute/kernels/codegen_internal_test.cc |  8 +++--
 cpp/src/arrow/compute/kernels/scalar_arithmetic.cc | 30 +++++++++++++++++
 .../arrow/compute/kernels/scalar_temporal_test.cc  | 39 ++++++++++++++++++++++
 4 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/cpp/src/arrow/compute/kernels/codegen_internal.cc b/cpp/src/arrow/compute/kernels/codegen_internal.cc
index 1e06a36..26c12eb 100644
--- a/cpp/src/arrow/compute/kernels/codegen_internal.cc
+++ b/cpp/src/arrow/compute/kernels/codegen_internal.cc
@@ -120,7 +120,14 @@ void ReplaceTemporalTypes(const TimeUnit::type unit, std::vector<ValueDescr>* de
         continue;
       }
       case Type::TIME32:
-      case Type::TIME64:
+      case Type::TIME64: {
+        if (unit > TimeUnit::MILLI) {
+          it->type = time64(unit);
+        } else {
+          it->type = time32(unit);
+        }
+        continue;
+      }
       case Type::DURATION: {
         it->type = duration(unit);
         continue;
diff --git a/cpp/src/arrow/compute/kernels/codegen_internal_test.cc b/cpp/src/arrow/compute/kernels/codegen_internal_test.cc
index 6b68632..c2e17e3 100644
--- a/cpp/src/arrow/compute/kernels/codegen_internal_test.cc
+++ b/cpp/src/arrow/compute/kernels/codegen_internal_test.cc
@@ -198,6 +198,10 @@ TEST(TestDispatchBest, CommonTemporalResolution) {
   ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
   args = {timestamp(TimeUnit::SECOND, "UTC"), timestamp(TimeUnit::SECOND, tz)};
   ASSERT_EQ(TimeUnit::SECOND, CommonTemporalResolution(args.data(), args.size()));
+  args = {time32(TimeUnit::MILLI), duration(TimeUnit::SECOND)};
+  ASSERT_EQ(TimeUnit::MILLI, CommonTemporalResolution(args.data(), args.size()));
+  args = {time64(TimeUnit::MICRO), duration(TimeUnit::NANO)};
+  ASSERT_EQ(TimeUnit::NANO, CommonTemporalResolution(args.data(), args.size()));
 }
 
 TEST(TestDispatchBest, ReplaceTemporalTypes) {
@@ -215,7 +219,7 @@ TEST(TestDispatchBest, ReplaceTemporalTypes) {
   ty = CommonTemporalResolution(args.data(), args.size());
   ReplaceTemporalTypes(ty, &args);
   AssertTypeEqual(args[0].type, timestamp(TimeUnit::MILLI));
-  AssertTypeEqual(args[1].type, duration(TimeUnit::MILLI));
+  AssertTypeEqual(args[1].type, time32(TimeUnit::MILLI));
 
   args = {duration(TimeUnit::SECOND), date64()};
   ty = CommonTemporalResolution(args.data(), args.size());
@@ -233,7 +237,7 @@ TEST(TestDispatchBest, ReplaceTemporalTypes) {
   ty = CommonTemporalResolution(args.data(), args.size());
   ReplaceTemporalTypes(ty, &args);
   AssertTypeEqual(args[0].type, timestamp(TimeUnit::NANO, tz));
-  AssertTypeEqual(args[1].type, duration(TimeUnit::NANO));
+  AssertTypeEqual(args[1].type, time64(TimeUnit::NANO));
 
   args = {timestamp(TimeUnit::SECOND, tz), date64()};
   ty = CommonTemporalResolution(args.data(), args.size());
diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
index b8dae54..dd04765 100644
--- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
@@ -2481,6 +2481,20 @@ void RegisterScalarArithmetic(FunctionRegistry* registry) {
                                   std::move(exec)));
   }
 
+  // Add subtract(time32, time32) -> duration
+  for (auto unit : {TimeUnit::SECOND, TimeUnit::MILLI}) {
+    InputType in_type(match::Time32TypeUnit(unit));
+    auto exec = ScalarBinaryEqualTypes<Int64Type, Time32Type, Subtract>::Exec;
+    DCHECK_OK(subtract->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
+  }
+
+  // Add subtract(time64, time64) -> duration
+  for (auto unit : {TimeUnit::MICRO, TimeUnit::NANO}) {
+    InputType in_type(match::Time64TypeUnit(unit));
+    auto exec = ScalarBinaryEqualTypes<Int64Type, Time64Type, Subtract>::Exec;
+    DCHECK_OK(subtract->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
+  }
+
   // Add subtract(date32, date32) -> duration(TimeUnit::SECOND)
   InputType in_type_date_32(date32());
   auto exec_date_32 = ScalarBinaryEqualTypes<Int64Type, Date32Type, SubtractDate32>::Exec;
@@ -2533,6 +2547,22 @@ void RegisterScalarArithmetic(FunctionRegistry* registry) {
                                         duration(TimeUnit::MILLI),
                                         std::move(exec_date_64_checked)));
 
+  // Add subtract_checked(time32, time32) -> duration
+  for (auto unit : {TimeUnit::SECOND, TimeUnit::MILLI}) {
+    InputType in_type(match::Time32TypeUnit(unit));
+    auto exec = ScalarBinaryEqualTypes<Int64Type, Time32Type, SubtractChecked>::Exec;
+    DCHECK_OK(
+        subtract_checked->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
+  }
+
+  // Add subtract_checked(time64, time64) -> duration
+  for (auto unit : {TimeUnit::MICRO, TimeUnit::NANO}) {
+    InputType in_type(match::Time64TypeUnit(unit));
+    auto exec = ScalarBinaryEqualTypes<Int64Type, Time64Type, SubtractChecked>::Exec;
+    DCHECK_OK(
+        subtract_checked->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
+  }
+
   DCHECK_OK(registry->AddFunction(std::move(subtract_checked)));
 
   // ----------------------------------------------------------------------
diff --git a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
index 67a5a8b..7b7a314 100644
--- a/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_temporal_test.cc
@@ -1117,6 +1117,45 @@ TEST_F(ScalarTemporalTest, TestTemporalSubtractTimestamp) {
   }
 }
 
+TEST_F(ScalarTemporalTest, TestTemporalSubtractTime) {
+  for (auto op : {"subtract", "subtract_checked"}) {
+    auto arr_s = ArrayFromJSON(time32(TimeUnit::SECOND), times_s);
+    auto arr_s2 = ArrayFromJSON(time32(TimeUnit::SECOND), times_s2);
+    auto arr_ms = ArrayFromJSON(time32(TimeUnit::MILLI), times_ms);
+    auto arr_ms2 = ArrayFromJSON(time32(TimeUnit::MILLI), times_ms2);
+    auto arr_us = ArrayFromJSON(time64(TimeUnit::MICRO), times_us);
+    auto arr_us2 = ArrayFromJSON(time64(TimeUnit::MICRO), times_us2);
+    auto arr_ns = ArrayFromJSON(time64(TimeUnit::NANO), times_ns);
+    auto arr_ns2 = ArrayFromJSON(time64(TimeUnit::NANO), times_ns2);
+
+    CheckScalarBinary(op, arr_s2, arr_s,
+                      ArrayFromJSON(duration(TimeUnit::SECOND), seconds_between_time));
+    CheckScalarBinary(
+        op, arr_ms2, arr_ms,
+        ArrayFromJSON(duration(TimeUnit::MILLI), milliseconds_between_time));
+    CheckScalarBinary(
+        op, arr_us2, arr_us,
+        ArrayFromJSON(duration(TimeUnit::MICRO), microseconds_between_time));
+    CheckScalarBinary(op, arr_ns2, arr_ns,
+                      ArrayFromJSON(duration(TimeUnit::NANO), nanoseconds_between_time));
+
+    CheckScalarBinary(op, arr_s, arr_s, ArrayFromJSON(duration(TimeUnit::SECOND), zeros));
+    CheckScalarBinary(op, arr_ms, arr_ms,
+                      ArrayFromJSON(duration(TimeUnit::MILLI), zeros));
+    CheckScalarBinary(op, arr_us, arr_us,
+                      ArrayFromJSON(duration(TimeUnit::MICRO), zeros));
+    CheckScalarBinary(op, arr_ns, arr_ns, ArrayFromJSON(duration(TimeUnit::NANO), zeros));
+
+    auto seconds_3 = ArrayFromJSON(time32(TimeUnit::SECOND), R"([3, null])");
+    auto milliseconds_2k = ArrayFromJSON(time32(TimeUnit::MILLI), R"([1999, null])");
+    auto milliseconds_1k = ArrayFromJSON(duration(TimeUnit::MILLI), R"([1001, null])");
+    auto microseconds_2M = ArrayFromJSON(time64(TimeUnit::MICRO), R"([1999999, null])");
+    auto microseconds_1M = ArrayFromJSON(duration(TimeUnit::MICRO), R"([1000001, null])");
+    CheckScalarBinary(op, seconds_3, milliseconds_2k, milliseconds_1k);
+    CheckScalarBinary(op, seconds_3, microseconds_2M, microseconds_1M);
+  }
+}
+
 TEST_F(ScalarTemporalTest, TestTemporalDifferenceWeeks) {
   auto raw_days = ArrayFromJSON(timestamp(TimeUnit::SECOND), R"([
     "2021-08-09", "2021-08-10", "2021-08-11", "2021-08-12", "2021-08-13", "2021-08-14", "2021-08-15",