174 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H10#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H11 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 19using LIBC_NAMESPACE::Sign;20 21template <typename OutType, typename InType>22class 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 35public:36 using DivFunc = OutType (*)(InType, InType);37 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 EXPECT_FP_EQ(zero, func(in.min_normal, in.inf));51 EXPECT_FP_EQ(zero, func(in.zero, in.inf));52 EXPECT_FP_EQ(zero, func(in.neg_zero, in.neg_inf));53 EXPECT_FP_EQ(neg_zero, func(in.min_normal, in.neg_inf));54 EXPECT_FP_EQ(neg_zero, func(in.zero, in.neg_inf));55 }56 57 void test_division_by_zero(DivFunc func) {58 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), in.zero), FE_DIVBYZERO);59 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(-1.0), in.zero),60 FE_DIVBYZERO);61 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(1.0), in.neg_zero),62 FE_DIVBYZERO);63 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), in.zero), FE_DIVBYZERO);64 }65 66 void test_invalid_operations(DivFunc func) {67 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.zero, in.zero), FE_INVALID);68 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_zero, in.zero), FE_INVALID);69 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.zero, in.neg_zero), FE_INVALID);70 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_zero, in.neg_zero), FE_INVALID);71 72 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.inf), FE_INVALID);73 EXPECT_MATH_ERRNO(EDOM);74 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.inf), FE_INVALID);75 EXPECT_MATH_ERRNO(EDOM);76 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_inf), FE_INVALID);77 EXPECT_MATH_ERRNO(EDOM);78 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_inf), FE_INVALID);79 EXPECT_MATH_ERRNO(EDOM);80 }81 82 void test_range_errors(DivFunc func) {83 using namespace LIBC_NAMESPACE::fputil::testing;84 85 if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {86 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.min_normal),87 FE_OVERFLOW | FE_INEXACT);88 EXPECT_MATH_ERRNO(ERANGE);89 EXPECT_FP_EQ_WITH_EXCEPTION(-inf,90 func(in.neg_max_normal, in.min_denormal),91 FE_OVERFLOW | FE_INEXACT);92 EXPECT_MATH_ERRNO(ERANGE);93 94 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal),95 FE_UNDERFLOW | FE_INEXACT);96 EXPECT_MATH_ERRNO(ERANGE);97 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,98 func(in.neg_min_denormal, in.max_normal),99 FE_UNDERFLOW | FE_INEXACT);100 EXPECT_MATH_ERRNO(ERANGE);101 }102 103 if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {104 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,105 func(in.max_normal, in.min_normal),106 FE_OVERFLOW | FE_INEXACT);107 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,108 func(in.neg_max_normal, in.min_denormal),109 FE_OVERFLOW | FE_INEXACT);110 111 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal),112 FE_UNDERFLOW | FE_INEXACT);113 EXPECT_MATH_ERRNO(ERANGE);114 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,115 func(in.neg_min_denormal, in.max_normal),116 FE_UNDERFLOW | FE_INEXACT);117 EXPECT_MATH_ERRNO(ERANGE);118 }119 120 if (ForceRoundingMode r(RoundingMode::Downward); r.success) {121 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,122 func(in.max_normal, in.min_normal),123 FE_OVERFLOW | FE_INEXACT);124 EXPECT_FP_EQ_WITH_EXCEPTION(-inf,125 func(in.neg_max_normal, in.min_denormal),126 FE_OVERFLOW | FE_INEXACT);127 EXPECT_MATH_ERRNO(ERANGE);128 129 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal),130 FE_UNDERFLOW | FE_INEXACT);131 EXPECT_MATH_ERRNO(ERANGE);132 EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,133 func(in.neg_min_denormal, in.max_normal),134 FE_UNDERFLOW | FE_INEXACT);135 EXPECT_MATH_ERRNO(ERANGE);136 }137 138 if (ForceRoundingMode r(RoundingMode::Upward); r.success) {139 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.min_normal),140 FE_OVERFLOW | FE_INEXACT);141 EXPECT_MATH_ERRNO(ERANGE);142 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,143 func(in.neg_max_normal, in.min_denormal),144 FE_OVERFLOW | FE_INEXACT);145 146 EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,147 func(in.min_denormal, in.max_normal),148 FE_UNDERFLOW | FE_INEXACT);149 EXPECT_MATH_ERRNO(ERANGE);150 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,151 func(in.neg_min_denormal, in.max_normal),152 FE_UNDERFLOW | FE_INEXACT);153 EXPECT_MATH_ERRNO(ERANGE);154 }155 }156 157 void test_inexact_results(DivFunc func) {158 func(InType(1.0), InType(3.0));159 EXPECT_FP_EXCEPTION(FE_INEXACT);160 }161};162 163#define LIST_DIV_TESTS(OutType, InType, func) \164 using LlvmLibcDivTest = DivTest<OutType, InType>; \165 TEST_F(LlvmLibcDivTest, SpecialNumbers) { test_special_numbers(&func); } \166 TEST_F(LlvmLibcDivTest, DivisionByZero) { test_division_by_zero(&func); } \167 TEST_F(LlvmLibcDivTest, InvalidOperations) { \168 test_invalid_operations(&func); \169 } \170 TEST_F(LlvmLibcDivTest, RangeErrors) { test_range_errors(&func); } \171 TEST_F(LlvmLibcDivTest, InexactResults) { test_inexact_results(&func); }172 173#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H174