edponce commented on a change in pull request #10349:
URL: https://github.com/apache/arrow/pull/10349#discussion_r659133597



##########
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##########
@@ -454,6 +456,159 @@ struct PowerChecked {
   }
 };
 
+using RoundState = internal::OptionsWrapper<RoundOptions>;
+
+struct Round {
+  template <typename T, enable_if_t<std::is_floating_point<T>::value, bool> = 
true>
+  static constexpr bool ApproxEqual(T x, T y, int ulp = 8) {
+    // https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
+    // The machine epsilon has to be scaled to the magnitude of the values used
+    // and multiplied by the desired precision in ULPs (units in the last 
place)
+    return (std::fabs(x - y) <=
+            (std::numeric_limits<T>::epsilon() * std::fabs(x + y) * ulp))
+           // unless the result is subnormal
+           || (std::fabs(x - y) < std::numeric_limits<T>::min());
+  }
+
+  template <typename T, enable_if_t<std::is_floating_point<T>::value, bool> = 
true>
+  static constexpr bool IsHalf(T val) {
+    // |frac| == 0.5?
+    return ApproxEqual(std::fabs(std::fmod(val, T(1))), T(0.5));
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> RoundWithMultiple(T val, T 
mult) {
+    return (val / mult) * mult;
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> Floor(T val) {
+    return std::floor(val);
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> Ceiling(T val) {
+    return std::ceil(val);
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> Truncate(T val) {
+    return std::trunc(val);
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> TowardsInfinity(T val) {
+    return std::signbit(val) ? std::floor(val) : std::ceil(val);
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> HalfDown(T val) {
+    return std::ceil(val - T(0.5));
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> HalfUp(T val) {
+    return std::floor(val + T(0.5));
+  }
+
+  template <typename T>
+  static enable_if_floating_point<T> HalfToEven(T val) {
+    if (IsHalf(val)) {
+      auto floor = std::floor(val);
+      // Odd + 1, Even + 0
+      return floor + (std::fmod(std::fabs(floor), T(2)) >= T(1));
+    }
+    return std::round(val);
+  }
+
+  template <typename T>
+  static enable_if_floating_point<T> HalfToOdd(T val) {
+    if (IsHalf(val)) {
+      auto floor = std::floor(val);
+      // Odd + 0, Even + 1
+      return floor + (std::fmod(std::fabs(floor), T(2)) < T(1));
+    }
+    return std::round(val);
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> Nearest(T val) {
+    return std::round(val);
+  }
+
+  template <typename T>
+  static constexpr enable_if_floating_point<T> HalfTowardsZero(T val) {
+    return std::copysign(std::ceil(std::fabs(val) - T(0.5)), val);
+  }
+
+  template <typename T, typename Arg,
+            enable_if_t<std::is_integral<Arg>::value, bool> = true>
+  static constexpr enable_if_floating_point<T> Call(KernelContext* ctx, Arg 
arg,
+                                                    Status* st) {
+    return Call<T, T>(ctx, T(arg), st);
+  }
+
+  template <typename T, typename Arg,
+            enable_if_t<std::is_floating_point<Arg>::value, bool> = true>
+  static enable_if_floating_point<T> Call(KernelContext* ctx, Arg arg, Status* 
st) {
+    const RoundOptions& options = RoundState::Get(ctx);

Review comment:
       I was able to found the issues triggering a segfault when 
`RoundState::Get(ctx)` in kernels. The first issue was resolved by @lidavidm 
fix, `kRoundOptions` needs to be defined in global space. The second issue 
occurred because no `KernelInit` parameter (in this case (`RoundOptions::Init`) 
was passed to `AddKernel` and the [default value is 
null](https://github.com/edponce/arrow/blob/master/cpp/src/arrow/compute/function.h#L267-L268)
 which [prevented options from being set in the 
`KernelState`](https://github.com/edponce/arrow/blob/master/cpp/src/arrow/compute/function.cc#L181-L184).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to