xref: /llvm-project/libc/test/src/math/smoke/AddTest.h (revision f6b2a222beed734df1d91bd5c165a5233c19fddb)
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