1 | /* |
2 | * IBM Accurate Mathematical Library |
3 | * written by International Business Machines Corp. |
4 | * Copyright (C) 2001-2021 Free Software Foundation, Inc. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU Lesser General Public License as published by |
8 | * the Free Software Foundation; either version 2.1 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public License |
17 | * along with this program; if not, see <https://www.gnu.org/licenses/>. |
18 | */ |
19 | /******************************************************************/ |
20 | /* MODULE_NAME:uasncs.c */ |
21 | /* */ |
22 | /* FUNCTIONS: uasin */ |
23 | /* uacos */ |
24 | /* FILES NEEDED: dla.h endian.h mydefs.h usncs.h */ |
25 | /* sincos.tbl asincos.tbl powtwo.tbl root.tbl */ |
26 | /* */ |
27 | /******************************************************************/ |
28 | #include "endian.h" |
29 | #include "mydefs.h" |
30 | #include "asincos.tbl" |
31 | #include "root.tbl" |
32 | #include "powtwo.tbl" |
33 | #include "uasncs.h" |
34 | #include <float.h> |
35 | #include <math.h> |
36 | #include <math_private.h> |
37 | #include <math-underflow.h> |
38 | #include <libm-alias-finite.h> |
39 | |
40 | #ifndef SECTION |
41 | # define SECTION |
42 | #endif |
43 | |
44 | /* asin with max ULP of ~0.516 based on random sampling. */ |
45 | double |
46 | SECTION |
47 | __ieee754_asin(double x){ |
48 | double x2,xx,res1,p,t,res,r,cor,cc,y,c,z; |
49 | mynumber u,v; |
50 | int4 k,m,n; |
51 | |
52 | u.x = x; |
53 | m = u.i[HIGH_HALF]; |
54 | k = 0x7fffffff&m; /* no sign */ |
55 | |
56 | if (k < 0x3e500000) |
57 | { |
58 | math_check_force_underflow (x); |
59 | return x; /* for x->0 => sin(x)=x */ |
60 | } |
61 | /*----------------------2^-26 <= |x| < 2^ -3 -----------------*/ |
62 | else |
63 | if (k < 0x3fc00000) { |
64 | x2 = x*x; |
65 | t = (((((f6*x2 + f5)*x2 + f4)*x2 + f3)*x2 + f2)*x2 + f1)*(x2*x); |
66 | res = x+t; /* res=arcsin(x) according to Taylor series */ |
67 | /* Max ULP is 0.513. */ |
68 | return res; |
69 | } |
70 | /*---------------------0.125 <= |x| < 0.5 -----------------------------*/ |
71 | else if (k < 0x3fe00000) { |
72 | if (k<0x3fd00000) n = 11*((k&0x000fffff)>>15); |
73 | else n = 11*((k&0x000fffff)>>14)+352; |
74 | if (m>0) xx = x - asncs.x[n]; |
75 | else xx = -x - asncs.x[n]; |
76 | t = asncs.x[n+1]*xx; |
77 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+xx*(asncs.x[n+5] |
78 | +xx*asncs.x[n+6]))))+asncs.x[n+7]; |
79 | t+=p; |
80 | res =asncs.x[n+8] +t; |
81 | /* Max ULP is 0.524. */ |
82 | return (m>0)?res:-res; |
83 | } /* else if (k < 0x3fe00000) */ |
84 | /*-------------------- 0.5 <= |x| < 0.75 -----------------------------*/ |
85 | else |
86 | if (k < 0x3fe80000) { |
87 | n = 1056+((k&0x000fe000)>>11)*3; |
88 | if (m>0) xx = x - asncs.x[n]; |
89 | else xx = -x - asncs.x[n]; |
90 | t = asncs.x[n+1]*xx; |
91 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+xx*(asncs.x[n+5] |
92 | +xx*(asncs.x[n+6]+xx*asncs.x[n+7])))))+asncs.x[n+8]; |
93 | t+=p; |
94 | res =asncs.x[n+9] +t; |
95 | /* Max ULP is 0.505. */ |
96 | return (m>0)?res:-res; |
97 | } /* else if (k < 0x3fe80000) */ |
98 | /*--------------------- 0.75 <= |x|< 0.921875 ----------------------*/ |
99 | else |
100 | if (k < 0x3fed8000) { |
101 | n = 992+((k&0x000fe000)>>13)*13; |
102 | if (m>0) xx = x - asncs.x[n]; |
103 | else xx = -x - asncs.x[n]; |
104 | t = asncs.x[n+1]*xx; |
105 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+xx*(asncs.x[n+5] |
106 | +xx*(asncs.x[n+6]+xx*(asncs.x[n+7]+xx*asncs.x[n+8]))))))+asncs.x[n+9]; |
107 | t+=p; |
108 | res =asncs.x[n+10] +t; |
109 | /* Max ULP is 0.505. */ |
110 | return (m>0)?res:-res; |
111 | } /* else if (k < 0x3fed8000) */ |
112 | /*-------------------0.921875 <= |x| < 0.953125 ------------------------*/ |
113 | else |
114 | if (k < 0x3fee8000) { |
115 | n = 884+((k&0x000fe000)>>13)*14; |
116 | if (m>0) xx = x - asncs.x[n]; |
117 | else xx = -x - asncs.x[n]; |
118 | t = asncs.x[n+1]*xx; |
119 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
120 | xx*(asncs.x[n+5]+xx*(asncs.x[n+6] |
121 | +xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+ |
122 | xx*asncs.x[n+9])))))))+asncs.x[n+10]; |
123 | t+=p; |
124 | res =asncs.x[n+11] +t; |
125 | /* Max ULP is 0.505. */ |
126 | return (m>0)?res:-res; |
127 | } /* else if (k < 0x3fee8000) */ |
128 | |
129 | /*--------------------0.953125 <= |x| < 0.96875 ------------------------*/ |
130 | else |
131 | if (k < 0x3fef0000) { |
132 | n = 768+((k&0x000fe000)>>13)*15; |
133 | if (m>0) xx = x - asncs.x[n]; |
134 | else xx = -x - asncs.x[n]; |
135 | t = asncs.x[n+1]*xx; |
136 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
137 | xx*(asncs.x[n+5]+xx*(asncs.x[n+6] |
138 | +xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+ |
139 | xx*(asncs.x[n+9]+xx*asncs.x[n+10]))))))))+asncs.x[n+11]; |
140 | t+=p; |
141 | res =asncs.x[n+12] +t; |
142 | /* Max ULP is 0.505. */ |
143 | return (m>0)?res:-res; |
144 | } /* else if (k < 0x3fef0000) */ |
145 | /*--------------------0.96875 <= |x| < 1 --------------------------------*/ |
146 | else |
147 | if (k<0x3ff00000) { |
148 | z = 0.5*((m>0)?(1.0-x):(1.0+x)); |
149 | v.x=z; |
150 | k=v.i[HIGH_HALF]; |
151 | t=inroot[(k&0x001fffff)>>14]*powtwo[511-(k>>21)]; |
152 | r=1.0-t*t*z; |
153 | t = t*(rt0+r*(rt1+r*(rt2+r*rt3))); |
154 | c=t*z; |
155 | t=c*(1.5-0.5*t*c); |
156 | y=(c+t24)-t24; |
157 | cc = (z-y*y)/(t+y); |
158 | p=(((((f6*z+f5)*z+f4)*z+f3)*z+f2)*z+f1)*z; |
159 | cor = (hp1.x - 2.0*cc)-2.0*(y+cc)*p; |
160 | res1 = hp0.x - 2.0*y; |
161 | res =res1 + cor; |
162 | /* Max ULP is 0.5015. */ |
163 | return (m>0)?res:-res; |
164 | } /* else if (k < 0x3ff00000) */ |
165 | /*---------------------------- |x|>=1 -------------------------------*/ |
166 | else if (k==0x3ff00000 && u.i[LOW_HALF]==0) return (m>0)?hp0.x:-hp0.x; |
167 | else |
168 | if (k>0x7ff00000 || (k == 0x7ff00000 && u.i[LOW_HALF] != 0)) return x + x; |
169 | else { |
170 | u.i[HIGH_HALF]=0x7ff00000; |
171 | v.i[HIGH_HALF]=0x7ff00000; |
172 | u.i[LOW_HALF]=0; |
173 | v.i[LOW_HALF]=0; |
174 | return u.x/v.x; /* NaN */ |
175 | } |
176 | } |
177 | #ifndef __ieee754_asin |
178 | libm_alias_finite (__ieee754_asin, __asin) |
179 | #endif |
180 | |
181 | /*******************************************************************/ |
182 | /* */ |
183 | /* End of arcsine, below is arccosine */ |
184 | /* */ |
185 | /*******************************************************************/ |
186 | |
187 | /* acos with max ULP of ~0.523 based on random sampling. */ |
188 | double |
189 | SECTION |
190 | __ieee754_acos(double x) |
191 | { |
192 | double x2,xx,res1,p,t,res,r,cor,cc,y,c,z; |
193 | mynumber u,v; |
194 | int4 k,m,n; |
195 | u.x = x; |
196 | m = u.i[HIGH_HALF]; |
197 | k = 0x7fffffff&m; |
198 | /*------------------- |x|<2.77556*10^-17 ----------------------*/ |
199 | if (k < 0x3c880000) return hp0.x; |
200 | |
201 | /*----------------- 2.77556*10^-17 <= |x| < 2^-3 --------------*/ |
202 | else |
203 | if (k < 0x3fc00000) { |
204 | x2 = x*x; |
205 | t = (((((f6*x2 + f5)*x2 + f4)*x2 + f3)*x2 + f2)*x2 + f1)*(x2*x); |
206 | r=hp0.x-x; |
207 | cor=(((hp0.x-r)-x)+hp1.x)-t; |
208 | res = r+cor; |
209 | /* Max ULP is 0.502. */ |
210 | return res; |
211 | } /* else if (k < 0x3fc00000) */ |
212 | /*---------------------- 0.125 <= |x| < 0.5 --------------------*/ |
213 | else |
214 | if (k < 0x3fe00000) { |
215 | if (k<0x3fd00000) n = 11*((k&0x000fffff)>>15); |
216 | else n = 11*((k&0x000fffff)>>14)+352; |
217 | if (m>0) xx = x - asncs.x[n]; |
218 | else xx = -x - asncs.x[n]; |
219 | t = asncs.x[n+1]*xx; |
220 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
221 | xx*(asncs.x[n+5]+xx*asncs.x[n+6]))))+asncs.x[n+7]; |
222 | t+=p; |
223 | y = (m>0)?(hp0.x-asncs.x[n+8]):(hp0.x+asncs.x[n+8]); |
224 | t = (m>0)?(hp1.x-t):(hp1.x+t); |
225 | res = y+t; |
226 | /* Max ULP is 0.51. */ |
227 | return res; |
228 | } /* else if (k < 0x3fe00000) */ |
229 | |
230 | /*--------------------------- 0.5 <= |x| < 0.75 ---------------------*/ |
231 | else |
232 | if (k < 0x3fe80000) { |
233 | n = 1056+((k&0x000fe000)>>11)*3; |
234 | if (m>0) {xx = x - asncs.x[n]; } |
235 | else {xx = -x - asncs.x[n]; } |
236 | t = asncs.x[n+1]*xx; |
237 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
238 | xx*(asncs.x[n+5]+xx*(asncs.x[n+6]+ |
239 | xx*asncs.x[n+7])))))+asncs.x[n+8]; |
240 | t+=p; |
241 | y = (m>0)?(hp0.x-asncs.x[n+9]):(hp0.x+asncs.x[n+9]); |
242 | t = (m>0)?(hp1.x-t):(hp1.x+t); |
243 | res = y+t; |
244 | /* Max ULP is 0.523 based on random sampling. */ |
245 | return res; |
246 | } /* else if (k < 0x3fe80000) */ |
247 | |
248 | /*------------------------- 0.75 <= |x| < 0.921875 -------------*/ |
249 | else |
250 | if (k < 0x3fed8000) { |
251 | n = 992+((k&0x000fe000)>>13)*13; |
252 | if (m>0) {xx = x - asncs.x[n]; } |
253 | else {xx = -x - asncs.x[n]; } |
254 | t = asncs.x[n+1]*xx; |
255 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
256 | xx*(asncs.x[n+5]+xx*(asncs.x[n+6]+xx*(asncs.x[n+7]+ |
257 | xx*asncs.x[n+8]))))))+asncs.x[n+9]; |
258 | t+=p; |
259 | y = (m>0)?(hp0.x-asncs.x[n+10]):(hp0.x+asncs.x[n+10]); |
260 | t = (m>0)?(hp1.x-t):(hp1.x+t); |
261 | res = y+t; |
262 | /* Max ULP is 0.523 based on random sampling. */ |
263 | return res; |
264 | } /* else if (k < 0x3fed8000) */ |
265 | |
266 | /*-------------------0.921875 <= |x| < 0.953125 ------------------*/ |
267 | else |
268 | if (k < 0x3fee8000) { |
269 | n = 884+((k&0x000fe000)>>13)*14; |
270 | if (m>0) {xx = x - asncs.x[n]; } |
271 | else {xx = -x - asncs.x[n]; } |
272 | t = asncs.x[n+1]*xx; |
273 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
274 | xx*(asncs.x[n+5]+xx*(asncs.x[n+6] |
275 | +xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+ |
276 | xx*asncs.x[n+9])))))))+asncs.x[n+10]; |
277 | t+=p; |
278 | y = (m>0)?(hp0.x-asncs.x[n+11]):(hp0.x+asncs.x[n+11]); |
279 | t = (m>0)?(hp1.x-t):(hp1.x+t); |
280 | res = y+t; |
281 | /* Max ULP is 0.523 based on random sampling. */ |
282 | return res; |
283 | } /* else if (k < 0x3fee8000) */ |
284 | |
285 | /*--------------------0.953125 <= |x| < 0.96875 ----------------*/ |
286 | else |
287 | if (k < 0x3fef0000) { |
288 | n = 768+((k&0x000fe000)>>13)*15; |
289 | if (m>0) {xx = x - asncs.x[n]; } |
290 | else {xx = -x - asncs.x[n]; } |
291 | t = asncs.x[n+1]*xx; |
292 | p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+ |
293 | xx*(asncs.x[n+5]+xx*(asncs.x[n+6] |
294 | +xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+xx*(asncs.x[n+9]+ |
295 | xx*asncs.x[n+10]))))))))+asncs.x[n+11]; |
296 | t+=p; |
297 | y = (m>0)?(hp0.x-asncs.x[n+12]):(hp0.x+asncs.x[n+12]); |
298 | t = (m>0)?(hp1.x-t):(hp1.x+t); |
299 | res = y+t; |
300 | /* Max ULP is 0.523 based on random sampling. */ |
301 | return res; |
302 | } /* else if (k < 0x3fef0000) */ |
303 | /*-----------------0.96875 <= |x| < 1 ---------------------------*/ |
304 | |
305 | else |
306 | if (k<0x3ff00000) { |
307 | z = 0.5*((m>0)?(1.0-x):(1.0+x)); |
308 | v.x=z; |
309 | k=v.i[HIGH_HALF]; |
310 | t=inroot[(k&0x001fffff)>>14]*powtwo[511-(k>>21)]; |
311 | r=1.0-t*t*z; |
312 | t = t*(rt0+r*(rt1+r*(rt2+r*rt3))); |
313 | c=t*z; |
314 | t=c*(1.5-0.5*t*c); |
315 | y = (t27*c+c)-t27*c; |
316 | cc = (z-y*y)/(t+y); |
317 | p=(((((f6*z+f5)*z+f4)*z+f3)*z+f2)*z+f1)*z; |
318 | if (m<0) { |
319 | cor = (hp1.x - cc)-(y+cc)*p; |
320 | res1 = hp0.x - y; |
321 | res =res1 + cor; |
322 | /* Max ULP is 0.501. */ |
323 | return (res+res); |
324 | } |
325 | else { |
326 | cor = cc+p*(y+cc); |
327 | res = y + cor; |
328 | /* Max ULP is 0.515. */ |
329 | return (res+res); |
330 | } |
331 | } /* else if (k < 0x3ff00000) */ |
332 | |
333 | /*---------------------------- |x|>=1 -----------------------*/ |
334 | else |
335 | if (k==0x3ff00000 && u.i[LOW_HALF]==0) return (m>0)?0:2.0*hp0.x; |
336 | else |
337 | if (k>0x7ff00000 || (k == 0x7ff00000 && u.i[LOW_HALF] != 0)) return x + x; |
338 | else { |
339 | u.i[HIGH_HALF]=0x7ff00000; |
340 | v.i[HIGH_HALF]=0x7ff00000; |
341 | u.i[LOW_HALF]=0; |
342 | v.i[LOW_HALF]=0; |
343 | return u.x/v.x; |
344 | } |
345 | } |
346 | #ifndef __ieee754_acos |
347 | libm_alias_finite (__ieee754_acos, __acos) |
348 | #endif |
349 | |