From d27218e1cdb53ac49dadb946c6feda7a32371004 Mon Sep 17 00:00:00 2001 From: Rok Date: Mon, 29 Mar 2021 22:01:11 +0200 Subject: [PATCH 01/21] Adding exponentiation kernel. --- cpp/src/arrow/compute/api_scalar.cc | 1 + cpp/src/arrow/compute/api_scalar.h | 14 ++++ .../compute/kernels/scalar_arithmetic.cc | 61 +++++++++++++++ .../compute/kernels/scalar_arithmetic_test.cc | 78 ++++++++++++++++++- 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/compute/api_scalar.cc b/cpp/src/arrow/compute/api_scalar.cc index f4696fbe02a..0ede1bf6502 100644 --- a/cpp/src/arrow/compute/api_scalar.cc +++ b/cpp/src/arrow/compute/api_scalar.cc @@ -52,6 +52,7 @@ SCALAR_ARITHMETIC_BINARY(Add, "add", "add_checked") SCALAR_ARITHMETIC_BINARY(Subtract, "subtract", "subtract_checked") SCALAR_ARITHMETIC_BINARY(Multiply, "multiply", "multiply_checked") SCALAR_ARITHMETIC_BINARY(Divide, "divide", "divide_checked") +SCALAR_ARITHMETIC_BINARY(Exponentiate, "exponentiate", "exponentiate_checked") // ---------------------------------------------------------------------- // Set-related operations diff --git a/cpp/src/arrow/compute/api_scalar.h b/cpp/src/arrow/compute/api_scalar.h index f59426d8f1b..66b59573e57 100644 --- a/cpp/src/arrow/compute/api_scalar.h +++ b/cpp/src/arrow/compute/api_scalar.h @@ -204,6 +204,20 @@ Result Divide(const Datum& left, const Datum& right, ArithmeticOptions options = ArithmeticOptions(), ExecContext* ctx = NULLPTR); +/// \brief Compute the value of base value to the power of the exponent value. +/// Array values must be the same length. If either argument is null the result will be +/// null. For integer types, if there is a zero base value, an error will be raised. +/// +/// \param[in] left the base +/// \param[in] right the exponent +/// \param[in] options arithmetic options (enable/disable overflow checking), optional +/// \param[in] ctx the function execution context, optional +/// \return the elementwise quotient +ARROW_EXPORT +Result Exponentiate(const Datum& left, const Datum& right, + ArithmeticOptions options = ArithmeticOptions(), + ExecContext* ctx = NULLPTR); + /// \brief Compare a numeric array with a scalar. /// /// \param[in] left datum to compare, must be an Array diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc index 7abaa1c1a59..2e8b605451e 100644 --- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc +++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc @@ -18,11 +18,13 @@ #include "arrow/compute/kernels/common.h" #include "arrow/util/int_util_internal.h" #include "arrow/util/macros.h" +#include "math.h" namespace arrow { using internal::AddWithOverflow; using internal::DivideWithOverflow; +// using internal::ExponentiateWithOverflow; using internal::MultiplyWithOverflow; using internal::SubtractWithOverflow; @@ -233,6 +235,41 @@ struct DivideChecked { } }; +struct Exponentiate { + template + static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) { + if (left == 0 && (-INFINITY < right && right < 0)) { + ctx->SetStatus(Status::Invalid("divide by zero")); + } + return pow(left, right); + } + + template + static enable_if_floating_point Call(KernelContext* ctx, Arg0 left, Arg1 right) { + return pow(left, right); + } +}; + +struct ExponentiateChecked { + template + static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) { + static_assert(std::is_same::value && std::is_same::value, ""); + if (left == 0 && (-INFINITY < right && right < 0)) { + ctx->SetStatus(Status::Invalid("divide by zero")); + } + return pow(left, right); + } + + template + static enable_if_floating_point Call(KernelContext* ctx, Arg0 left, Arg1 right) { + static_assert(std::is_same::value && std::is_same::value, ""); + if (left == 0 && (-INFINITY < right && right < 0)) { + ctx->SetStatus(Status::Invalid("divide by zero")); + } + return pow(left, right); + } +}; + // Generate a kernel given an arithmetic functor template