165 lines · c
1//===-- Utility class to test different flavors of float mul ----*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H10#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H11 12#include "hdr/errno_macros.h"13#include "hdr/fenv_macros.h"14#include "src/__support/FPUtil/BasicOperations.h"15#include "test/UnitTest/FEnvSafeTest.h"16#include "test/UnitTest/FPMatcher.h"17#include "test/UnitTest/Test.h"18 19using LIBC_NAMESPACE::Sign;20 21template <typename OutType, typename InType>22class MulTest : 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 MulFunc = OutType (*)(InType, InType);37 38 void test_special_numbers(MulFunc 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, InType(1.0)));47 EXPECT_FP_EQ(neg_inf, func(in.neg_inf, InType(1.0)));48 EXPECT_FP_EQ(neg_inf, func(in.inf, InType(-1.0)));49 EXPECT_FP_EQ(inf, func(in.neg_inf, InType(-1.0)));50 51 EXPECT_FP_EQ_ALL_ROUNDING(zero, func(in.zero, in.zero));52 EXPECT_FP_EQ_ALL_ROUNDING(zero, func(in.neg_zero, in.neg_zero));53 EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(in.zero, in.neg_zero));54 EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(in.neg_zero, in.zero));55 56 EXPECT_FP_EQ_ALL_ROUNDING(OutType(1.0), func(InType(1.0), InType(1.0)));57 EXPECT_FP_EQ_ALL_ROUNDING(OutType(15.0), func(InType(3.0), InType(5.0)));58 EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-13),59 func(InType(0x1.0p+1), InType(0x1.0p-14)));60 EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-10),61 func(InType(0x1.0p+2), InType(0x1.0p-12)));62 }63 64 void test_invalid_operations(MulFunc func) {65 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.zero), FE_INVALID);66 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_zero), FE_INVALID);67 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.zero), FE_INVALID);68 EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_zero), FE_INVALID);69 }70 71 void test_range_errors(MulFunc func) {72 using namespace LIBC_NAMESPACE::fputil::testing;73 74 if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {75 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal),76 FE_OVERFLOW | FE_INEXACT);77 EXPECT_MATH_ERRNO(ERANGE);78 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf,79 func(in.neg_max_normal, in.max_normal),80 FE_OVERFLOW | FE_INEXACT);81 EXPECT_MATH_ERRNO(ERANGE);82 83 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),84 FE_UNDERFLOW | FE_INEXACT);85 EXPECT_MATH_ERRNO(ERANGE);86 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,87 func(in.neg_min_denormal, in.min_denormal),88 FE_UNDERFLOW | FE_INEXACT);89 EXPECT_MATH_ERRNO(ERANGE);90 }91 92 if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {93 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,94 func(in.max_normal, in.max_normal),95 FE_OVERFLOW | FE_INEXACT);96 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,97 func(in.neg_max_normal, in.max_normal),98 FE_OVERFLOW | FE_INEXACT);99 100 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),101 FE_UNDERFLOW | FE_INEXACT);102 EXPECT_MATH_ERRNO(ERANGE);103 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,104 func(in.neg_min_denormal, in.min_denormal),105 FE_UNDERFLOW | FE_INEXACT);106 EXPECT_MATH_ERRNO(ERANGE);107 }108 109 if (ForceRoundingMode r(RoundingMode::Downward); r.success) {110 EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,111 func(in.max_normal, in.max_normal),112 FE_OVERFLOW | FE_INEXACT);113 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf,114 func(in.neg_max_normal, in.max_normal),115 FE_OVERFLOW | FE_INEXACT);116 EXPECT_MATH_ERRNO(ERANGE);117 118 EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),119 FE_UNDERFLOW | FE_INEXACT);120 EXPECT_MATH_ERRNO(ERANGE);121 EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,122 func(in.neg_min_denormal, in.min_denormal),123 FE_UNDERFLOW | FE_INEXACT);124 EXPECT_MATH_ERRNO(ERANGE);125 }126 127 if (ForceRoundingMode r(RoundingMode::Upward); r.success) {128 EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal),129 FE_OVERFLOW | FE_INEXACT);130 EXPECT_MATH_ERRNO(ERANGE);131 EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,132 func(in.neg_max_normal, in.max_normal),133 FE_OVERFLOW | FE_INEXACT);134 135 EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,136 func(in.min_denormal, in.min_denormal),137 FE_UNDERFLOW | FE_INEXACT);138 EXPECT_MATH_ERRNO(ERANGE);139 EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,140 func(in.neg_min_denormal, in.min_denormal),141 FE_UNDERFLOW | FE_INEXACT);142 EXPECT_MATH_ERRNO(ERANGE);143 }144 }145 146 void test_inexact_results(MulFunc func) {147 InFPBits x_bits = InFPBits::one();148 x_bits.set_mantissa(InFPBits::SIG_MASK);149 InType x = x_bits.get_val();150 func(x, x);151 EXPECT_FP_EXCEPTION(FE_INEXACT);152 }153};154 155#define LIST_MUL_TESTS(OutType, InType, func) \156 using LlvmLibcMulTest = MulTest<OutType, InType>; \157 TEST_F(LlvmLibcMulTest, SpecialNumbers) { test_special_numbers(&func); } \158 TEST_F(LlvmLibcMulTest, InvalidOperations) { \159 test_invalid_operations(&func); \160 } \161 TEST_F(LlvmLibcMulTest, RangeErrors) { test_range_errors(&func); } \162 TEST_F(LlvmLibcMulTest, InexactResults) { test_inexact_results(&func); }163 164#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H165