112a1e6ddSOverMighty //===-- Utility class to test different flavors of float add ----*- C++ -*-===// 212a1e6ddSOverMighty // 312a1e6ddSOverMighty // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 412a1e6ddSOverMighty // See https://llvm.org/LICENSE.txt for license information. 512a1e6ddSOverMighty // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 612a1e6ddSOverMighty // 712a1e6ddSOverMighty //===----------------------------------------------------------------------===// 812a1e6ddSOverMighty 912a1e6ddSOverMighty #ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_ADDTEST_H 1012a1e6ddSOverMighty #define LLVM_LIBC_TEST_SRC_MATH_SMOKE_ADDTEST_H 1112a1e6ddSOverMighty 1212a1e6ddSOverMighty #include "hdr/errno_macros.h" 1312a1e6ddSOverMighty #include "hdr/fenv_macros.h" 1412a1e6ddSOverMighty #include "src/__support/FPUtil/BasicOperations.h" 15ded08015SSirui Mu #include "src/__support/macros/properties/os.h" 1612a1e6ddSOverMighty #include "test/UnitTest/FEnvSafeTest.h" 1712a1e6ddSOverMighty #include "test/UnitTest/FPMatcher.h" 1812a1e6ddSOverMighty #include "test/UnitTest/Test.h" 1912a1e6ddSOverMighty 20*f6b2a222SMichael Jones using LIBC_NAMESPACE::Sign; 21*f6b2a222SMichael Jones 2212a1e6ddSOverMighty template <typename OutType, typename InType> 2312a1e6ddSOverMighty class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 2412a1e6ddSOverMighty 2512a1e6ddSOverMighty DECLARE_SPECIAL_CONSTANTS(OutType) 2612a1e6ddSOverMighty 2712a1e6ddSOverMighty struct InConstants { 2812a1e6ddSOverMighty DECLARE_SPECIAL_CONSTANTS(InType) 2912a1e6ddSOverMighty }; 3012a1e6ddSOverMighty 3112a1e6ddSOverMighty using InFPBits = typename InConstants::FPBits; 3212a1e6ddSOverMighty using InStorageType = typename InConstants::StorageType; 3312a1e6ddSOverMighty 3412a1e6ddSOverMighty InConstants in; 3512a1e6ddSOverMighty 3612a1e6ddSOverMighty public: 3712a1e6ddSOverMighty using AddFunc = OutType (*)(InType, InType); 3812a1e6ddSOverMighty 3912a1e6ddSOverMighty void test_special_numbers(AddFunc func) { 40127349fcSOverMighty EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN)); 41127349fcSOverMighty EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID); 4212a1e6ddSOverMighty 4312a1e6ddSOverMighty InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val(); 44127349fcSOverMighty EXPECT_FP_IS_NAN(func(qnan_42, in.zero)); 45127349fcSOverMighty EXPECT_FP_IS_NAN(func(in.zero, qnan_42)); 4612a1e6ddSOverMighty 47127349fcSOverMighty EXPECT_FP_EQ(inf, func(in.inf, in.zero)); 48127349fcSOverMighty EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero)); 49127349fcSOverMighty EXPECT_FP_EQ(inf, func(in.inf, in.neg_zero)); 50127349fcSOverMighty EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.neg_zero)); 5112a1e6ddSOverMighty } 5212a1e6ddSOverMighty 5312a1e6ddSOverMighty void test_invalid_operations(AddFunc func) { 54127349fcSOverMighty EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_inf), FE_INVALID); 55127349fcSOverMighty EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.inf), FE_INVALID); 5612a1e6ddSOverMighty } 5712a1e6ddSOverMighty 5812a1e6ddSOverMighty void test_range_errors(AddFunc func) { 59ded08015SSirui Mu #ifndef LIBC_TARGET_OS_IS_WINDOWS 6012a1e6ddSOverMighty using namespace LIBC_NAMESPACE::fputil::testing; 6112a1e6ddSOverMighty 6212a1e6ddSOverMighty if (ForceRoundingMode r(RoundingMode::Nearest); r.success) { 63127349fcSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal), 6412a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 6512a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 66127349fcSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(-inf, 67127349fcSOverMighty func(in.neg_max_normal, in.neg_max_normal), 6812a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 6912a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 7012a1e6ddSOverMighty 7112a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal), 7212a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 7312a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 7412a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION( 7512a1e6ddSOverMighty neg_zero, func(in.neg_min_denormal, in.neg_min_denormal), 7612a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 7712a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 7812a1e6ddSOverMighty } 7912a1e6ddSOverMighty 8012a1e6ddSOverMighty if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) { 81127349fcSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, 82127349fcSOverMighty func(in.max_normal, in.max_normal), 8312a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 8412a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal, 85127349fcSOverMighty func(in.neg_max_normal, in.neg_max_normal), 8612a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 8712a1e6ddSOverMighty 8812a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal), 8912a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 9012a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 9112a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION( 9212a1e6ddSOverMighty neg_zero, func(in.neg_min_denormal, in.neg_min_denormal), 9312a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 9412a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 9512a1e6ddSOverMighty } 9612a1e6ddSOverMighty 9712a1e6ddSOverMighty if (ForceRoundingMode r(RoundingMode::Downward); r.success) { 98127349fcSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, 99127349fcSOverMighty func(in.max_normal, in.max_normal), 10012a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 101127349fcSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(-inf, 102127349fcSOverMighty func(in.neg_max_normal, in.neg_max_normal), 10312a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 10412a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 10512a1e6ddSOverMighty 10612a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal), 10712a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 10812a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 10912a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION( 11012a1e6ddSOverMighty neg_min_denormal, func(in.neg_min_denormal, in.neg_min_denormal), 11112a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 11212a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 11312a1e6ddSOverMighty } 11412a1e6ddSOverMighty 11512a1e6ddSOverMighty if (ForceRoundingMode r(RoundingMode::Upward); r.success) { 116127349fcSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal), 11712a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 11812a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 11912a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal, 120127349fcSOverMighty func(in.neg_max_normal, in.neg_max_normal), 12112a1e6ddSOverMighty FE_OVERFLOW | FE_INEXACT); 12212a1e6ddSOverMighty 12312a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal, 12412a1e6ddSOverMighty func(in.min_denormal, in.min_denormal), 12512a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 12612a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 12712a1e6ddSOverMighty EXPECT_FP_EQ_WITH_EXCEPTION( 12812a1e6ddSOverMighty neg_zero, func(in.neg_min_denormal, in.neg_min_denormal), 12912a1e6ddSOverMighty FE_UNDERFLOW | FE_INEXACT); 13012a1e6ddSOverMighty EXPECT_MATH_ERRNO(ERANGE); 13112a1e6ddSOverMighty } 132ded08015SSirui Mu #endif 13312a1e6ddSOverMighty } 13412a1e6ddSOverMighty 13512a1e6ddSOverMighty void test_inexact_results(AddFunc func) { 136127349fcSOverMighty func(InType(1.0), in.min_denormal); 13712a1e6ddSOverMighty EXPECT_FP_EXCEPTION(FE_INEXACT); 13812a1e6ddSOverMighty } 13912a1e6ddSOverMighty }; 14012a1e6ddSOverMighty 14112a1e6ddSOverMighty #define LIST_ADD_TESTS(OutType, InType, func) \ 14212a1e6ddSOverMighty using LlvmLibcAddTest = AddTest<OutType, InType>; \ 14312a1e6ddSOverMighty TEST_F(LlvmLibcAddTest, SpecialNumbers) { test_special_numbers(&func); } \ 14412a1e6ddSOverMighty TEST_F(LlvmLibcAddTest, InvalidOperations) { \ 14512a1e6ddSOverMighty test_invalid_operations(&func); \ 14612a1e6ddSOverMighty } \ 14712a1e6ddSOverMighty TEST_F(LlvmLibcAddTest, RangeErrors) { test_range_errors(&func); } \ 14812a1e6ddSOverMighty TEST_F(LlvmLibcAddTest, InexactResults) { test_inexact_results(&func); } 14912a1e6ddSOverMighty 15012a1e6ddSOverMighty #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_ADDTEST_H 151