Skip to content

Commit b22bafa

Browse files
committed
[libc][math] Add MPFR unit tests for nearbyint{,f,l,f16}
1 parent d69f987 commit b22bafa

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed

libc/test/src/math/CMakeLists.txt

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,74 @@ add_fp_unittest(
484484
libc.src.__support.FPUtil.fp_bits
485485
)
486486

487+
add_fp_unittest(
488+
nearbyint_test
489+
NEED_MPFR
490+
SUITE
491+
libc-math-unittests
492+
SRCS
493+
nearbyint_test.cpp
494+
HDRS
495+
NearbyIntTest.h
496+
DEPENDS
497+
libc.hdr.fenv_macros
498+
libc.src.math.nearbyint
499+
libc.src.__support.CPP.algorithm
500+
libc.src.__support.FPUtil.fenv_impl
501+
libc.src.__support.FPUtil.fp_bits
502+
)
503+
504+
add_fp_unittest(
505+
nearbyintf_test
506+
NEED_MPFR
507+
SUITE
508+
libc-math-unittests
509+
SRCS
510+
nearbyintf_test.cpp
511+
HDRS
512+
NearbyIntTest.h
513+
DEPENDS
514+
libc.hdr.fenv_macros
515+
libc.src.math.nearbyintf
516+
libc.src.__support.CPP.algorithm
517+
libc.src.__support.FPUtil.fenv_impl
518+
libc.src.__support.FPUtil.fp_bits
519+
)
520+
521+
add_fp_unittest(
522+
nearbyintl_test
523+
NEED_MPFR
524+
SUITE
525+
libc-math-unittests
526+
SRCS
527+
nearbyintl_test.cpp
528+
HDRS
529+
NearbyIntTest.h
530+
DEPENDS
531+
libc.hdr.fenv_macros
532+
libc.src.math.nearbyintl
533+
libc.src.__support.CPP.algorithm
534+
libc.src.__support.FPUtil.fenv_impl
535+
libc.src.__support.FPUtil.fp_bits
536+
)
537+
538+
add_fp_unittest(
539+
nearbyintf16_test
540+
NEED_MPFR
541+
SUITE
542+
libc-math-unittests
543+
SRCS
544+
nearbyintf16_test.cpp
545+
HDRS
546+
NearbyIntTest.h
547+
DEPENDS
548+
libc.hdr.fenv_macros
549+
libc.src.math.nearbyintf16
550+
libc.src.__support.CPP.algorithm
551+
libc.src.__support.FPUtil.fenv_impl
552+
libc.src.__support.FPUtil.fp_bits
553+
)
554+
487555
add_fp_unittest(
488556
rint_test
489557
NEED_MPFR

libc/test/src/math/NearbyIntTest.h

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//===-- Utility class to test different flavors of nearbyint ----*- 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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H
10+
#define LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H
11+
12+
#include "src/__support/CPP/algorithm.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+
#include "utils/MPFRWrapper/MPFRUtils.h"
19+
20+
#include "hdr/fenv_macros.h"
21+
#include "hdr/math_macros.h"
22+
23+
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
24+
25+
static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
26+
FE_TONEAREST};
27+
28+
template <typename T>
29+
class NearbyIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
30+
public:
31+
typedef T (*NearbyIntFunc)(T);
32+
33+
private:
34+
using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
35+
using StorageType = typename FPBits::StorageType;
36+
37+
const T inf = FPBits::inf(Sign::POS).get_val();
38+
const T neg_inf = FPBits::inf(Sign::NEG).get_val();
39+
const T zero = FPBits::zero(Sign::POS).get_val();
40+
const T neg_zero = FPBits::zero(Sign::NEG).get_val();
41+
const T nan = FPBits::quiet_nan().get_val();
42+
43+
static constexpr StorageType MIN_SUBNORMAL =
44+
FPBits::min_subnormal().uintval();
45+
static constexpr StorageType MAX_SUBNORMAL =
46+
FPBits::max_subnormal().uintval();
47+
static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
48+
static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
49+
50+
static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) {
51+
switch (mode) {
52+
case FE_UPWARD:
53+
return mpfr::RoundingMode::Upward;
54+
case FE_DOWNWARD:
55+
return mpfr::RoundingMode::Downward;
56+
case FE_TOWARDZERO:
57+
return mpfr::RoundingMode::TowardZero;
58+
case FE_TONEAREST:
59+
return mpfr::RoundingMode::Nearest;
60+
default:
61+
__builtin_unreachable();
62+
}
63+
}
64+
65+
public:
66+
void testSpecialNumbers(NearbyIntFunc func) {
67+
for (int mode : ROUNDING_MODES) {
68+
LIBC_NAMESPACE::fputil::set_round(mode);
69+
EXPECT_FP_EQ(inf, func(inf));
70+
EXPECT_FP_EQ(neg_inf, func(neg_inf));
71+
EXPECT_FP_EQ(nan, func(nan));
72+
EXPECT_FP_EQ(zero, func(zero));
73+
EXPECT_FP_EQ(neg_zero, func(neg_zero));
74+
}
75+
}
76+
77+
void testRoundNumbers(NearbyIntFunc func) {
78+
for (int mode : ROUNDING_MODES) {
79+
LIBC_NAMESPACE::fputil::set_round(mode);
80+
mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
81+
EXPECT_FP_EQ(func(T(1.0)), mpfr::round(T(1.0), mpfr_mode));
82+
EXPECT_FP_EQ(func(T(-1.0)), mpfr::round(T(-1.0), mpfr_mode));
83+
EXPECT_FP_EQ(func(T(10.0)), mpfr::round(T(10.0), mpfr_mode));
84+
EXPECT_FP_EQ(func(T(-10.0)), mpfr::round(T(-10.0), mpfr_mode));
85+
EXPECT_FP_EQ(func(T(1234.0)), mpfr::round(T(1234.0), mpfr_mode));
86+
EXPECT_FP_EQ(func(T(-1234.0)), mpfr::round(T(-1234.0), mpfr_mode));
87+
}
88+
}
89+
90+
void testFractions(NearbyIntFunc func) {
91+
for (int mode : ROUNDING_MODES) {
92+
LIBC_NAMESPACE::fputil::set_round(mode);
93+
mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
94+
EXPECT_FP_EQ(func(T(0.5)), mpfr::round(T(0.5), mpfr_mode));
95+
EXPECT_FP_EQ(func(T(-0.5)), mpfr::round(T(-0.5), mpfr_mode));
96+
EXPECT_FP_EQ(func(T(0.115)), mpfr::round(T(0.115), mpfr_mode));
97+
EXPECT_FP_EQ(func(T(-0.115)), mpfr::round(T(-0.115), mpfr_mode));
98+
EXPECT_FP_EQ(func(T(0.715)), mpfr::round(T(0.715), mpfr_mode));
99+
EXPECT_FP_EQ(func(T(-0.715)), mpfr::round(T(-0.715), mpfr_mode));
100+
}
101+
}
102+
103+
void testSubnormalRange(NearbyIntFunc func) {
104+
constexpr int COUNT = 100'001;
105+
constexpr StorageType STEP = LIBC_NAMESPACE::cpp::max(
106+
static_cast<StorageType>((MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT),
107+
StorageType(1));
108+
for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) {
109+
T x = FPBits(i).get_val();
110+
for (int mode : ROUNDING_MODES) {
111+
LIBC_NAMESPACE::fputil::set_round(mode);
112+
mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
113+
EXPECT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
114+
}
115+
}
116+
}
117+
118+
void testNormalRange(NearbyIntFunc func) {
119+
constexpr int COUNT = 100'001;
120+
constexpr StorageType STEP = LIBC_NAMESPACE::cpp::max(
121+
static_cast<StorageType>((MAX_NORMAL - MIN_NORMAL) / COUNT),
122+
StorageType(1));
123+
for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) {
124+
FPBits xbits(i);
125+
T x = xbits.get_val();
126+
// In normal range on x86 platforms, the long double implicit 1 bit can be
127+
// zero making the numbers NaN. We will skip them.
128+
if (xbits.is_nan())
129+
continue;
130+
131+
for (int mode : ROUNDING_MODES) {
132+
LIBC_NAMESPACE::fputil::set_round(mode);
133+
mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
134+
EXPECT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
135+
}
136+
}
137+
}
138+
};
139+
140+
#define LIST_NEARBYINT_TESTS(F, func) \
141+
using LlvmLibcNearbyIntTest = NearbyIntTestTemplate<F>; \
142+
TEST_F(LlvmLibcNearbyIntTest, specialNumbers) { testSpecialNumbers(&func); } \
143+
TEST_F(LlvmLibcNearbyIntTest, RoundNumbers) { testRoundNumbers(&func); } \
144+
TEST_F(LlvmLibcNearbyIntTest, Fractions) { testFractions(&func); } \
145+
TEST_F(LlvmLibcNearbyIntTest, SubnormalRange) { testSubnormalRange(&func); } \
146+
TEST_F(LlvmLibcNearbyIntTest, NormalRange) { testNormalRange(&func); }
147+
148+
#endif // LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H

libc/test/src/math/nearbyint_test.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for nearbyint -------------------------------------------===//
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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "NearbyIntTest.h"
10+
11+
#include "src/math/nearbyint.h"
12+
13+
LIST_NEARBYINT_TESTS(double, LIBC_NAMESPACE::nearbyint)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for nearbyintf16 ----------------------------------------===//
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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "NearbyIntTest.h"
10+
11+
#include "src/math/nearbyintf16.h"
12+
13+
LIST_NEARBYINT_TESTS(float16, LIBC_NAMESPACE::nearbyintf16)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for nearbyintf ------------------------------------------===//
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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "NearbyIntTest.h"
10+
11+
#include "src/math/nearbyintf.h"
12+
13+
LIST_NEARBYINT_TESTS(float, LIBC_NAMESPACE::nearbyintf)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for nearbyintl ------------------------------------------===//
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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "NearbyIntTest.h"
10+
11+
#include "src/math/nearbyintl.h"
12+
13+
LIST_NEARBYINT_TESTS(long double, LIBC_NAMESPACE::nearbyintl)

0 commit comments

Comments
 (0)