1 //===-- Utility class to test different flavors of float div --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H 10 #define LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H 11 12 #include "hdr/errno_macros.h" 13 #include "hdr/fenv_macros.h" 14 #include "test/UnitTest/FEnvSafeTest.h" 15 #include "test/UnitTest/FPMatcher.h" 16 #include "test/UnitTest/RoundingModeUtils.h" 17 #include "test/UnitTest/Test.h" 18 19 using LIBC_NAMESPACE::Sign; 20 21 template <typename OutType, typename InType> 22 class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 23 24 DECLARE_SPECIAL_CONSTANTS(OutType) 25 26 struct InConstants { 27 DECLARE_SPECIAL_CONSTANTS(InType) 28 }; 29 30 using InFPBits = typename InConstants::FPBits; 31 using InStorageType = typename InConstants::StorageType; 32 33 InConstants in; 34 35 public: 36 using DivFunc = OutType (*)(InType, InType); 37 test_special_numbers(DivFunc func)38 void test_special_numbers(DivFunc func) { 39 EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN)); 40 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID); 41 42 InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val(); 43 EXPECT_FP_IS_NAN(func(qnan_42, in.zero)); 44 EXPECT_FP_IS_NAN(func(in.zero, qnan_42)); 45 46 EXPECT_FP_EQ(inf, func(in.inf, in.zero)); 47 EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero)); 48 EXPECT_FP_EQ(neg_inf, func(in.inf, in.neg_zero)); 49 EXPECT_FP_EQ(inf, func(in.neg_inf, in.neg_zero)); 50 } 51 test_division_by_zero(DivFunc func)52 void test_division_by_zero(DivFunc func) { 53 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), in.zero), FE_DIVBYZERO); 54 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(-1.0), in.zero), 55 FE_DIVBYZERO); 56 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(1.0), in.neg_zero), 57 FE_DIVBYZERO); 58 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), in.zero), FE_DIVBYZERO); 59 } 60 test_invalid_operations(DivFunc func)61 void test_invalid_operations(DivFunc func) { 62 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.zero, in.zero), FE_INVALID); 63 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_zero, in.zero), FE_INVALID); 64 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.zero, in.neg_zero), FE_INVALID); 65 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_zero, in.neg_zero), FE_INVALID); 66 67 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.inf), FE_INVALID); 68 EXPECT_MATH_ERRNO(EDOM); 69 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.inf), FE_INVALID); 70 EXPECT_MATH_ERRNO(EDOM); 71 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_inf), FE_INVALID); 72 EXPECT_MATH_ERRNO(EDOM); 73 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_inf), FE_INVALID); 74 EXPECT_MATH_ERRNO(EDOM); 75 } 76 test_range_errors(DivFunc func)77 void test_range_errors(DivFunc func) { 78 using namespace LIBC_NAMESPACE::fputil::testing; 79 80 if (ForceRoundingMode r(RoundingMode::Nearest); r.success) { 81 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.min_normal), 82 FE_OVERFLOW | FE_INEXACT); 83 EXPECT_MATH_ERRNO(ERANGE); 84 EXPECT_FP_EQ_WITH_EXCEPTION(-inf, 85 func(in.neg_max_normal, in.min_denormal), 86 FE_OVERFLOW | FE_INEXACT); 87 EXPECT_MATH_ERRNO(ERANGE); 88 89 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal), 90 FE_UNDERFLOW | FE_INEXACT); 91 EXPECT_MATH_ERRNO(ERANGE); 92 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero, 93 func(in.neg_min_denormal, in.max_normal), 94 FE_UNDERFLOW | FE_INEXACT); 95 EXPECT_MATH_ERRNO(ERANGE); 96 } 97 98 if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) { 99 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, 100 func(in.max_normal, in.min_normal), 101 FE_OVERFLOW | FE_INEXACT); 102 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal, 103 func(in.neg_max_normal, in.min_denormal), 104 FE_OVERFLOW | FE_INEXACT); 105 106 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal), 107 FE_UNDERFLOW | FE_INEXACT); 108 EXPECT_MATH_ERRNO(ERANGE); 109 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero, 110 func(in.neg_min_denormal, in.max_normal), 111 FE_UNDERFLOW | FE_INEXACT); 112 EXPECT_MATH_ERRNO(ERANGE); 113 } 114 115 if (ForceRoundingMode r(RoundingMode::Downward); r.success) { 116 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, 117 func(in.max_normal, in.min_normal), 118 FE_OVERFLOW | FE_INEXACT); 119 EXPECT_FP_EQ_WITH_EXCEPTION(-inf, 120 func(in.neg_max_normal, in.min_denormal), 121 FE_OVERFLOW | FE_INEXACT); 122 EXPECT_MATH_ERRNO(ERANGE); 123 124 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal), 125 FE_UNDERFLOW | FE_INEXACT); 126 EXPECT_MATH_ERRNO(ERANGE); 127 EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal, 128 func(in.neg_min_denormal, in.max_normal), 129 FE_UNDERFLOW | FE_INEXACT); 130 EXPECT_MATH_ERRNO(ERANGE); 131 } 132 133 if (ForceRoundingMode r(RoundingMode::Upward); r.success) { 134 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.min_normal), 135 FE_OVERFLOW | FE_INEXACT); 136 EXPECT_MATH_ERRNO(ERANGE); 137 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal, 138 func(in.neg_max_normal, in.min_denormal), 139 FE_OVERFLOW | FE_INEXACT); 140 141 EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal, 142 func(in.min_denormal, in.max_normal), 143 FE_UNDERFLOW | FE_INEXACT); 144 EXPECT_MATH_ERRNO(ERANGE); 145 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero, 146 func(in.neg_min_denormal, in.max_normal), 147 FE_UNDERFLOW | FE_INEXACT); 148 EXPECT_MATH_ERRNO(ERANGE); 149 } 150 } 151 test_inexact_results(DivFunc func)152 void test_inexact_results(DivFunc func) { 153 func(InType(1.0), InType(3.0)); 154 EXPECT_FP_EXCEPTION(FE_INEXACT); 155 } 156 }; 157 158 #define LIST_DIV_TESTS(OutType, InType, func) \ 159 using LlvmLibcDivTest = DivTest<OutType, InType>; \ 160 TEST_F(LlvmLibcDivTest, SpecialNumbers) { test_special_numbers(&func); } \ 161 TEST_F(LlvmLibcDivTest, DivisionByZero) { test_division_by_zero(&func); } \ 162 TEST_F(LlvmLibcDivTest, InvalidOperations) { \ 163 test_invalid_operations(&func); \ 164 } \ 165 TEST_F(LlvmLibcDivTest, RangeErrors) { test_range_errors(&func); } \ 166 TEST_F(LlvmLibcDivTest, InexactResults) { test_inexact_results(&func); } 167 168 #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H 169