1 /*
2  * ====================================================
3  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4  *
5  * Developed at SunPro, a Sun Microsystems, Inc. business.
6  * Permission to use, copy, modify, and distribute this
7  * software is freely granted, provided that this notice
8  * is preserved.
9  * ====================================================
10  */
11 
12 /*
13   Long double expansions are
14   Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
15   and are incorporated herein by permission of the author.  The author
16   reserves the right to distribute this material elsewhere under different
17   copying permissions.  These modifications are distributed here under the
18   following terms:
19 
20     This library is free software; you can redistribute it and/or
21     modify it under the terms of the GNU Lesser General Public
22     License as published by the Free Software Foundation; either
23     version 2.1 of the License, or (at your option) any later version.
24 
25     This library is distributed in the hope that it will be useful,
26     but WITHOUT ANY WARRANTY; without even the implied warranty of
27     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28     Lesser General Public License for more details.
29 
30     You should have received a copy of the GNU Lesser General Public
31     License along with this library; if not, see
32     <https://www.gnu.org/licenses/>.  */
33 
34 /* __ieee754_asin(x)
35  * Method :
36  *	Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
37  *	we approximate asin(x) on [0,0.5] by
38  *		asin(x) = x + x*x^2*R(x^2)
39  *      Between .5 and .625 the approximation is
40  *              asin(0.5625 + x) = asin(0.5625) + x rS(x) / sS(x)
41  *	For x in [0.625,1]
42  *		asin(x) = pi/2-2*asin(sqrt((1-x)/2))
43  *	Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
44  *	then for x>0.98
45  *		asin(x) = pi/2 - 2*(s+s*z*R(z))
46  *			= pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
47  *	For x<=0.98, let pio4_hi = pio2_hi/2, then
48  *		f = hi part of s;
49  *		c = sqrt(z) - f = (z-f*f)/(s+f) 	...f+c=sqrt(z)
50  *	and
51  *		asin(x) = pi/2 - 2*(s+s*z*R(z))
52  *			= pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
53  *			= pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
54  *
55  * Special cases:
56  *	if x is NaN, return x itself;
57  *	if |x|>1, return NaN with invalid signal.
58  *
59  */
60 
61 
62 #include <float.h>
63 #include <math.h>
64 #include <math-barriers.h>
65 #include <math_private.h>
66 #include <math-underflow.h>
67 #include <libm-alias-finite.h>
68 
69 static const _Float128
70   one = 1,
71   huge = L(1.0e+4932),
72   pio2_hi = L(1.5707963267948966192313216916397514420986),
73   pio2_lo = L(4.3359050650618905123985220130216759843812E-35),
74   pio4_hi = L(7.8539816339744830961566084581987569936977E-1),
75 
76 	/* coefficient for R(x^2) */
77 
78   /* asin(x) = x + x^3 pS(x^2) / qS(x^2)
79      0 <= x <= 0.5
80      peak relative error 1.9e-35  */
81   pS0 = L(-8.358099012470680544198472400254596543711E2),
82   pS1 =  L(3.674973957689619490312782828051860366493E3),
83   pS2 = L(-6.730729094812979665807581609853656623219E3),
84   pS3 =  L(6.643843795209060298375552684423454077633E3),
85   pS4 = L(-3.817341990928606692235481812252049415993E3),
86   pS5 =  L(1.284635388402653715636722822195716476156E3),
87   pS6 = L(-2.410736125231549204856567737329112037867E2),
88   pS7 =  L(2.219191969382402856557594215833622156220E1),
89   pS8 = L(-7.249056260830627156600112195061001036533E-1),
90   pS9 =  L(1.055923570937755300061509030361395604448E-3),
91 
92   qS0 = L(-5.014859407482408326519083440151745519205E3),
93   qS1 =  L(2.430653047950480068881028451580393430537E4),
94   qS2 = L(-4.997904737193653607449250593976069726962E4),
95   qS3 =  L(5.675712336110456923807959930107347511086E4),
96   qS4 = L(-3.881523118339661268482937768522572588022E4),
97   qS5 =  L(1.634202194895541569749717032234510811216E4),
98   qS6 = L(-4.151452662440709301601820849901296953752E3),
99   qS7 =  L(5.956050864057192019085175976175695342168E2),
100   qS8 = L(-4.175375777334867025769346564600396877176E1),
101   /* 1.000000000000000000000000000000000000000E0 */
102 
103   /* asin(0.5625 + x) = asin(0.5625) + x rS(x) / sS(x)
104      -0.0625 <= x <= 0.0625
105      peak relative error 3.3e-35  */
106   rS0 = L(-5.619049346208901520945464704848780243887E0),
107   rS1 =  L(4.460504162777731472539175700169871920352E1),
108   rS2 = L(-1.317669505315409261479577040530751477488E2),
109   rS3 =  L(1.626532582423661989632442410808596009227E2),
110   rS4 = L(-3.144806644195158614904369445440583873264E1),
111   rS5 = L(-9.806674443470740708765165604769099559553E1),
112   rS6 =  L(5.708468492052010816555762842394927806920E1),
113   rS7 =  L(1.396540499232262112248553357962639431922E1),
114   rS8 = L(-1.126243289311910363001762058295832610344E1),
115   rS9 = L(-4.956179821329901954211277873774472383512E-1),
116   rS10 =  L(3.313227657082367169241333738391762525780E-1),
117 
118   sS0 = L(-4.645814742084009935700221277307007679325E0),
119   sS1 =  L(3.879074822457694323970438316317961918430E1),
120   sS2 = L(-1.221986588013474694623973554726201001066E2),
121   sS3 =  L(1.658821150347718105012079876756201905822E2),
122   sS4 = L(-4.804379630977558197953176474426239748977E1),
123   sS5 = L(-1.004296417397316948114344573811562952793E2),
124   sS6 =  L(7.530281592861320234941101403870010111138E1),
125   sS7 =  L(1.270735595411673647119592092304357226607E1),
126   sS8 = L(-1.815144839646376500705105967064792930282E1),
127   sS9 = L(-7.821597334910963922204235247786840828217E-2),
128   /*  1.000000000000000000000000000000000000000E0 */
129 
130  asinr5625 =  L(5.9740641664535021430381036628424864397707E-1);
131 
132 
133 
134 _Float128
__ieee754_asinl(_Float128 x)135 __ieee754_asinl (_Float128 x)
136 {
137   _Float128 t, w, p, q, c, r, s;
138   int32_t ix, sign, flag;
139   ieee854_long_double_shape_type u;
140 
141   flag = 0;
142   u.value = x;
143   sign = u.parts32.w0;
144   ix = sign & 0x7fffffff;
145   u.parts32.w0 = ix;    /* |x| */
146   if (ix >= 0x3fff0000)	/* |x|>= 1 */
147     {
148       if (ix == 0x3fff0000
149 	  && (u.parts32.w1 | u.parts32.w2 | u.parts32.w3) == 0)
150 	/* asin(1)=+-pi/2 with inexact */
151 	return x * pio2_hi + x * pio2_lo;
152       return (x - x) / (x - x);	/* asin(|x|>1) is NaN */
153     }
154   else if (ix < 0x3ffe0000) /* |x| < 0.5 */
155     {
156       if (ix < 0x3fc60000) /* |x| < 2**-57 */
157 	{
158 	  math_check_force_underflow (x);
159 	  _Float128 force_inexact = huge + x;
160 	  math_force_eval (force_inexact);
161 	  return x;		/* return x with inexact if x!=0 */
162 	}
163       else
164 	{
165 	  t = x * x;
166 	  /* Mark to use pS, qS later on.  */
167 	  flag = 1;
168 	}
169     }
170   else if (ix < 0x3ffe4000) /* 0.625 */
171     {
172       t = u.value - 0.5625;
173       p = ((((((((((rS10 * t
174 		    + rS9) * t
175 		   + rS8) * t
176 		  + rS7) * t
177 		 + rS6) * t
178 		+ rS5) * t
179 	       + rS4) * t
180 	      + rS3) * t
181 	     + rS2) * t
182 	    + rS1) * t
183 	   + rS0) * t;
184 
185       q = ((((((((( t
186 		    + sS9) * t
187 		  + sS8) * t
188 		 + sS7) * t
189 		+ sS6) * t
190 	       + sS5) * t
191 	      + sS4) * t
192 	     + sS3) * t
193 	    + sS2) * t
194 	   + sS1) * t
195 	+ sS0;
196       t = asinr5625 + p / q;
197       if ((sign & 0x80000000) == 0)
198 	return t;
199       else
200 	return -t;
201     }
202   else
203     {
204       /* 1 > |x| >= 0.625 */
205       w = one - u.value;
206       t = w * 0.5;
207     }
208 
209   p = (((((((((pS9 * t
210 	       + pS8) * t
211 	      + pS7) * t
212 	     + pS6) * t
213 	    + pS5) * t
214 	   + pS4) * t
215 	  + pS3) * t
216 	 + pS2) * t
217 	+ pS1) * t
218        + pS0) * t;
219 
220   q = (((((((( t
221 	      + qS8) * t
222 	     + qS7) * t
223 	    + qS6) * t
224 	   + qS5) * t
225 	  + qS4) * t
226 	 + qS3) * t
227 	+ qS2) * t
228        + qS1) * t
229     + qS0;
230 
231   if (flag) /* 2^-57 < |x| < 0.5 */
232     {
233       w = p / q;
234       return x + x * w;
235     }
236 
237   s = sqrtl (t);
238   if (ix >= 0x3ffef333) /* |x| > 0.975 */
239     {
240       w = p / q;
241       t = pio2_hi - (2.0 * (s + s * w) - pio2_lo);
242     }
243   else
244     {
245       u.value = s;
246       u.parts32.w3 = 0;
247       u.parts32.w2 = 0;
248       w = u.value;
249       c = (t - w * w) / (s + w);
250       r = p / q;
251       p = 2.0 * s * r - (pio2_lo - 2.0 * c);
252       q = pio4_hi - 2.0 * w;
253       t = pio4_hi - (p - q);
254     }
255 
256   if ((sign & 0x80000000) == 0)
257     return t;
258   else
259     return -t;
260 }
261 libm_alias_finite (__ieee754_asinl, __asinl)
262