brintos

brintos / llvm-project-archived public Read only

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