[GitHub] [arrow] bkietz commented on a change in pull request #7748: ARROW-9388: [C++] Division kernels

2020-08-18 Thread GitBox


bkietz commented on a change in pull request #7748:
URL: https://github.com/apache/arrow/pull/7748#discussion_r472240168



##
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##
@@ -186,6 +187,42 @@ struct MultiplyChecked {
   }
 };
 
+struct Divide {
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, Arg0 left,
+Arg1 right) {
+return left / right;

Review comment:
   This is true, but division by zero can result in `SIGFPE` if 
[`feenableexcept()`](http://www.gnu.org/savannah-checkouts/gnu/libc/manual/html_node/Control-Functions.html)
 or a hardware exception if 
[`_control87()`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/control87-controlfp-control87-2)
 are used. For example:
   
   ```sh
   g++ -lm -xc++ - <
   int main(int argc, char* argv[]) {
 feenableexcept(FE_ALL_EXCEPT);
 return static_cast(1.0 / 0.0);
   }
   !
   ./a.out # abort
   ```
   
   These are rare, so maybe we don't need to support them (or at least restrict 
this check to the checked division kernel), but they do represent a potential 
crash when dividing by `0.0`. @pitrou ?





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.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org




[GitHub] [arrow] bkietz commented on a change in pull request #7748: ARROW-9388: [C++] Division kernels

2020-08-13 Thread GitBox


bkietz commented on a change in pull request #7748:
URL: https://github.com/apache/arrow/pull/7748#discussion_r469934580



##
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##
@@ -186,6 +187,42 @@ struct MultiplyChecked {
   }
 };
 
+struct Divide {
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, Arg0 left,
+Arg1 right) {
+return left / right;
+  }
+
+  template 
+  static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) {
+if (ARROW_PREDICT_FALSE(right == 0)) {
+  ctx->SetStatus(Status::Invalid("overflow"));

Review comment:
   ```suggestion
 ctx->SetStatus(Status::Invalid("divide by zero"));
   ```

##
File path: cpp/src/arrow/compute/api_scalar.h
##
@@ -129,6 +129,20 @@ Result Multiply(const Datum& left, const Datum& 
right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR);
 
+/// \brief Divide two values. Array values must be the same length. If either
+/// factor is null the result will be null.

Review comment:
   ```suggestion
   /// \brief Divide two values. Array values must be the same length. If either
   /// argument is null the result will be null.
   ```

##
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##
@@ -186,6 +187,42 @@ struct MultiplyChecked {
   }
 };
 
+struct Divide {
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, Arg0 left,
+Arg1 right) {
+return left / right;
+  }
+
+  template 
+  static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) {
+if (ARROW_PREDICT_FALSE(right == 0)) {
+  ctx->SetStatus(Status::Invalid("overflow"));
+  return 0;
+}
+return left / right;
+  }
+};
+
+struct DivideChecked {
+  template 
+  static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) {
+static_assert(std::is_same::value && std::is_same::value, "");
+T result;
+if (ARROW_PREDICT_FALSE(DivideWithOverflow(left, right, ))) {
+  ctx->SetStatus(Status::Invalid("overflow"));

Review comment:
   ```suggestion
 if (right == 0) {
   ctx->SetStatus(Status::Invalid("divide by zero"));
 } else {
   ctx->SetStatus(Status::Invalid("overflow"));
 }
   ```

##
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##
@@ -186,6 +187,42 @@ struct MultiplyChecked {
   }
 };
 
+struct Divide {
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, Arg0 left,
+Arg1 right) {
+return left / right;
+  }
+
+  template 
+  static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) {
+if (ARROW_PREDICT_FALSE(right == 0)) {
+  ctx->SetStatus(Status::Invalid("overflow"));
+  return 0;
+}
+return left / right;
+  }
+};
+
+struct DivideChecked {
+  template 
+  static enable_if_integer Call(KernelContext* ctx, Arg0 left, Arg1 right) {
+static_assert(std::is_same::value && std::is_same::value, "");
+T result;
+if (ARROW_PREDICT_FALSE(DivideWithOverflow(left, right, ))) {
+  ctx->SetStatus(Status::Invalid("overflow"));
+}
+return result;
+  }
+
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, Arg0 left,
+Arg1 right) {
+static_assert(std::is_same::value && std::is_same::value, "");
+return left / right;

Review comment:
   ```suggestion
   if (ARROW_PREDICT_FALSE(right == 0)) {
 ctx->SetStatus(Status::Invalid("divide by zero"));
 return 0;
   }
   ```

##
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##
@@ -186,6 +187,42 @@ struct MultiplyChecked {
   }
 };
 
+struct Divide {
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, Arg0 left,
+Arg1 right) {
+return left / right;

Review comment:
   ```suggestion
   if (ARROW_PREDICT_FALSE(right == 0)) {
 ctx->SetStatus(Status::Invalid("divide by zero"));
 return 0;
   }
   return left / right;
   ```





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.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org




[GitHub] [arrow] bkietz commented on a change in pull request #7748: ARROW-9388: [C++] Division kernels

2020-07-14 Thread GitBox


bkietz commented on a change in pull request #7748:
URL: https://github.com/apache/arrow/pull/7748#discussion_r454610972



##
File path: cpp/src/arrow/compute/kernels/codegen_internal.h
##
@@ -675,11 +704,80 @@ struct ScalarBinary {
   }
 };
 
+// An alternative to ScalarBinary that Applies a scalar operation on only the
+// not-null values of arrays.
+template 
+struct ScalarBinaryNotNull {
+  using OUT = typename GetOutputType::T;
+
+  static void ArrayArray(KernelContext* ctx, const ArrayData& arg0, const 
ArrayData& arg1,
+ Datum* out) {
+ArrayIterator arg0_it(arg0);
+ArrayIterator arg1_it(arg1);
+OutputAdapter::WriteOnlyValid(
+ctx, out, [&]() -> OUT { return Op::template Call(ctx, arg0_it(), 
arg1_it()); },
+[&]() {
+  ARROW_UNUSED(arg0_it());
+  ARROW_UNUSED(arg1_it());
+});
+  }
+
+  static void ArrayScalar(KernelContext* ctx, const ArrayData& arg0, const 
Scalar& arg1,
+  Datum* out) {
+ArrayIterator arg0_it(arg0);
+auto arg1_val = UnboxScalar::Unbox(arg1);
+OutputAdapter::WriteOnlyValid(
+ctx, out, [&]() -> OUT { return Op::template Call(ctx, arg0_it(), 
arg1_val); },
+[&]() { ARROW_UNUSED(arg0_it()); });
+  }
+
+  static void ScalarArray(KernelContext* ctx, const Scalar& arg0, const 
ArrayData& arg1,
+  Datum* out) {
+auto arg0_val = UnboxScalar::Unbox(arg0);
+ArrayIterator arg1_it(arg1);
+OutputAdapter::WriteOnlyValid(
+ctx, out, [&]() -> OUT { return Op::template Call(ctx, arg0_val, 
arg1_it()); },
+[&]() { ARROW_UNUSED(arg1_it()); });
+  }
+
+  static void ScalarScalar(KernelContext* ctx, const Scalar& arg0, const 
Scalar& arg1,
+   Datum* out) {
+if (out->scalar()->is_valid) {
+  auto arg0_val = UnboxScalar::Unbox(arg0);
+  auto arg1_val = UnboxScalar::Unbox(arg1);
+  BoxScalar::Box(Op::template Call(ctx, arg0_val, arg1_val),
+  out->scalar().get());
+}
+  }
+
+  static void Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
+if (batch[0].kind() == Datum::ARRAY) {
+  if (batch[1].kind() == Datum::ARRAY) {
+return ArrayArray(ctx, *batch[0].array(), *batch[1].array(), out);
+  } else {
+return ArrayScalar(ctx, *batch[0].array(), *batch[1].scalar(), out);
+  }
+} else {
+  if (batch[1].kind() == Datum::ARRAY) {
+// e.g. if we were doing scalar < array, we flip and do array >= scalar

Review comment:
   I think this comment is not applicable
   ```suggestion
   ```

##
File path: cpp/src/arrow/compute/api_scalar.h
##
@@ -130,6 +130,19 @@ Result Multiply(const Datum& left, const Datum& 
right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR);
 
+/// \brief Divide two values. Array values must be the same length. If either
+/// factor is null the result will be null.

Review comment:
   Please describe division-by-zero behavior

##
File path: cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
##
@@ -219,48 +219,77 @@ struct MultiplyChecked {
   }
 };
 
+struct Divide {
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, T left, T 
right) {
+return left / right;
+  }
+
+  template 
+  static constexpr enable_if_integer Call(KernelContext*, T left, T right) {
+return left / right;
+  }
+};
+
+struct DivideChecked {
+  template 
+  static enable_if_integer Call(KernelContext* ctx, T left, T right) {
+if (right == 0) {
+  ctx->SetStatus(Status::Invalid("divide by 0"));
+  return right;
+}
+return Divide::Call(ctx, left, right);
+  }
+
+  template 
+  static constexpr enable_if_floating_point Call(KernelContext*, T left, T 
right) {
+return left * right;

Review comment:
   ```suggestion
   return left / right;
   ```

##
File path: cpp/src/arrow/compute/api_scalar.h
##
@@ -130,6 +130,19 @@ Result Multiply(const Datum& left, const Datum& 
right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR);
 
+/// \brief Divide two values. Array values must be the same length. If either
+/// factor is null the result will be null.
+///
+/// \param[in] left the dividend
+/// \param[in] right the divisor
+/// \param[in] options arithmetic options (overflow handling), optional

Review comment:
   Division does not overflow unless the dividend is INT_MIN and the 
divisor is -1; IIUC `overflow_handling` is being used to indicate whether 
divide-by-zero should raise an error. If so please amend the comment





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