1919
2020namespace LIBC_NAMESPACE_DECL {
2121
22- constexpr size_t N_EXCEPTS = 3 ;
22+ constexpr size_t N_EXCEPTS = 4 ;
2323
2424constexpr 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
3132LLVM_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