|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
9 | 9 | #include "src/math/cosf.h"
|
10 |
| -#include "common_constants.h" |
| 10 | +#include "sincosf_utils.h" |
11 | 11 | #include "src/__support/FPUtil/BasicOperations.h"
|
12 | 12 | #include "src/__support/FPUtil/FEnvImpl.h"
|
13 | 13 | #include "src/__support/FPUtil/FPBits.h"
|
14 |
| -#include "src/__support/FPUtil/PolyEval.h" |
15 | 14 | #include "src/__support/FPUtil/except_value_utils.h"
|
16 | 15 | #include "src/__support/FPUtil/multiply_add.h"
|
17 | 16 | #include "src/__support/common.h"
|
18 | 17 |
|
19 | 18 | #include <errno.h>
|
20 | 19 |
|
21 |
| -#if defined(LIBC_TARGET_HAS_FMA) |
22 |
| -#include "range_reduction_fma.h" |
23 |
| -// using namespace __llvm_libc::fma; |
24 |
| -using __llvm_libc::fma::FAST_PASS_BOUND; |
25 |
| -using __llvm_libc::fma::large_range_reduction; |
26 |
| -using __llvm_libc::fma::small_range_reduction; |
27 |
| -#else |
28 |
| -#include "range_reduction.h" |
29 |
| -// using namespace __llvm_libc::generic; |
30 |
| -using __llvm_libc::generic::FAST_PASS_BOUND; |
31 |
| -using __llvm_libc::generic::large_range_reduction; |
32 |
| -using __llvm_libc::generic::small_range_reduction; |
33 |
| -#endif |
34 |
| - |
35 | 20 | namespace __llvm_libc {
|
36 | 21 |
|
37 | 22 | // Exceptional cases for cosf.
|
@@ -132,58 +117,26 @@ LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
|
132 | 117 | return result;
|
133 | 118 | }
|
134 | 119 |
|
135 |
| - // TODO(lntue): refactor range reduction and most of polynomial approximation |
136 |
| - // to share between sinf, cosf, and sincosf. |
137 |
| - int k; |
138 |
| - double y; |
139 |
| - |
140 |
| - if (likely(x_abs < FAST_PASS_BOUND)) { |
141 |
| - k = small_range_reduction(xd, y); |
142 |
| - } else { |
143 |
| - // x is inf or nan. |
144 |
| - if (unlikely(x_abs >= 0x7f80'0000U)) { |
145 |
| - if (x_abs == 0x7f80'0000U) { |
146 |
| - errno = EDOM; |
147 |
| - fputil::set_except(FE_INVALID); |
148 |
| - } |
149 |
| - return x + |
150 |
| - FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1)); |
| 120 | + // x is inf or nan. |
| 121 | + if (unlikely(x_abs >= 0x7f80'0000U)) { |
| 122 | + if (x_abs == 0x7f80'0000U) { |
| 123 | + errno = EDOM; |
| 124 | + fputil::set_except(FE_INVALID); |
151 | 125 | }
|
152 |
| - |
153 |
| - k = large_range_reduction(xd, xbits.get_exponent(), y); |
| 126 | + return x + |
| 127 | + FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1)); |
154 | 128 | }
|
155 | 129 |
|
156 |
| - // After range reduction, k = round(x * 16 / pi) and y = (x * 16 / pi) - k. |
157 |
| - // So k is an integer and -0.5 <= y <= 0.5. |
158 |
| - // Then cos(x) = cos((k + y)*pi/16) |
159 |
| - // = cos(y*pi/16) * cos(k*pi/16) - sin(y*pi/16) * sin(k*pi/16) |
160 |
| - |
161 |
| - double ysq = y * y; |
162 |
| - |
163 |
| - // Degree-6 minimax even polynomial for sin(y*pi/16)/y generated by Sollya |
164 |
| - // with: |
165 |
| - // > Q = fpminimax(sin(y*pi/16)/y, [|0, 2, 4, 6|], [|D...|], [0, 0.5]); |
166 |
| - double sin_y = |
167 |
| - y * fputil::polyeval(ysq, 0x1.921fb54442d17p-3, -0x1.4abbce6256adp-10, |
168 |
| - 0x1.466bc5a5ac6b3p-19, -0x1.32bdcb4207562p-29); |
169 |
| - // Degree-8 minimax even polynomial for cos(y*pi/16) generated by Sollya with: |
170 |
| - // > P = fpminimax(cos(x*pi/16), [|0, 2, 4, 6, 8|], [|1, D...|], [0, 0.5]); |
171 |
| - // Note that cosm1_y = cos(y*pi/16) - 1. |
172 |
| - double cosm1_y = |
173 |
| - ysq * fputil::polyeval(ysq, -0x1.3bd3cc9be45dcp-6, 0x1.03c1f081b08ap-14, |
174 |
| - -0x1.55d3c6fb0fb6ep-24, 0x1.e1d3d60f58873p-35); |
175 |
| - |
176 |
| - double sin_k = -SIN_K_PI_OVER_16[k & 31]; |
177 |
| - // cos(k * pi/16) = sin(k * pi/16 + pi/2) = sin((k + 8) * pi/16). |
178 |
| - // cos_k = y * cos(k * pi/16) |
179 |
| - double cos_k = SIN_K_PI_OVER_16[(k + 8) & 31]; |
180 |
| - |
181 | 130 | // Combine the results with the sine of sum formula:
|
182 | 131 | // cos(x) = cos((k + y)*pi/16)
|
183 | 132 | // = cos(y*pi/16) * cos(k*pi/16) - sin(y*pi/16) * sin(k*pi/16)
|
184 | 133 | // = cosm1_y * cos_k + sin_y * sin_k
|
185 | 134 | // = (cosm1_y * cos_k + cos_k) + sin_y * sin_k
|
186 |
| - return fputil::multiply_add(sin_y, sin_k, |
| 135 | + double sin_k, cos_k, sin_y, cosm1_y; |
| 136 | + |
| 137 | + sincosf_eval(xd, x_abs, sin_k, cos_k, sin_y, cosm1_y); |
| 138 | + |
| 139 | + return fputil::multiply_add(sin_y, -sin_k, |
187 | 140 | fputil::multiply_add(cosm1_y, cos_k, cos_k));
|
188 | 141 | }
|
189 | 142 |
|
|
0 commit comments