brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 5020067 Raw
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