| //===-- Unittests for shared math check exception functions ---------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "shared/math_check_exceptions.h" |
| #include "src/__support/CPP/array.h" |
| #include "src/__support/math/check/exp_exceptions.h" |
| #include "test/UnitTest/FPMatcher.h" |
| #include "test/UnitTest/Test.h" |
| |
| template <typename T> |
| class CheckExpTest : public LIBC_NAMESPACE::testing::Test { |
| |
| DECLARE_SPECIAL_CONSTANTS(T) |
| |
| public: |
| void run_test() { |
| using LIBC_NAMESPACE::shared::check::exp_exceptions; |
| using IntArray = LIBC_NAMESPACE::cpp::array<int, 4>; |
| using Bounds = LIBC_NAMESPACE::math::check::exp_internal::Bounds<T>; |
| |
| constexpr IntArray ROUNDING_MODES = {FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, |
| FE_TOWARDZERO}; |
| for (auto rm : ROUNDING_MODES) { |
| EXPECT_EQ(FE_INVALID, exp_exceptions(sNaN, rm)); |
| EXPECT_EQ(FE_INVALID, exp_exceptions(neg_sNaN, rm)); |
| EXPECT_EQ(0, exp_exceptions(aNaN, rm)); |
| EXPECT_EQ(0, exp_exceptions(neg_aNaN, rm)); |
| EXPECT_EQ(0, exp_exceptions(inf, rm)); |
| EXPECT_EQ(0, exp_exceptions(neg_inf, rm)); |
| EXPECT_EQ(0, exp_exceptions(zero, rm)); |
| EXPECT_EQ(0, exp_exceptions(neg_zero, rm)); |
| EXPECT_EQ(FE_UNDERFLOW, |
| exp_exceptions(neg_max_normal, rm) & FE_UNDERFLOW); |
| EXPECT_EQ(FE_UNDERFLOW, exp_exceptions(Bounds::LOWER, rm) & FE_UNDERFLOW); |
| EXPECT_EQ(0, exp_exceptions(T(1), rm) & (~FE_INEXACT)); |
| } |
| |
| EXPECT_EQ(FE_OVERFLOW, |
| exp_exceptions(max_normal, FE_TONEAREST) & FE_OVERFLOW); |
| EXPECT_EQ(FE_OVERFLOW, exp_exceptions(max_normal, FE_UPWARD) & FE_OVERFLOW); |
| EXPECT_EQ(0, exp_exceptions(max_normal, FE_DOWNWARD) & FE_OVERFLOW); |
| EXPECT_EQ(0, exp_exceptions(max_normal, FE_TOWARDZERO) & FE_OVERFLOW); |
| |
| EXPECT_EQ(FE_OVERFLOW, |
| exp_exceptions(Bounds::UPPER, FE_TONEAREST) & FE_OVERFLOW); |
| EXPECT_EQ(FE_OVERFLOW, |
| exp_exceptions(Bounds::UPPER, FE_UPWARD) & FE_OVERFLOW); |
| EXPECT_EQ(0, exp_exceptions(Bounds::UPPER, FE_DOWNWARD) & FE_OVERFLOW); |
| EXPECT_EQ(0, exp_exceptions(Bounds::UPPER, FE_TOWARDZERO) & FE_OVERFLOW); |
| } |
| }; |
| |
| using LlvmLibcCheckExpTestFloat = CheckExpTest<float>; |
| using LlvmLibcCheckExpTestDouble = CheckExpTest<double>; |
| |
| TEST_F(LlvmLibcCheckExpTestFloat, CheckExpfExceptions) { run_test(); } |
| TEST_F(LlvmLibcCheckExpTestDouble, CheckExpExceptions) { run_test(); } |