brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 0d775ac Raw
123 lines · c
1//===-- Utility class to test different flavors of fma --------------------===//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_FMATEST_H10#define LLVM_LIBC_TEST_SRC_MATH_FMATEST_H11 12#include "src/__support/FPUtil/cast.h"13#include "test/UnitTest/FEnvSafeTest.h"14#include "test/UnitTest/FPMatcher.h"15#include "test/UnitTest/Test.h"16 17template <typename OutType, typename InType = OutType>18class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {19 20  struct OutConstants {21    DECLARE_SPECIAL_CONSTANTS(OutType)22  };23 24  struct InConstants {25    DECLARE_SPECIAL_CONSTANTS(InType)26  };27 28  using OutFPBits = typename OutConstants::FPBits;29  using OutStorageType = typename OutConstants::StorageType;30  using InFPBits = typename InConstants::FPBits;31  using InStorageType = typename InConstants::StorageType;32 33  static constexpr OutStorageType OUT_MIN_NORMAL_U =34      OutFPBits::min_normal().uintval();35  static constexpr InStorageType IN_MIN_NORMAL_U =36      InFPBits::min_normal().uintval();37 38  OutConstants out;39  InConstants in;40 41  const InType in_out_min_normal =42      LIBC_NAMESPACE::fputil::cast<InType>(out.min_normal);43  const InType in_out_min_denormal =44      LIBC_NAMESPACE::fputil::cast<InType>(out.min_denormal);45 46public:47  using FmaFunc = OutType (*)(InType, InType, InType);48 49  void test_special_numbers(FmaFunc func) {50    EXPECT_FP_EQ(out.zero, func(in.zero, in.zero, in.zero));51    EXPECT_FP_EQ(out.neg_zero, func(in.zero, in.neg_zero, in.neg_zero));52    EXPECT_FP_EQ(out.inf, func(in.inf, in.inf, in.zero));53    EXPECT_FP_EQ(out.neg_inf, func(in.neg_inf, in.inf, in.neg_inf));54    EXPECT_FP_EQ(out.aNaN, func(in.inf, in.zero, in.zero));55    EXPECT_FP_EQ(out.aNaN, func(in.inf, in.neg_inf, in.inf));56    EXPECT_FP_EQ(out.aNaN, func(in.aNaN, in.zero, in.inf));57    EXPECT_FP_EQ(out.aNaN, func(in.inf, in.neg_inf, in.aNaN));58 59    // Test underflow rounding up.60    EXPECT_FP_EQ(OutFPBits(OutStorageType(2)).get_val(),61                 func(InType(0.5), in_out_min_denormal, in_out_min_denormal));62 63    if constexpr (sizeof(OutType) < sizeof(InType)) {64      EXPECT_FP_EQ(out.zero,65                   func(InType(0.5), in.min_denormal, in.min_denormal));66    }67 68    // Test underflow rounding down.69    OutType v = OutFPBits(static_cast<OutStorageType>(OUT_MIN_NORMAL_U +70                                                      OutStorageType(1)))71                    .get_val();72    EXPECT_FP_EQ(v, func(InType(1) / InType(OUT_MIN_NORMAL_U << 1),73                         LIBC_NAMESPACE::fputil::cast<InType>(v),74                         in_out_min_normal));75 76    if constexpr (sizeof(OutType) < sizeof(InType)) {77      InFPBits tmp = InFPBits::one();78      tmp.set_biased_exponent(InFPBits::EXP_BIAS - InFPBits::FRACTION_LEN - 1);79      InType reciprocal_value = tmp.get_val();80 81      InType v = InFPBits(static_cast<InStorageType>(IN_MIN_NORMAL_U +82                                                     InStorageType(1)))83                     .get_val();84      EXPECT_FP_EQ(out.min_normal,85                   func(reciprocal_value, v, in_out_min_normal));86    }87 88    // Test overflow.89    InType in_z = LIBC_NAMESPACE::fputil::cast<InType>(out.max_normal);90    EXPECT_FP_EQ_ALL_ROUNDING(func(InType(-0.25), in_z, in_z),91                              func(InType(1.75), in_z, -in_z));92 93    // Exact cancellation.94    EXPECT_FP_EQ_ROUNDING_NEAREST(95        out.zero, func(InType(3.0), InType(5.0), InType(-15.0)));96    EXPECT_FP_EQ_ROUNDING_UPWARD(out.zero,97                                 func(InType(3.0), InType(5.0), InType(-15.0)));98    EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(99        out.zero, func(InType(3.0), InType(5.0), InType(-15.0)));100    EXPECT_FP_EQ_ROUNDING_DOWNWARD(101        out.neg_zero, func(InType(3.0), InType(5.0), InType(-15.0)));102 103    EXPECT_FP_EQ_ROUNDING_NEAREST(104        out.zero, func(InType(-3.0), InType(5.0), InType(15.0)));105    EXPECT_FP_EQ_ROUNDING_UPWARD(out.zero,106                                 func(InType(-3.0), InType(5.0), InType(15.0)));107    EXPECT_FP_EQ_ROUNDING_TOWARD_ZERO(108        out.zero, func(InType(-3.0), InType(5.0), InType(15.0)));109    EXPECT_FP_EQ_ROUNDING_DOWNWARD(110        out.neg_zero, func(InType(-3.0), InType(5.0), InType(15.0)));111  }112};113 114#define LIST_FMA_TESTS(T, func)                                                \115  using LlvmLibcFmaTest = FmaTestTemplate<T>;                                  \116  TEST_F(LlvmLibcFmaTest, SpecialNumbers) { test_special_numbers(&func); }117 118#define LIST_NARROWING_FMA_TESTS(OutType, InType, func)                        \119  using LlvmLibcFmaTest = FmaTestTemplate<OutType, InType>;                    \120  TEST_F(LlvmLibcFmaTest, SpecialNumbers) { test_special_numbers(&func); }121 122#endif // LLVM_LIBC_TEST_SRC_MATH_FMATEST_H123