1 //===-- Utility class to test different flavors of float add ----*- C++ -*-===// 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_ADDTEST_H 10 #define LLVM_LIBC_TEST_SRC_MATH_SMOKE_ADDTEST_H 11 12 #include "hdr/errno_macros.h" 13 #include "hdr/fenv_macros.h" 14 #include "src/__support/FPUtil/BasicOperations.h" 15 #include "src/__support/macros/properties/os.h" 16 #include "test/UnitTest/FEnvSafeTest.h" 17 #include "test/UnitTest/FPMatcher.h" 18 #include "test/UnitTest/Test.h" 19 20 using LIBC_NAMESPACE::Sign; 21 22 template <typename OutType, typename InType> 23 class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 24 25 DECLARE_SPECIAL_CONSTANTS(OutType) 26 27 struct InConstants { 28 DECLARE_SPECIAL_CONSTANTS(InType) 29 }; 30 31 using InFPBits = typename InConstants::FPBits; 32 using InStorageType = typename InConstants::StorageType; 33 34 InConstants in; 35 36 public: 37 using AddFunc = OutType (*)(InType, InType); 38 test_special_numbers(AddFunc func)39 void test_special_numbers(AddFunc func) { 40 EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN)); 41 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID); 42 43 InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val(); 44 EXPECT_FP_IS_NAN(func(qnan_42, in.zero)); 45 EXPECT_FP_IS_NAN(func(in.zero, qnan_42)); 46 47 EXPECT_FP_EQ(inf, func(in.inf, in.zero)); 48 EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero)); 49 EXPECT_FP_EQ(inf, func(in.inf, in.neg_zero)); 50 EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.neg_zero)); 51 } 52 test_invalid_operations(AddFunc func)53 void test_invalid_operations(AddFunc func) { 54 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_inf), FE_INVALID); 55 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.inf), FE_INVALID); 56 } 57 test_range_errors(AddFunc func)58 void test_range_errors(AddFunc func) { 59 #ifndef LIBC_TARGET_OS_IS_WINDOWS 60 using namespace LIBC_NAMESPACE::fputil::testing; 61 62 if (ForceRoundingMode r(RoundingMode::Nearest); r.success) { 63 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal), 64 FE_OVERFLOW | FE_INEXACT); 65 EXPECT_MATH_ERRNO(ERANGE); 66 EXPECT_FP_EQ_WITH_EXCEPTION(-inf, 67 func(in.neg_max_normal, in.neg_max_normal), 68 FE_OVERFLOW | FE_INEXACT); 69 EXPECT_MATH_ERRNO(ERANGE); 70 71 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal), 72 FE_UNDERFLOW | FE_INEXACT); 73 EXPECT_MATH_ERRNO(ERANGE); 74 EXPECT_FP_EQ_WITH_EXCEPTION( 75 neg_zero, func(in.neg_min_denormal, in.neg_min_denormal), 76 FE_UNDERFLOW | FE_INEXACT); 77 EXPECT_MATH_ERRNO(ERANGE); 78 } 79 80 if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) { 81 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, 82 func(in.max_normal, in.max_normal), 83 FE_OVERFLOW | FE_INEXACT); 84 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal, 85 func(in.neg_max_normal, in.neg_max_normal), 86 FE_OVERFLOW | FE_INEXACT); 87 88 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal), 89 FE_UNDERFLOW | FE_INEXACT); 90 EXPECT_MATH_ERRNO(ERANGE); 91 EXPECT_FP_EQ_WITH_EXCEPTION( 92 neg_zero, func(in.neg_min_denormal, in.neg_min_denormal), 93 FE_UNDERFLOW | FE_INEXACT); 94 EXPECT_MATH_ERRNO(ERANGE); 95 } 96 97 if (ForceRoundingMode r(RoundingMode::Downward); r.success) { 98 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, 99 func(in.max_normal, in.max_normal), 100 FE_OVERFLOW | FE_INEXACT); 101 EXPECT_FP_EQ_WITH_EXCEPTION(-inf, 102 func(in.neg_max_normal, in.neg_max_normal), 103 FE_OVERFLOW | FE_INEXACT); 104 EXPECT_MATH_ERRNO(ERANGE); 105 106 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal), 107 FE_UNDERFLOW | FE_INEXACT); 108 EXPECT_MATH_ERRNO(ERANGE); 109 EXPECT_FP_EQ_WITH_EXCEPTION( 110 neg_min_denormal, func(in.neg_min_denormal, in.neg_min_denormal), 111 FE_UNDERFLOW | FE_INEXACT); 112 EXPECT_MATH_ERRNO(ERANGE); 113 } 114 115 if (ForceRoundingMode r(RoundingMode::Upward); r.success) { 116 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal), 117 FE_OVERFLOW | FE_INEXACT); 118 EXPECT_MATH_ERRNO(ERANGE); 119 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal, 120 func(in.neg_max_normal, in.neg_max_normal), 121 FE_OVERFLOW | FE_INEXACT); 122 123 EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal, 124 func(in.min_denormal, in.min_denormal), 125 FE_UNDERFLOW | FE_INEXACT); 126 EXPECT_MATH_ERRNO(ERANGE); 127 EXPECT_FP_EQ_WITH_EXCEPTION( 128 neg_zero, func(in.neg_min_denormal, in.neg_min_denormal), 129 FE_UNDERFLOW | FE_INEXACT); 130 EXPECT_MATH_ERRNO(ERANGE); 131 } 132 #endif 133 } 134 test_inexact_results(AddFunc func)135 void test_inexact_results(AddFunc func) { 136 func(InType(1.0), in.min_denormal); 137 EXPECT_FP_EXCEPTION(FE_INEXACT); 138 } 139 }; 140 141 #define LIST_ADD_TESTS(OutType, InType, func) \ 142 using LlvmLibcAddTest = AddTest<OutType, InType>; \ 143 TEST_F(LlvmLibcAddTest, SpecialNumbers) { test_special_numbers(&func); } \ 144 TEST_F(LlvmLibcAddTest, InvalidOperations) { \ 145 test_invalid_operations(&func); \ 146 } \ 147 TEST_F(LlvmLibcAddTest, RangeErrors) { test_range_errors(&func); } \ 148 TEST_F(LlvmLibcAddTest, InexactResults) { test_inexact_results(&func); } 149 150 #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_ADDTEST_H 151