1313#include " src/__support/FPUtil/FEnvImpl.h"
1414#include " src/__support/FPUtil/FPBits.h"
1515#include " src/__support/FPUtil/cast.h"
16+ #include " src/__support/FPUtil/except_value_utils.h"
1617#include " src/__support/FPUtil/multiply_add.h"
1718#include " src/__support/macros/optimization.h"
1819
1920namespace LIBC_NAMESPACE_DECL {
2021
22+ constexpr size_t N_EXCEPTS = 2 ;
23+
24+ constexpr fputil::ExceptValues<float16, N_EXCEPTS> SINF16_EXCEPTS{{
25+ // (input, RZ output, RU offset, RD offset, RN offset)
26+ {0x585c , 0x3ba3 , 1 , 0 , 1 },
27+ {0x5cb0 , 0xbbff , 0 , 1 , 0 },
28+ }};
29+
2130LLVM_LIBC_FUNCTION (float16, sinf16, (float16 x)) {
2231 using FPBits = typename fputil::FPBits<float16>;
2332 FPBits xbits (x);
2433
2534 uint16_t x_u = xbits.uintval ();
2635 uint16_t x_abs = x_u & 0x7fff ;
2736 float xf = x;
28-
37+
2938 // Range reduction:
3039 // For !x| > pi/32, we perform range reduction as follows:
3140 // Find k and y such that:
@@ -41,15 +50,35 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
4150 // sin(x) = sin((k + y) * pi/32)
4251 // = sin(k * pi/32) * cos(y * pi/32) +
4352 // sin(y * pi/32) * cos(k * pi/32)
44-
53+
54+ // Handle exceptional values
55+ if (LIBC_UNLIKELY (x_abs == 0x585C || x_abs == 0x5cb0 )) {
56+ bool x_sign = x_u >> 15 ;
57+ if (auto r = SINF16_EXCEPTS.lookup_odd (x_abs, x_sign);
58+ LIBC_UNLIKELY (r.has_value ()))
59+ return r.value ();
60+ }
61+
62+ int rounding = fputil::quick_get_round ();
4563 if (LIBC_UNLIKELY (x_abs <= 0x13d0 )) {
46- int rounding = fputil::quick_get_round ();
47-
48- // For signed zeros
49- if ((LIBC_UNLIKELY (x_abs == 0U )) ||
50- (rounding == FE_UPWARD && xbits.is_pos ()) ||
51- (rounding == FE_DOWNWARD && xbits.is_neg ()))
64+ if (LIBC_UNLIKELY (x_abs == 0U ))
5265 return x;
66+
67+ if ((rounding == FE_UPWARD && xbits.is_pos ()) ||
68+ (rounding == FE_DOWNWARD && xbits.is_neg ()))
69+ return x;
70+
71+ if (rounding == FE_UPWARD && xbits.is_neg ()) {
72+ x_u--;
73+ return FPBits (x_u).get_val ();
74+ }
75+ }
76+
77+ if (LIBC_UNLIKELY (x_abs == 0x2b45 )) {
78+ if (rounding == FE_DOWNWARD && xbits.is_neg ()) {
79+ x_u--;
80+ return FPBits (x_u).get_val ();
81+ }
5382 }
5483
5584 if (LIBC_UNLIKELY (x_abs >= 0x7c00 )) {
@@ -61,7 +90,6 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
6190
6291 return x + FPBits::quiet_nan ().get_val ();
6392 }
64-
6593
6694 float sin_k, cos_k, sin_y, cosm1_y;
6795 sincosf16_eval (xf, sin_k, cos_k, sin_y, cosm1_y);
@@ -71,7 +99,8 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
7199
72100 // Since, cosm1_y = cos_y - 1, therfore:
73101 // sin(x) = cos_k * sin_y + sin_k + (cosm1_y * sin_k)
74- return fputil::cast<float16>(fputil::multiply_add (sin_y, cos_k, fputil::multiply_add (cosm1_y, sin_k, sin_k)));
102+ return fputil::cast<float16>(fputil::multiply_add (
103+ sin_y, cos_k, fputil::multiply_add (cosm1_y, sin_k, sin_k)));
75104}
76105
77106} // namespace LIBC_NAMESPACE_DECL
0 commit comments