Skip to content

Commit f549bb2

Browse files
authored
[libc][math] Adjust rsqrtf16 exception checks. (#159411)
1 parent 432b589 commit f549bb2

File tree

3 files changed

+44
-31
lines changed

3 files changed

+44
-31
lines changed

libc/src/__support/math/rsqrtf16.h

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,36 +28,39 @@ LIBC_INLINE static constexpr float16 rsqrtf16(float16 x) {
2828
using FPBits = fputil::FPBits<float16>;
2929
FPBits xbits(x);
3030

31-
const uint16_t x_u = xbits.uintval();
32-
const uint16_t x_abs = x_u & 0x7fff;
33-
const uint16_t x_sign = x_u >> 15;
31+
uint16_t x_u = xbits.uintval();
32+
uint16_t x_abs = x_u & 0x7fff;
33+
34+
constexpr uint16_t INF_BIT = FPBits::inf().uintval();
35+
36+
// x is 0, inf/nan, or negative.
37+
if (LIBC_UNLIKELY(x_u == 0 || x_u >= INF_BIT)) {
38+
// x is NaN
39+
if (x_abs > INF_BIT) {
40+
if (xbits.is_signaling_nan()) {
41+
fputil::raise_except_if_required(FE_INVALID);
42+
return FPBits::quiet_nan().get_val();
43+
}
44+
return x;
45+
}
46+
47+
// |x| = 0
48+
if (x_abs == 0) {
49+
fputil::raise_except_if_required(FE_DIVBYZERO);
50+
fputil::set_errno_if_required(ERANGE);
51+
return FPBits::inf(xbits.sign()).get_val();
52+
}
3453

35-
// x is NaN
36-
if (LIBC_UNLIKELY(xbits.is_nan())) {
37-
if (xbits.is_signaling_nan()) {
54+
// -inf <= x < 0
55+
if (x_u > 0x7fff) {
3856
fputil::raise_except_if_required(FE_INVALID);
57+
fputil::set_errno_if_required(EDOM);
3958
return FPBits::quiet_nan().get_val();
4059
}
41-
return x;
42-
}
4360

44-
// |x| = 0
45-
if (LIBC_UNLIKELY(x_abs == 0x0)) {
46-
fputil::raise_except_if_required(FE_DIVBYZERO);
47-
fputil::set_errno_if_required(ERANGE);
48-
return FPBits::inf(Sign::POS).get_val();
49-
}
50-
51-
// -inf <= x < 0
52-
if (LIBC_UNLIKELY(x_sign == 1)) {
53-
fputil::raise_except_if_required(FE_INVALID);
54-
fputil::set_errno_if_required(EDOM);
55-
return FPBits::quiet_nan().get_val();
56-
}
57-
58-
// x = +inf => rsqrt(x) = 0
59-
if (LIBC_UNLIKELY(xbits.is_inf()))
61+
// x = +inf => rsqrt(x) = 0
6062
return FPBits::zero().get_val();
63+
}
6164

6265
// TODO: add integer based implementation when LIBC_TARGET_CPU_HAS_FPU_FLOAT
6366
// is not defined

libc/test/src/math/rsqrtf16_test.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
1919
static constexpr uint16_t POS_START = 0x0000U;
2020
static constexpr uint16_t POS_STOP = 0x7c00U;
2121

22-
// Range: [-Inf, 0]
23-
static constexpr uint16_t NEG_START = 0x8000U;
22+
// Range: [-Inf, 0)
23+
// rsqrt(-0.0) is -inf, not the same for mpfr.
24+
static constexpr uint16_t NEG_START = 0x8001U;
2425
static constexpr uint16_t NEG_STOP = 0xfc00U;
2526

2627
TEST_F(LlvmLibcRsqrtf16Test, PositiveRange) {

libc/test/src/math/smoke/rsqrtf16_test.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,39 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "hdr/errno_macros.h"
10+
#include "src/__support/FPUtil/cast.h"
1011
#include "src/math/rsqrtf16.h"
1112
#include "test/UnitTest/FPMatcher.h"
1213
#include "test/UnitTest/Test.h"
1314

1415
using LlvmLibcRsqrtf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
16+
using LIBC_NAMESPACE::fputil::cast;
17+
1518
TEST_F(LlvmLibcRsqrtf16Test, SpecialNumbers) {
1619
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(aNaN));
1720
EXPECT_MATH_ERRNO(0);
1821

19-
EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::rsqrtf16(sNaN), FE_INVALID);
22+
EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::rsqrtf16(sNaN), FE_INVALID);
2023
EXPECT_MATH_ERRNO(0);
2124

22-
EXPECT_FP_EQ(inf, LIBC_NAMESPACE::rsqrtf16(0.0f));
25+
EXPECT_FP_EQ(inf, LIBC_NAMESPACE::rsqrtf16(zero));
26+
EXPECT_MATH_ERRNO(ERANGE);
27+
28+
EXPECT_FP_EQ(neg_inf, LIBC_NAMESPACE::rsqrtf16(neg_zero));
2329
EXPECT_MATH_ERRNO(ERANGE);
2430

25-
EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::rsqrtf16(1.0f));
31+
EXPECT_FP_EQ(
32+
LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
33+
LIBC_NAMESPACE::rsqrtf16(LIBC_NAMESPACE::fputil::cast<float16>(1.0f)));
2634
EXPECT_MATH_ERRNO(0);
2735

28-
EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::rsqrtf16(inf));
36+
EXPECT_FP_EQ(zero, LIBC_NAMESPACE::rsqrtf16(inf));
2937
EXPECT_MATH_ERRNO(0);
3038

3139
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(neg_inf));
3240
EXPECT_MATH_ERRNO(EDOM);
3341

34-
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(-2.0f));
42+
EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::rsqrtf16(
43+
LIBC_NAMESPACE::fputil::cast<float16>(-2.0f)));
3544
EXPECT_MATH_ERRNO(EDOM);
3645
}

0 commit comments

Comments
 (0)