Skip to content

Commit 8ce0c01

Browse files
edponcelidavidm
authored andcommitted
ARROW-12745: [C++][Compute] Add floor, ceiling, and truncate kernels
This PR adds floor, ceiling, and truncate scalar kernels. For all integral inputs, output is a 64-bit floating-point value. Closes #10727 from edponce/ARROW-12745-Compute-Add-floor-ceiling-and-truncate-k Authored-by: Eduardo Ponce <edponce00@gmail.com> Signed-off-by: David Li <li.davidm96@gmail.com>
1 parent e61843a commit 8ce0c01

6 files changed

Lines changed: 349 additions & 60 deletions

File tree

cpp/src/arrow/compute/api_scalar.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ SCALAR_ARITHMETIC_BINARY(Power, "power", "power_checked")
358358
SCALAR_ARITHMETIC_BINARY(ShiftLeft, "shift_left", "shift_left_checked")
359359
SCALAR_ARITHMETIC_BINARY(ShiftRight, "shift_right", "shift_right_checked")
360360
SCALAR_EAGER_BINARY(Atan2, "atan2")
361+
SCALAR_EAGER_UNARY(Floor, "floor")
362+
SCALAR_EAGER_UNARY(Ceil, "ceil")
363+
SCALAR_EAGER_UNARY(Trunc, "trunc")
361364

362365
Result<Datum> MaxElementWise(const std::vector<Datum>& args,
363366
ElementWiseAggregateOptions options, ExecContext* ctx) {

cpp/src/arrow/compute/api_scalar.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,35 @@ ARROW_EXPORT
487487
Result<Datum> Log1p(const Datum& arg, ArithmeticOptions options = ArithmeticOptions(),
488488
ExecContext* ctx = NULLPTR);
489489

490+
/// \brief Round to the nearest integer less than or equal in magnitude to the
491+
/// argument. Array values can be of arbitrary length. If argument is null the
492+
/// result will be null.
493+
///
494+
/// \param[in] arg the value to round
495+
/// \param[in] ctx the function execution context, optional
496+
/// \return the rounded value
497+
ARROW_EXPORT
498+
Result<Datum> Floor(const Datum& arg, ExecContext* ctx = NULLPTR);
499+
500+
/// \brief Round to the nearest integer greater than or equal in magnitude to the
501+
/// argument. Array values can be of arbitrary length. If argument is null the
502+
/// result will be null.
503+
///
504+
/// \param[in] arg the value to round
505+
/// \param[in] ctx the function execution context, optional
506+
/// \return the rounded value
507+
ARROW_EXPORT
508+
Result<Datum> Ceil(const Datum& arg, ExecContext* ctx = NULLPTR);
509+
510+
/// \brief Get the integral part without fractional digits. Array values can be
511+
/// of arbitrary length. If argument is null the result will be null.
512+
///
513+
/// \param[in] arg the value to truncate
514+
/// \param[in] ctx the function execution context, optional
515+
/// \return the truncated value
516+
ARROW_EXPORT
517+
Result<Datum> Trunc(const Datum& arg, ExecContext* ctx = NULLPTR);
518+
490519
/// \brief Find the element-wise maximum of any number of arrays or scalars.
491520
/// Array values must be the same length.
492521
///

cpp/src/arrow/compute/kernels/scalar_arithmetic.cc

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,27 @@ struct Log1pChecked {
817817
}
818818
};
819819

820+
struct Floor {
821+
template <typename T, typename Arg>
822+
static constexpr enable_if_floating_point<T> Call(KernelContext*, Arg arg, Status*) {
823+
return std::floor(arg);
824+
}
825+
};
826+
827+
struct Ceil {
828+
template <typename T, typename Arg>
829+
static constexpr enable_if_floating_point<T> Call(KernelContext*, Arg arg, Status*) {
830+
return std::ceil(arg);
831+
}
832+
};
833+
834+
struct Trunc {
835+
template <typename T, typename Arg>
836+
static constexpr enable_if_floating_point<T> Call(KernelContext*, Arg arg, Status*) {
837+
return std::trunc(arg);
838+
}
839+
};
840+
820841
// Generate a kernel given an arithmetic functor
821842
template <template <typename... Args> class KernelGenerator, typename Op>
822843
ArrayKernelExec ArithmeticExecFromOp(detail::GetTypeId get_id) {
@@ -1391,16 +1412,16 @@ const FunctionDoc sign_doc{
13911412
{"x"}};
13921413

13931414
const FunctionDoc bit_wise_not_doc{
1394-
"Bit-wise negate the arguments element-wise", ("Null values return null."), {"x"}};
1415+
"Bit-wise negate the arguments element-wise", "Null values return null.", {"x"}};
13951416

13961417
const FunctionDoc bit_wise_and_doc{
1397-
"Bit-wise AND the arguments element-wise", ("Null values return null."), {"x", "y"}};
1418+
"Bit-wise AND the arguments element-wise", "Null values return null.", {"x", "y"}};
13981419

13991420
const FunctionDoc bit_wise_or_doc{
1400-
"Bit-wise OR the arguments element-wise", ("Null values return null."), {"x", "y"}};
1421+
"Bit-wise OR the arguments element-wise", "Null values return null.", {"x", "y"}};
14011422

14021423
const FunctionDoc bit_wise_xor_doc{
1403-
"Bit-wise XOR the arguments element-wise", ("Null values return null."), {"x", "y"}};
1424+
"Bit-wise XOR the arguments element-wise", "Null values return null.", {"x", "y"}};
14041425

14051426
const FunctionDoc shift_left_doc{
14061427
"Left shift `x` by `y`",
@@ -1506,12 +1527,12 @@ const FunctionDoc acos_checked_doc{
15061527
{"x"}};
15071528

15081529
const FunctionDoc atan_doc{"Compute the principal value of the inverse tangent",
1509-
("Integer arguments return double values."),
1530+
"Integer arguments return double values.",
15101531
{"x"}};
15111532

15121533
const FunctionDoc atan2_doc{
15131534
"Compute the inverse tangent using argument signs to determine the quadrant",
1514-
("Integer arguments return double values."),
1535+
"Integer arguments return double values.",
15151536
{"y", "x"}};
15161537

15171538
const FunctionDoc ln_doc{
@@ -1567,6 +1588,24 @@ const FunctionDoc log1p_checked_doc{
15671588
"Use function \"log1p\" if you want non-positive values to return "
15681589
"-inf or NaN."),
15691590
{"x"}};
1591+
1592+
const FunctionDoc floor_doc{
1593+
"Round down to the nearest integer",
1594+
("Calculate the nearest integer less than or equal in magnitude to the "
1595+
"argument element-wise"),
1596+
{"x"}};
1597+
1598+
const FunctionDoc ceil_doc{
1599+
"Round up to the nearest integer",
1600+
("Calculate the nearest integer greater than or equal in magnitude to the "
1601+
"argument element-wise"),
1602+
{"x"}};
1603+
1604+
const FunctionDoc trunc_doc{
1605+
"Get the integral part without fractional digits",
1606+
("Calculate the nearest integer not greater in magnitude than to the "
1607+
"argument element-wise."),
1608+
{"x"}};
15701609
} // namespace
15711610

15721611
void RegisterScalarArithmetic(FunctionRegistry* registry) {
@@ -1592,7 +1631,6 @@ void RegisterScalarArithmetic(FunctionRegistry* registry) {
15921631
DCHECK_OK(registry->AddFunction(std::move(add_checked)));
15931632

15941633
// ----------------------------------------------------------------------
1595-
// subtract
15961634
auto subtract = MakeArithmeticFunction<Subtract>("subtract", &sub_doc);
15971635
AddDecimalBinaryKernels<Subtract>("subtract", &subtract);
15981636

@@ -1767,6 +1805,17 @@ void RegisterScalarArithmetic(FunctionRegistry* registry) {
17671805
auto log1p_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<Log1pChecked>(
17681806
"log1p_checked", &log1p_checked_doc);
17691807
DCHECK_OK(registry->AddFunction(std::move(log1p_checked)));
1808+
1809+
// ----------------------------------------------------------------------
1810+
// Rounding functions
1811+
auto floor = MakeUnaryArithmeticFunctionFloatingPoint<Floor>("floor", &floor_doc);
1812+
DCHECK_OK(registry->AddFunction(std::move(floor)));
1813+
1814+
auto ceil = MakeUnaryArithmeticFunctionFloatingPoint<Ceil>("ceil", &ceil_doc);
1815+
DCHECK_OK(registry->AddFunction(std::move(ceil)));
1816+
1817+
auto trunc = MakeUnaryArithmeticFunctionFloatingPoint<Trunc>("trunc", &trunc_doc);
1818+
DCHECK_OK(registry->AddFunction(std::move(trunc)));
17701819
}
17711820

17721821
} // namespace internal

0 commit comments

Comments
 (0)