From 95da7efad2aa79325662b92753e420566aadf01a Mon Sep 17 00:00:00 2001 From: liyafan82 Date: Mon, 24 Aug 2020 21:01:10 +0800 Subject: [PATCH 1/3] ARROW-9811: [C++] Unchecked floating point division by 0 should succeed --- cpp/src/arrow/compare.cc | 35 ++++++++++++++++--- cpp/src/arrow/compare.h | 7 ++++ .../compute/kernels/scalar_arithmetic.cc | 13 +++++-- .../compute/kernels/scalar_arithmetic_test.cc | 25 +++++++++---- cpp/src/arrow/scalar.cc | 4 +++ cpp/src/arrow/scalar.h | 2 ++ cpp/src/arrow/testing/gtest_util.cc | 20 ++++++++--- cpp/src/arrow/testing/gtest_util.h | 5 +++ 8 files changed, 95 insertions(+), 16 deletions(-) diff --git a/cpp/src/arrow/compare.cc b/cpp/src/arrow/compare.cc index e0c23a31eac..f05d474cb6e 100644 --- a/cpp/src/arrow/compare.cc +++ b/cpp/src/arrow/compare.cc @@ -862,7 +862,11 @@ class TypeEqualsVisitor { class ScalarEqualsVisitor { public: - explicit ScalarEqualsVisitor(const Scalar& right) : right_(right), result_(false) {} + explicit ScalarEqualsVisitor(const Scalar& right) + : right_(right), result_(false), options_(EqualOptions()) {} + + explicit ScalarEqualsVisitor(const Scalar& right, const EqualOptions& opts) + : right_(right), result_(false), options_(opts) {} Status Visit(const NullScalar& left) { result_ = true; @@ -875,9 +879,26 @@ class ScalarEqualsVisitor { return Status::OK(); } + template + typename std::enable_if::value || + std::is_base_of::value, + Status>::type + Visit(const T& left_) { + const auto& right = checked_cast(right_); + if (options_.nans_equal()) { + result_ = right.value == left_.value || + (std::isnan(right.value) && std::isnan(left_.value)); + } else { + result_ = right.value == left_.value; + } + return Status::OK(); + } + template typename std::enable_if< - std::is_base_of, T>::value || + (std::is_base_of, T>::value && + !std::is_base_of::value && + !std::is_base_of::value) || std::is_base_of, T>::value, Status>::type Visit(const T& left_) { @@ -968,6 +989,7 @@ class ScalarEqualsVisitor { protected: const Scalar& right_; bool result_; + EqualOptions options_; }; Status PrintDiff(const Array& left, const Array& right, std::ostream* os) { @@ -1386,7 +1408,7 @@ bool TypeEquals(const DataType& left, const DataType& right, bool check_metadata } } -bool ScalarEquals(const Scalar& left, const Scalar& right) { +bool ScalarEquals(const Scalar& left, const Scalar& right, const EqualOptions& options) { bool are_equal = false; if (&left == &right) { are_equal = true; @@ -1395,7 +1417,7 @@ bool ScalarEquals(const Scalar& left, const Scalar& right) { } else if (left.is_valid != right.is_valid) { are_equal = false; } else { - ScalarEqualsVisitor visitor(right); + ScalarEqualsVisitor visitor(right, options); auto error = VisitScalarInline(left, &visitor); DCHECK_OK(error); are_equal = visitor.result(); @@ -1403,4 +1425,9 @@ bool ScalarEquals(const Scalar& left, const Scalar& right) { return are_equal; } +bool ScalarEquals(const Scalar& left, const Scalar& right) { + const EqualOptions options; + return ScalarEquals(left, right, options); +} + } // namespace arrow diff --git a/cpp/src/arrow/compare.h b/cpp/src/arrow/compare.h index abcf39a62e5..84e7cf8760c 100644 --- a/cpp/src/arrow/compare.h +++ b/cpp/src/arrow/compare.h @@ -113,4 +113,11 @@ bool ARROW_EXPORT TypeEquals(const DataType& left, const DataType& right, /// \param[in] right a Scalar bool ARROW_EXPORT ScalarEquals(const Scalar& left, const Scalar& right); +/// Returns true if scalars are equal +/// \param[in] left a Scalar +/// \param[in] right a Scalar +/// \param[in] options comparison options +bool ARROW_EXPORT ScalarEquals(const Scalar& left, const Scalar& right, + const EqualOptions& options); + } // namespace arrow diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc index e56203bdfc3..347ad15bcac 100644 --- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc +++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +#include + #include "arrow/compute/kernels/common.h" #include "arrow/util/int_util_internal.h" #include "arrow/util/macros.h" @@ -191,8 +193,15 @@ struct Divide { template static enable_if_floating_point Call(KernelContext* ctx, Arg0 left, Arg1 right) { if (ARROW_PREDICT_FALSE(right == 0)) { - ctx->SetStatus(Status::Invalid("divide by zero")); - return 0; + if (left == 0) { + return static_cast(NAN); + } else { + if (std::signbit(left) == std::signbit(right)) { + return std::numeric_limits::infinity(); + } else { + return -std::numeric_limits::infinity(); + } + } } return left / right; } diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc index ea24089a06d..f6d28daa558 100644 --- a/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc @@ -144,7 +144,8 @@ class TestBinaryArithmetic : public TestBase { const auto expected_scalar = *expected->GetScalar(i); ASSERT_OK_AND_ASSIGN( actual, func(*left->GetScalar(i), *right->GetScalar(i), options_, nullptr)); - AssertScalarsEqual(*expected_scalar, *actual.scalar(), /*verbose=*/true); + AssertScalarsEqual(*expected_scalar, *actual.scalar(), /*verbose=*/true, + equal_options_); } } @@ -165,12 +166,17 @@ class TestBinaryArithmetic : public TestBase { void ValidateAndAssertApproxEqual(const std::shared_ptr& actual, const std::shared_ptr& expected) { ASSERT_OK(actual->ValidateFull()); - AssertArraysApproxEqual(*expected, *actual, /*verbose=*/true); + AssertArraysApproxEqual(*expected, *actual, /*verbose=*/true, equal_options_); } void SetOverflowCheck(bool value = true) { options_.check_overflow = value; } + void SetNansEqual(bool value = false) { + this->equal_options_ = equal_options_.nans_equal(value); + } + ArithmeticOptions options_ = ArithmeticOptions(); + EqualOptions equal_options_ = EqualOptions(); }; template @@ -557,10 +563,17 @@ TYPED_TEST(TestBinaryArithmeticIntegral, DivideByZero) { } TYPED_TEST(TestBinaryArithmeticFloating, DivideByZero) { - for (auto check_overflow : {false, true}) { - this->SetOverflowCheck(check_overflow); - this->AssertBinopRaises(Divide, "[3.0, 2.0, 6.0]", "[1.0, 1.0, 0]", "divide by zero"); - } + this->SetOverflowCheck(true); + this->AssertBinopRaises(Divide, "[3.0, 2.0, 6.0]", "[1.0, 1.0, 0.0]", "divide by zero"); + this->AssertBinopRaises(Divide, "[3.0, 2.0, 0.0]", "[1.0, 1.0, 0.0]", "divide by zero"); + this->AssertBinopRaises(Divide, "[3.0, 2.0, -6.0]", "[1.0, 1.0, 0.0]", + "divide by zero"); + + this->SetOverflowCheck(false); + this->SetNansEqual(true); + this->AssertBinop(Divide, "[3.0, 2.0, 6.0]", "[1.0, 1.0, 0.0]", "[3.0, 2.0, Inf]"); + this->AssertBinop(Divide, "[3.0, 2.0, 0.0]", "[1.0, 1.0, 0.0]", "[3.0, 2.0, NaN]"); + this->AssertBinop(Divide, "[3.0, 2.0, -6.0]", "[1.0, 1.0, 0.0]", "[3.0, 2.0, -Inf]"); } TYPED_TEST(TestBinaryArithmeticSigned, DivideOverflowRaises) { diff --git a/cpp/src/arrow/scalar.cc b/cpp/src/arrow/scalar.cc index b953177a459..ad89a16357b 100644 --- a/cpp/src/arrow/scalar.cc +++ b/cpp/src/arrow/scalar.cc @@ -40,6 +40,10 @@ namespace arrow { using internal::checked_cast; using internal::checked_pointer_cast; +bool Scalar::Equals(const Scalar& other, const EqualOptions& options) const { + return ScalarEquals(*this, other, options); +} + bool Scalar::Equals(const Scalar& other) const { return ScalarEquals(*this, other); } struct ScalarHashImpl { diff --git a/cpp/src/arrow/scalar.h b/cpp/src/arrow/scalar.h index d15c44ce9db..743fed36adb 100644 --- a/cpp/src/arrow/scalar.h +++ b/cpp/src/arrow/scalar.h @@ -28,6 +28,7 @@ #include #include +#include "arrow/compare.h" #include "arrow/result.h" #include "arrow/status.h" #include "arrow/type.h" @@ -62,6 +63,7 @@ struct ARROW_EXPORT Scalar : public util::EqualityComparable { using util::EqualityComparable::operator==; using util::EqualityComparable::Equals; bool Equals(const Scalar& other) const; + bool Equals(const Scalar& other, const EqualOptions& options) const; struct ARROW_EXPORT Hash { size_t operator()(const Scalar& scalar) const { return hash(scalar); } diff --git a/cpp/src/arrow/testing/gtest_util.cc b/cpp/src/arrow/testing/gtest_util.cc index b2f55668977..5a5ee4fe54a 100644 --- a/cpp/src/arrow/testing/gtest_util.cc +++ b/cpp/src/arrow/testing/gtest_util.cc @@ -136,21 +136,28 @@ void AssertArraysEqual(const Array& expected, const Array& actual, bool verbose) } void AssertArraysApproxEqual(const Array& expected, const Array& actual, bool verbose) { + const EqualOptions options; + return AssertArraysApproxEqual(expected, actual, verbose, options); +} + +void AssertArraysApproxEqual(const Array& expected, const Array& actual, bool verbose, + const EqualOptions& option) { return AssertArraysEqualWith( expected, actual, verbose, - [](const Array& expected, const Array& actual, std::stringstream* diff) { - return expected.ApproxEquals(actual, EqualOptions().diff_sink(diff)); + [&option](const Array& expected, const Array& actual, std::stringstream* diff) { + return expected.ApproxEquals(actual, option.diff_sink(diff)); }); } -void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbose) { +void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbose, + const EqualOptions& options) { std::stringstream diff; // ARROW-8956, ScalarEquals returns false when both are null if (!expected.is_valid && !actual.is_valid) { // We consider both being null to be equal in this function return; } - if (!expected.Equals(actual)) { + if (!expected.Equals(actual, options)) { if (verbose) { diff << "Expected:\n" << expected.ToString(); diff << "\nActual:\n" << actual.ToString(); @@ -159,6 +166,11 @@ void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbo } } +void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbose) { + const EqualOptions options; + AssertScalarsEqual(expected, actual, verbose, options); +} + void AssertBatchesEqual(const RecordBatch& expected, const RecordBatch& actual, bool check_metadata) { AssertTsSame(expected, actual, diff --git a/cpp/src/arrow/testing/gtest_util.h b/cpp/src/arrow/testing/gtest_util.h index 1411e705bcf..160218e4a78 100644 --- a/cpp/src/arrow/testing/gtest_util.h +++ b/cpp/src/arrow/testing/gtest_util.h @@ -167,9 +167,14 @@ ARROW_TESTING_EXPORT void AssertArraysEqual(const Array& expected, const Array& ARROW_TESTING_EXPORT void AssertArraysApproxEqual(const Array& expected, const Array& actual, bool verbose = false); +ARROW_TESTING_EXPORT void AssertArraysApproxEqual(const Array& expected, + const Array& actual, bool verbose, + const EqualOptions& option); // Returns true when values are both null ARROW_TESTING_EXPORT void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbose = false); +ARROW_TESTING_EXPORT void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, + bool verbose, const EqualOptions& options); ARROW_TESTING_EXPORT void AssertBatchesEqual(const RecordBatch& expected, const RecordBatch& actual, bool check_metadata = false); From f749eade57280013d3ace47c979ffbeb3319b202 Mon Sep 17 00:00:00 2001 From: liyafan82 Date: Thu, 27 Aug 2020 15:57:34 +0800 Subject: [PATCH 2/3] ARROW-9811: [C++] Resolve comments --- cpp/src/arrow/compare.cc | 13 +++---------- cpp/src/arrow/compare.h | 7 +------ .../arrow/compute/kernels/scalar_arithmetic.cc | 18 ++++++------------ .../compute/kernels/scalar_arithmetic_test.cc | 7 +++++-- cpp/src/arrow/scalar.cc | 2 -- cpp/src/arrow/scalar.h | 4 ++-- cpp/src/arrow/testing/gtest_util.cc | 10 ---------- cpp/src/arrow/testing/gtest_util.h | 16 ++++++---------- 8 files changed, 23 insertions(+), 54 deletions(-) diff --git a/cpp/src/arrow/compare.cc b/cpp/src/arrow/compare.cc index f05d474cb6e..421ec139242 100644 --- a/cpp/src/arrow/compare.cc +++ b/cpp/src/arrow/compare.cc @@ -862,10 +862,8 @@ class TypeEqualsVisitor { class ScalarEqualsVisitor { public: - explicit ScalarEqualsVisitor(const Scalar& right) - : right_(right), result_(false), options_(EqualOptions()) {} - - explicit ScalarEqualsVisitor(const Scalar& right, const EqualOptions& opts) + explicit ScalarEqualsVisitor(const Scalar& right, + const EqualOptions& opts = EqualOptions::Defaults()) : right_(right), result_(false), options_(opts) {} Status Visit(const NullScalar& left) { @@ -989,7 +987,7 @@ class ScalarEqualsVisitor { protected: const Scalar& right_; bool result_; - EqualOptions options_; + const EqualOptions options_; }; Status PrintDiff(const Array& left, const Array& right, std::ostream* os) { @@ -1425,9 +1423,4 @@ bool ScalarEquals(const Scalar& left, const Scalar& right, const EqualOptions& o return are_equal; } -bool ScalarEquals(const Scalar& left, const Scalar& right) { - const EqualOptions options; - return ScalarEquals(left, right, options); -} - } // namespace arrow diff --git a/cpp/src/arrow/compare.h b/cpp/src/arrow/compare.h index 84e7cf8760c..f7899b7c5c6 100644 --- a/cpp/src/arrow/compare.h +++ b/cpp/src/arrow/compare.h @@ -108,16 +108,11 @@ bool ARROW_EXPORT ArrayRangeEquals(const Array& left, const Array& right, bool ARROW_EXPORT TypeEquals(const DataType& left, const DataType& right, bool check_metadata = true); -/// Returns true if scalars are equal -/// \param[in] left a Scalar -/// \param[in] right a Scalar -bool ARROW_EXPORT ScalarEquals(const Scalar& left, const Scalar& right); - /// Returns true if scalars are equal /// \param[in] left a Scalar /// \param[in] right a Scalar /// \param[in] options comparison options bool ARROW_EXPORT ScalarEquals(const Scalar& left, const Scalar& right, - const EqualOptions& options); + const EqualOptions& options = EqualOptions::Defaults()); } // namespace arrow diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc index 347ad15bcac..dcb8e1fcc5f 100644 --- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc +++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +#include #include #include "arrow/compute/kernels/common.h" @@ -192,18 +193,11 @@ struct MultiplyChecked { struct Divide { template static enable_if_floating_point Call(KernelContext* ctx, Arg0 left, Arg1 right) { - if (ARROW_PREDICT_FALSE(right == 0)) { - if (left == 0) { - return static_cast(NAN); - } else { - if (std::signbit(left) == std::signbit(right)) { - return std::numeric_limits::infinity(); - } else { - return -std::numeric_limits::infinity(); - } - } - } - return left / right; + fenv_t original_env; + std::feholdexcept(&original_env); + T result = left / right; + std::fesetenv(&original_env); + return result; } template diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc index f6d28daa558..9b3ed2a57e3 100644 --- a/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic_test.cc @@ -171,12 +171,12 @@ class TestBinaryArithmetic : public TestBase { void SetOverflowCheck(bool value = true) { options_.check_overflow = value; } - void SetNansEqual(bool value = false) { + void SetNansEqual(bool value = true) { this->equal_options_ = equal_options_.nans_equal(value); } ArithmeticOptions options_ = ArithmeticOptions(); - EqualOptions equal_options_ = EqualOptions(); + EqualOptions equal_options_ = EqualOptions::Defaults(); }; template @@ -516,6 +516,9 @@ TYPED_TEST(TestBinaryArithmeticFloating, Div) { "[null, 0.1, 0.25, null, 0.2, 0.5]"); // Array with infinity this->AssertBinop(Divide, "[3.4, Inf, -Inf]", "[1, 2, 3]", "[3.4, Inf, -Inf]"); + // Array with NaN + this->SetNansEqual(true); + this->AssertBinop(Divide, "[3.4, NaN, 2.0]", "[1, 2, 2.0]", "[3.4, NaN, 1.0]"); // Scalar divides by scalar this->AssertBinop(Divide, 21.0F, 3.0F, 7.0F); } diff --git a/cpp/src/arrow/scalar.cc b/cpp/src/arrow/scalar.cc index ad89a16357b..88e594e9b19 100644 --- a/cpp/src/arrow/scalar.cc +++ b/cpp/src/arrow/scalar.cc @@ -44,8 +44,6 @@ bool Scalar::Equals(const Scalar& other, const EqualOptions& options) const { return ScalarEquals(*this, other, options); } -bool Scalar::Equals(const Scalar& other) const { return ScalarEquals(*this, other); } - struct ScalarHashImpl { static std::hash string_hash; diff --git a/cpp/src/arrow/scalar.h b/cpp/src/arrow/scalar.h index 743fed36adb..4a007dd8782 100644 --- a/cpp/src/arrow/scalar.h +++ b/cpp/src/arrow/scalar.h @@ -62,8 +62,8 @@ struct ARROW_EXPORT Scalar : public util::EqualityComparable { using util::EqualityComparable::operator==; using util::EqualityComparable::Equals; - bool Equals(const Scalar& other) const; - bool Equals(const Scalar& other, const EqualOptions& options) const; + bool Equals(const Scalar& other, + const EqualOptions& options = EqualOptions::Defaults()) const; struct ARROW_EXPORT Hash { size_t operator()(const Scalar& scalar) const { return hash(scalar); } diff --git a/cpp/src/arrow/testing/gtest_util.cc b/cpp/src/arrow/testing/gtest_util.cc index 5a5ee4fe54a..75cd204e1b2 100644 --- a/cpp/src/arrow/testing/gtest_util.cc +++ b/cpp/src/arrow/testing/gtest_util.cc @@ -135,11 +135,6 @@ void AssertArraysEqual(const Array& expected, const Array& actual, bool verbose) }); } -void AssertArraysApproxEqual(const Array& expected, const Array& actual, bool verbose) { - const EqualOptions options; - return AssertArraysApproxEqual(expected, actual, verbose, options); -} - void AssertArraysApproxEqual(const Array& expected, const Array& actual, bool verbose, const EqualOptions& option) { return AssertArraysEqualWith( @@ -166,11 +161,6 @@ void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbo } } -void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, bool verbose) { - const EqualOptions options; - AssertScalarsEqual(expected, actual, verbose, options); -} - void AssertBatchesEqual(const RecordBatch& expected, const RecordBatch& actual, bool check_metadata) { AssertTsSame(expected, actual, diff --git a/cpp/src/arrow/testing/gtest_util.h b/cpp/src/arrow/testing/gtest_util.h index 160218e4a78..fd72b5a88c3 100644 --- a/cpp/src/arrow/testing/gtest_util.h +++ b/cpp/src/arrow/testing/gtest_util.h @@ -164,17 +164,13 @@ std::vector AllTypeIds(); // If verbose is true, then the arrays will be pretty printed ARROW_TESTING_EXPORT void AssertArraysEqual(const Array& expected, const Array& actual, bool verbose = false); -ARROW_TESTING_EXPORT void AssertArraysApproxEqual(const Array& expected, - const Array& actual, - bool verbose = false); -ARROW_TESTING_EXPORT void AssertArraysApproxEqual(const Array& expected, - const Array& actual, bool verbose, - const EqualOptions& option); +ARROW_TESTING_EXPORT void AssertArraysApproxEqual( + const Array& expected, const Array& actual, bool verbose = false, + const EqualOptions& option = EqualOptions::Defaults()); // Returns true when values are both null -ARROW_TESTING_EXPORT void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, - bool verbose = false); -ARROW_TESTING_EXPORT void AssertScalarsEqual(const Scalar& expected, const Scalar& actual, - bool verbose, const EqualOptions& options); +ARROW_TESTING_EXPORT void AssertScalarsEqual( + const Scalar& expected, const Scalar& actual, bool verbose = false, + const EqualOptions& options = EqualOptions::Defaults()); ARROW_TESTING_EXPORT void AssertBatchesEqual(const RecordBatch& expected, const RecordBatch& actual, bool check_metadata = false); From 99fd02ff65c8b25737d1a28f5e428c6c5aea1556 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 27 Aug 2020 12:29:55 +0200 Subject: [PATCH 3/3] Remove FP state handling and instead set the right UBSAN option --- cpp/cmake_modules/san-config.cmake | 7 +++++-- cpp/src/arrow/compute/kernels/scalar_arithmetic.cc | 9 +-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/cpp/cmake_modules/san-config.cmake b/cpp/cmake_modules/san-config.cmake index 2e2807801fb..5eee6278009 100644 --- a/cpp/cmake_modules/san-config.cmake +++ b/cpp/cmake_modules/san-config.cmake @@ -35,14 +35,17 @@ endif() # - disable 'vptr' because of RTTI issues across shared libraries (?) # - disable 'alignment' because unaligned access is really OK on Nehalem and we do it # all over the place. -# - disable 'function' because it appears to give a false positive https://github.com/google/sanitizers/issues/911 +# - disable 'function' because it appears to give a false positive +# (https://github.com/google/sanitizers/issues/911) +# - disable 'float-divide-by-zero' on clang, which considers it UB +# (https://bugs.llvm.org/show_bug.cgi?id=17000#c1) # Note: GCC does not support the 'function' flag. if(${ARROW_USE_UBSAN}) if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set( CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize=alignment,vptr,function -fno-sanitize-recover=all" + "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize=alignment,vptr,function,float-divide-by-zero -fno-sanitize-recover=all" ) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "5.1") diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc index dcb8e1fcc5f..ff6c6fab7c6 100644 --- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc +++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc @@ -15,9 +15,6 @@ // specific language governing permissions and limitations // under the License. -#include -#include - #include "arrow/compute/kernels/common.h" #include "arrow/util/int_util_internal.h" #include "arrow/util/macros.h" @@ -193,11 +190,7 @@ struct MultiplyChecked { struct Divide { template static enable_if_floating_point Call(KernelContext* ctx, Arg0 left, Arg1 right) { - fenv_t original_env; - std::feholdexcept(&original_env); - T result = left / right; - std::fesetenv(&original_env); - return result; + return left / right; } template