Skip to content

Commit c6bc857

Browse files
committed
Added comments, improved code readability
1 parent e234abd commit c6bc857

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

libc/src/math/generic/sincosf16_utils.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ LIBC_INLINE int32_t range_reduction_sincospif16(float x, float &y) {
4747
return static_cast<int32_t>(kf);
4848
}
4949

50+
// Recall, range reduction:
51+
// k = round(x * 32/pi)
52+
// y = x * 32/pi - k
53+
//
54+
// The constant 0x1.45f306dc9c883p3 is 32/pi rounded to double-precision.
55+
// 32/pi is generated by Sollya with the following commands:
56+
// > display = hexadecimal;
57+
// > round(32/pi, D, RN);
58+
//
59+
// The precision choice of 'double' is to minimize rounding errors
60+
// in this initial scaling step, preserving enough bits so errors accumulated
61+
// while computing the subtraction: y = x * 32/pi - round(x * 32/pi)
62+
// are beyond the least-significant bit of single-precision used during
63+
// intermediate computation.
5064
LIBC_INLINE int32_t range_reduction_sincosf16(float x, float &y) {
5165
double prod = x * 0x1.45f306dc9c883p3;
5266
double kf = fputil::nearest_integer(prod);

libc/src/math/generic/sinf16.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,26 @@
1919

2020
namespace LIBC_NAMESPACE_DECL {
2121

22-
constexpr size_t N_EXCEPTS = 3;
22+
constexpr size_t N_EXCEPTS = 4;
2323

2424
constexpr fputil::ExceptValues<float16, N_EXCEPTS> SINF16_EXCEPTS{{
2525
// (input, RZ output, RU offset, RD offset, RN offset)
26+
{0x2b45, 0x2b43, 1, 0, 1},
2627
{0x585c, 0x3ba3, 1, 0, 1},
2728
{0x5cb0, 0xbbff, 0, 1, 0},
2829
{0x51f5, 0xb80f, 0, 1, 0},
2930
}};
3031

3132
LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
32-
using FPBits = typename fputil::FPBits<float16>;
33+
using FPBits = fputil::FPBits<float16>;
3334
FPBits xbits(x);
3435

3536
uint16_t x_u = xbits.uintval();
3637
uint16_t x_abs = x_u & 0x7fff;
3738
float xf = x;
3839

3940
// Range reduction:
40-
// For !x| > pi/32, we perform range reduction as follows:
41+
// For |x| > pi/32, we perform range reduction as follows:
4142
// Find k and y such that:
4243
// x = (k + y) * pi/32
4344
// k is an integer, |y| < 0.5
@@ -53,13 +54,19 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
5354
// sin(y * pi/32) * cos(k * pi/32)
5455

5556
// Handle exceptional values
56-
if (LIBC_UNLIKELY(x_abs == 0x585C || x_abs == 0x5cb0 || x_abs == 0x51f5)) {
57+
if (LIBC_UNLIKELY(x_abs == 0x585c || x_abs == 0x5cb0 || x_abs == 0x51f5 ||
58+
x_abs == 0x2b45)) {
5759
bool x_sign = x_u >> 15;
5860
if (auto r = SINF16_EXCEPTS.lookup_odd(x_abs, x_sign);
5961
LIBC_UNLIKELY(r.has_value()))
6062
return r.value();
6163
}
6264

65+
// Exhaustive tests show that for |x| <= 0x13d0, 1ULP rounding errors occur.
66+
// To fix this, the following apply:
67+
// - When x >= 0, and rounding upward, sin(x) == x.
68+
// - When x < 0, and rounding downward, sin(x) == x.
69+
// - When x < 0, and rounding upward, sin(x) == (x - 1ULP)
6370
int rounding = fputil::quick_get_round();
6471
if (LIBC_UNLIKELY(x_abs <= 0x13d0)) {
6572
if (LIBC_UNLIKELY(x_abs == 0U))
@@ -75,16 +82,8 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
7582
}
7683
}
7784

78-
if (LIBC_UNLIKELY(x_abs == 0x2b45)) {
79-
if (rounding == FE_DOWNWARD && xbits.is_neg()) {
80-
x_u--;
81-
return FPBits(x_u).get_val();
82-
}
83-
}
84-
85-
if (LIBC_UNLIKELY(x_abs >= 0x7c00)) {
86-
// If value is equal to infinity
87-
if (x_abs == 0x7c00) {
85+
if (xbits.is_inf_or_nan()) {
86+
if (xbits.is_inf()){
8887
fputil::set_errno_if_required(EDOM);
8988
fputil::raise_except_if_required(FE_INVALID);
9089
}

0 commit comments

Comments
 (0)