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