brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 43e71c6 Raw
224 lines · c
1//===-- Utility class to test different flavors of nexttoward ---*- 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_NEXTTOWARDTEST_H10#define LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H11 12#include "src/__support/CPP/bit.h"13#include "src/__support/FPUtil/FEnvImpl.h"14#include "src/__support/FPUtil/FPBits.h"15#include "test/UnitTest/FEnvSafeTest.h"16#include "test/UnitTest/FPMatcher.h"17#include "test/UnitTest/Test.h"18 19#include "hdr/fenv_macros.h"20 21using LIBC_NAMESPACE::Sign;22 23// TODO: Strengthen errno,exception checks and remove these assert macros24// after new matchers/test fixtures are added25#define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception)      \26  ASSERT_FP_EQ(result, expected);                                              \27  ASSERT_FP_EXCEPTION(expected_exception);                                     \28  LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT)29 30#define ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected)                          \31  ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, FE_INEXACT | FE_UNDERFLOW)32 33#define ASSERT_FP_EQ_WITH_OVERFLOW(result, expected)                           \34  ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, FE_INEXACT | FE_OVERFLOW)35 36template <typename T>37class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {38  using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;39  using ToFPBits = LIBC_NAMESPACE::fputil::FPBits<long double>;40  using StorageType = typename FPBits::StorageType;41 42  const T inf = FPBits::inf(Sign::POS).get_val();43  const T neg_inf = FPBits::inf(Sign::NEG).get_val();44  const T zero = FPBits::zero(Sign::POS).get_val();45  const T neg_zero = FPBits::zero(Sign::NEG).get_val();46  const T nan = FPBits::quiet_nan().get_val();47 48  const long double to_inf = ToFPBits::inf(Sign::POS).get_val();49  const long double to_neg_inf = ToFPBits::inf(Sign::NEG).get_val();50  const long double to_zero = ToFPBits::zero().get_val();51  const long double to_neg_zero = ToFPBits::zero(Sign::NEG).get_val();52  const long double to_nan = ToFPBits::quiet_nan().get_val();53 54  static constexpr StorageType min_subnormal =55      FPBits::min_subnormal().uintval();56  static constexpr StorageType max_subnormal =57      FPBits::max_subnormal().uintval();58  static constexpr StorageType min_normal = FPBits::min_normal().uintval();59  static constexpr StorageType max_normal = FPBits::max_normal().uintval();60 61public:62  typedef T (*NextTowardFunc)(T, long double);63 64  void testNaN(NextTowardFunc func) {65    ASSERT_FP_EQ(func(nan, to_zero), nan);66    ASSERT_FP_EQ(func(zero, to_nan), nan);67  }68 69  void testBoundaries(NextTowardFunc func) {70    ASSERT_FP_EQ(func(zero, to_neg_zero), neg_zero);71    ASSERT_FP_EQ(func(neg_zero, to_zero), zero);72 73    // 'from' is zero|neg_zero.74    T x = zero;75    T result = func(x, 1);76    StorageType expected_bits = 1;77    T expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);78    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);79 80    result = func(x, -1);81    expected_bits = FPBits::SIGN_MASK + 1;82    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);83    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);84 85    x = neg_zero;86    result = func(x, 1);87    expected_bits = 1;88    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);89    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);90 91    result = func(x, -1);92    expected_bits = FPBits::SIGN_MASK + 1;93    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);94    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);95 96    // 'from' is max subnormal value.97    x = LIBC_NAMESPACE::cpp::bit_cast<T>(max_subnormal);98    result = func(x, 1);99    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(min_normal);100    ASSERT_FP_EQ(result, expected);101 102    result = func(x, 0);103    expected_bits = max_subnormal - 1;104    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);105    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);106 107    x = -x;108 109    result = func(x, -1);110    expected_bits = FPBits::SIGN_MASK + min_normal;111    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);112    ASSERT_FP_EQ(result, expected);113 114    result = func(x, 0);115    expected_bits = FPBits::SIGN_MASK + max_subnormal - 1;116    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);117    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);118 119    // 'from' is min subnormal value.120    x = LIBC_NAMESPACE::cpp::bit_cast<T>(min_subnormal);121    result = func(x, 1);122    expected_bits = min_subnormal + 1;123    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);124    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);125    ASSERT_FP_EQ_WITH_UNDERFLOW(func(x, 0), zero);126 127    x = -x;128    result = func(x, -1);129    expected_bits = FPBits::SIGN_MASK + min_subnormal + 1;130    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);131    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);132    ASSERT_FP_EQ_WITH_UNDERFLOW(func(x, 0), T(-0.0));133 134    // 'from' is min normal.135    x = LIBC_NAMESPACE::cpp::bit_cast<T>(min_normal);136    result = func(x, 0);137    expected_bits = max_subnormal;138    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);139    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);140 141    result = func(x, to_inf);142    expected_bits = min_normal + 1;143    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);144    ASSERT_FP_EQ(result, expected);145 146    x = -x;147    result = func(x, 0);148    expected_bits = FPBits::SIGN_MASK + max_subnormal;149    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);150    ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);151 152    result = func(x, to_neg_inf);153    expected_bits = FPBits::SIGN_MASK + min_normal + 1;154    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);155    ASSERT_FP_EQ(result, expected);156 157    // 'from' is max normal158    x = LIBC_NAMESPACE::cpp::bit_cast<T>(max_normal);159    result = func(x, 0);160    expected_bits = max_normal - 1;161    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);162    ASSERT_FP_EQ(result, expected);163    ASSERT_FP_EQ_WITH_OVERFLOW(func(x, to_inf), inf);164 165    x = -x;166    result = func(x, 0);167    expected_bits = FPBits::SIGN_MASK + max_normal - 1;168    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);169    ASSERT_FP_EQ(result, expected);170    ASSERT_FP_EQ_WITH_OVERFLOW(func(x, to_neg_inf), neg_inf);171 172    // 'from' is infinity.173    x = inf;174    result = func(x, 0);175    expected_bits = max_normal;176    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);177    ASSERT_FP_EQ(result, expected);178    ASSERT_FP_EQ(func(x, to_inf), inf);179 180    x = neg_inf;181    result = func(x, 0);182    expected_bits = FPBits::SIGN_MASK + max_normal;183    expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);184    ASSERT_FP_EQ(result, expected);185    ASSERT_FP_EQ(func(x, to_neg_inf), neg_inf);186 187    // 'from' is a power of 2.188    x = T(32.0);189    result = func(x, 0);190    FPBits x_bits = FPBits(x);191    FPBits result_bits = FPBits(result);192    ASSERT_EQ(result_bits.get_biased_exponent(),193              uint16_t(x_bits.get_biased_exponent() - 1));194    ASSERT_EQ(result_bits.get_mantissa(), FPBits::FRACTION_MASK);195 196    result = func(x, 33.0);197    result_bits = FPBits(result);198    ASSERT_EQ(result_bits.get_biased_exponent(), x_bits.get_biased_exponent());199    ASSERT_EQ(result_bits.get_mantissa(),200              static_cast<StorageType>(x_bits.get_mantissa() + StorageType(1)));201 202    x = -x;203 204    result = func(x, 0);205    result_bits = FPBits(result);206    ASSERT_EQ(result_bits.get_biased_exponent(),207              uint16_t(x_bits.get_biased_exponent() - 1));208    ASSERT_EQ(result_bits.get_mantissa(), FPBits::FRACTION_MASK);209 210    result = func(x, -33.0);211    result_bits = FPBits(result);212    ASSERT_EQ(result_bits.get_biased_exponent(), x_bits.get_biased_exponent());213    ASSERT_EQ(result_bits.get_mantissa(),214              static_cast<StorageType>(x_bits.get_mantissa() + StorageType(1)));215  }216};217 218#define LIST_NEXTTOWARD_TESTS(T, func)                                         \219  using LlvmLibcNextTowardTest = NextTowardTestTemplate<T>;                    \220  TEST_F(LlvmLibcNextTowardTest, TestNaN) { testNaN(&func); }                  \221  TEST_F(LlvmLibcNextTowardTest, TestBoundaries) { testBoundaries(&func); }222 223#endif // LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H224