Skip to content

Commit 43fefed

Browse files
committed
Initial implementation of rsqrtf16
- Defined and declared rsqrtf16 - Added entrypoints to support rsqrt in float16 format - Added tests - both unit and exhaustive - Added MPFR support for Rsqrt to verify the test results TODO: - Write computation as a polynomial in the end of rsqrtf16.cpp - Check if errors are generated correctly (Reference from C23: The rsqrt functions compute the reciprocal of the nonnegative square root of the argument. A domain error occurs if the argument is less than zero. A pole error may occur if the argument equals zero.)
1 parent 768d3ba commit 43fefed

File tree

15 files changed

+230
-1
lines changed

15 files changed

+230
-1
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
740740
libc.src.math.rintf16
741741
libc.src.math.roundevenf16
742742
libc.src.math.roundf16
743+
libc.src.math.rsqrtf16
743744
libc.src.math.scalblnf16
744745
libc.src.math.scalbnf16
745746
libc.src.math.setpayloadf16

libc/docs/headers/math/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ Higher Math Functions
333333
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
334334
| rootn | | | | | | 7.12.7.8 | F.10.4.8 |
335335
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
336-
| rsqrt | | | | | | 7.12.7.9 | F.10.4.9 |
336+
| rsqrt | | | | |check| | | 7.12.7.9 | F.10.4.9 |
337337
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
338338
| sin | |check| | |check| | | |check| | | 7.12.4.6 | F.10.1.6 |
339339
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/include/math.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,13 @@ functions:
22372237
return_type: long double
22382238
arguments:
22392239
- type: long double
2240+
- name: rsqrtf16
2241+
standards:
2242+
- stdc
2243+
return_type: _Float16
2244+
arguments:
2245+
- type: _Float16
2246+
guard: LIBC_TYPES_HAS_FLOAT16
22402247
- name: scalbln
22412248
standards:
22422249
- stdc

libc/src/math/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,8 @@ add_math_entrypoint_object(roundevenl)
467467
add_math_entrypoint_object(roundevenf16)
468468
add_math_entrypoint_object(roundevenf128)
469469

470+
add_math_entrypoint_object(rsqrtf16)
471+
470472
add_math_entrypoint_object(scalbln)
471473
add_math_entrypoint_object(scalblnf)
472474
add_math_entrypoint_object(scalblnl)

libc/src/math/generic/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,25 @@ add_entrypoint_object(
955955
libc.src.__support.FPUtil.nearest_integer_operations
956956
)
957957

958+
add_entrypoint_object(
959+
rsqrtf16
960+
SRCS
961+
rsqrtf16.cpp
962+
HDRS
963+
../rsqrtf16.h
964+
DEPENDS
965+
libc.hdr.errno_macros
966+
libc.hdr.fenv_macros
967+
libc.src.__support.FPUtil.cast
968+
libc.src.__support.FPUtil.fenv_impl
969+
libc.src.__support.FPUtil.fp_bits
970+
libc.src.__support.FPUtil.multiply_add
971+
libc.src.__support.FPUtil.polyeval
972+
libc.src.__support.FPUtil.sqrt
973+
libc.src.__support.macros.optimization
974+
libc.src.__support.macros.properties.types
975+
)
976+
958977
add_entrypoint_object(
959978
lround
960979
SRCS

libc/src/math/generic/rsqrtf16.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===-- Half-precision rsqrt function -------------------------------------===//
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 "src/math/rsqrtf16.h"
10+
#include "hdr/errno_macros.h"
11+
#include "hdr/fenv_macros.h"
12+
#include "src/__support/FPUtil/FEnvImpl.h"
13+
#include "src/__support/FPUtil/FPBits.h"
14+
#include "src/__support/FPUtil/PolyEval.h"
15+
#include "src/__support/FPUtil/cast.h"
16+
#include "src/__support/FPUtil/multiply_add.h"
17+
#include "src/__support/FPUtil/sqrt.h"
18+
#include "src/__support/macros/optimization.h"
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
22+
LLVM_LIBC_FUNCTION(float16, rsqrtf16, (float16 x)) {
23+
using FPBits = fputil::FPBits<float16>;
24+
FPBits xbits(x);
25+
26+
uint16_t x_u = xbits.uintval();
27+
uint16_t x_abs = x_u & 0x7fff;
28+
uint16_t x_sign = x_u >> 15;
29+
30+
// x is NaN
31+
if (LIBC_UNLIKELY(xbits.is_nan())) {
32+
if (xbits.is_signaling_nan()) {
33+
fputil::raise_except_if_required(FE_INVALID);
34+
return FPBits::quiet_nan().get_val();
35+
}
36+
return x;
37+
}
38+
39+
// |x| = 0
40+
if (LIBC_UNLIKELY(x_abs == 0x0)) {
41+
fputil::raise_except_if_required(FE_DIVBYZERO);
42+
fputil::set_errno_if_required(ERANGE);
43+
return FPBits::quiet_nan().get_val();
44+
}
45+
46+
// -inf <= x < 0
47+
if (LIBC_UNLIKELY(x_sign == 1)) {
48+
fputil::raise_except_if_required(FE_INVALID);
49+
fputil::set_errno_if_required(EDOM);
50+
return FPBits::quiet_nan().get_val();
51+
}
52+
53+
// x = +inf => rsqrt(x) = 0
54+
if (LIBC_UNLIKELY(xbits.is_inf())) {
55+
return fputil::cast<float16>(0.0f);
56+
}
57+
58+
// x = 1 => rsqrt(x) = 1
59+
if (LIBC_UNLIKELY(x_u == 0x1)) {
60+
return fputil::cast<float16>(1.0f);
61+
}
62+
63+
// x is valid, estimate the result - below is temporary solution for just testing
64+
float xf = x;
65+
return fputil::cast<float16>(1.0f / xf);
66+
}
67+
} // namespace LIBC_NAMESPACE_DECL

libc/src/math/rsqrtf16.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for rsqrtf16 ----------------------*- 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_SRC_MATH_RSQRTF16_H
10+
#define LLVM_LIBC_SRC_MATH_RSQRTF16_H
11+
12+
#include "src/__support/macros/config.h"
13+
#include "src/__support/macros/properties/types.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
float16 rsqrtf16(float16 x);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_MATH_RSQRTF16_H

libc/test/src/math/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,17 @@ add_fp_unittest(
15601560
libc.src.math.sqrtl
15611561
)
15621562

1563+
add_fp_unittest(
1564+
rsqrtf16_test
1565+
NEED_MPFR
1566+
SUITE
1567+
libc-math-unittests
1568+
SRCS
1569+
rsqrtf16_test.cpp
1570+
DEPENDS
1571+
libc.src.math.rsqrtf16
1572+
)
1573+
15631574
add_fp_unittest(
15641575
sqrtf16_test
15651576
NEED_MPFR
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===-- Exhaustive test for rsqrtf16 --------------------------------------===//
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 "src/math/rsqrtf16.h"
10+
#include "test/UnitTest/FPMatcher.h"
11+
#include "test/UnitTest/Test.h"
12+
#include "utils/MPFRWrapper/MPFRUtils.h"
13+
14+
using LlvmLibcRsqrtf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
15+
16+
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
17+
18+
// Range: [0, Inf]
19+
static constexpr uint16_t POS_START = 0x0000U;
20+
static constexpr uint16_t POS_STOP = 0x7c00U;
21+
22+
// Range: [-Inf, 0]
23+
static constexpr uint16_t NEG_START = 0x8000U;
24+
static constexpr uint16_t NEG_STOP = 0xfc00U;
25+
26+
TEST_F(LlvmLibcRsqrtf16Test, PositiveRange) {
27+
for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
28+
float16 x = FPBits(v).get_val();
29+
30+
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Rsqrt, x,
31+
LIBC_NAMESPACE::rsqrtf16(x), 0.5);
32+
}
33+
}
34+
35+
TEST_F(LlvmLibcRsqrtf16Test, NegativeRange) {
36+
for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
37+
float16 x = FPBits(v).get_val();
38+
39+
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Rsqrt, x,
40+
LIBC_NAMESPACE::rsqrtf16(x), 0.5);
41+
}
42+
}

libc/test/src/math/smoke/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,6 +2958,17 @@ add_fp_unittest(
29582958
libc.src.math.sqrtl
29592959
)
29602960

2961+
add_fp_unittest(
2962+
rsqrtf16_test
2963+
SUITE
2964+
libc-math-smoke-tests
2965+
SRCS
2966+
rsqrtf16_test.cpp
2967+
DEPENDS
2968+
libc.src.errno.errno
2969+
libc.src.math.rsqrtf16
2970+
)
2971+
29612972
add_fp_unittest(
29622973
sqrtf16_test
29632974
SUITE

0 commit comments

Comments
 (0)