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
18    the 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_acosl(x)
35  * Method :
36  *      acos(x)  = pi/2 - asin(x)
37  *      acos(-x) = pi/2 + asin(x)
38  * For |x| <= 0.375
39  *      acos(x) = pi/2 - asin(x)
40  * Between .375 and .5 the approximation is
41  *      acos(0.4375 + x) = acos(0.4375) + x P(x) / Q(x)
42  * Between .5 and .625 the approximation is
43  *      acos(0.5625 + x) = acos(0.5625) + x rS(x) / sS(x)
44  * For x > 0.625,
45  *      acos(x) = 2 asin(sqrt((1-x)/2))
46  *      computed with an extended precision square root in the leading term.
47  * For x < -0.625
48  *      acos(x) = pi - 2 asin(sqrt((1-|x|)/2))
49  *
50  * Special cases:
51  *      if x is NaN, return x itself;
52  *      if |x|>1, return NaN with invalid signal.
53  *
54  * Functions needed: sqrtl.
55  */
56 
57 #include <math.h>
58 #include <math_private.h>
59 #include <libm-alias-finite.h>
60 
61 static const long double
62   one = 1.0L,
63   pio2_hi = 1.5707963267948966192313216916397514420986L,
64   pio2_lo = 4.3359050650618905123985220130216759843812E-35L,
65 
66   /* acos(0.5625 + x) = acos(0.5625) + x rS(x) / sS(x)
67      -0.0625 <= x <= 0.0625
68      peak relative error 3.3e-35  */
69 
70   rS0 =  5.619049346208901520945464704848780243887E0L,
71   rS1 = -4.460504162777731472539175700169871920352E1L,
72   rS2 =  1.317669505315409261479577040530751477488E2L,
73   rS3 = -1.626532582423661989632442410808596009227E2L,
74   rS4 =  3.144806644195158614904369445440583873264E1L,
75   rS5 =  9.806674443470740708765165604769099559553E1L,
76   rS6 = -5.708468492052010816555762842394927806920E1L,
77   rS7 = -1.396540499232262112248553357962639431922E1L,
78   rS8 =  1.126243289311910363001762058295832610344E1L,
79   rS9 =  4.956179821329901954211277873774472383512E-1L,
80   rS10 = -3.313227657082367169241333738391762525780E-1L,
81 
82   sS0 = -4.645814742084009935700221277307007679325E0L,
83   sS1 =  3.879074822457694323970438316317961918430E1L,
84   sS2 = -1.221986588013474694623973554726201001066E2L,
85   sS3 =  1.658821150347718105012079876756201905822E2L,
86   sS4 = -4.804379630977558197953176474426239748977E1L,
87   sS5 = -1.004296417397316948114344573811562952793E2L,
88   sS6 =  7.530281592861320234941101403870010111138E1L,
89   sS7 =  1.270735595411673647119592092304357226607E1L,
90   sS8 = -1.815144839646376500705105967064792930282E1L,
91   sS9 = -7.821597334910963922204235247786840828217E-2L,
92   /* 1.000000000000000000000000000000000000000E0 */
93 
94   acosr5625 = 9.7338991014954640492751132535550279812151E-1L,
95   pimacosr5625 = 2.1682027434402468335351320579240000860757E0L,
96 
97   /* acos(0.4375 + x) = acos(0.4375) + x rS(x) / sS(x)
98      -0.0625 <= x <= 0.0625
99      peak relative error 2.1e-35  */
100 
101   P0 =  2.177690192235413635229046633751390484892E0L,
102   P1 = -2.848698225706605746657192566166142909573E1L,
103   P2 =  1.040076477655245590871244795403659880304E2L,
104   P3 = -1.400087608918906358323551402881238180553E2L,
105   P4 =  2.221047917671449176051896400503615543757E1L,
106   P5 =  9.643714856395587663736110523917499638702E1L,
107   P6 = -5.158406639829833829027457284942389079196E1L,
108   P7 = -1.578651828337585944715290382181219741813E1L,
109   P8 =  1.093632715903802870546857764647931045906E1L,
110   P9 =  5.448925479898460003048760932274085300103E-1L,
111   P10 = -3.315886001095605268470690485170092986337E-1L,
112   Q0 = -1.958219113487162405143608843774587557016E0L,
113   Q1 =  2.614577866876185080678907676023269360520E1L,
114   Q2 = -9.990858606464150981009763389881793660938E1L,
115   Q3 =  1.443958741356995763628660823395334281596E2L,
116   Q4 = -3.206441012484232867657763518369723873129E1L,
117   Q5 = -1.048560885341833443564920145642588991492E2L,
118   Q6 =  6.745883931909770880159915641984874746358E1L,
119   Q7 =  1.806809656342804436118449982647641392951E1L,
120   Q8 = -1.770150690652438294290020775359580915464E1L,
121   Q9 = -5.659156469628629327045433069052560211164E-1L,
122   /* 1.000000000000000000000000000000000000000E0 */
123 
124   acosr4375 = 1.1179797320499710475919903296900511518755E0L,
125   pimacosr4375 = 2.0236129215398221908706530535894517323217E0L,
126 
127   /* asin(x) = x + x^3 pS(x^2) / qS(x^2)
128      0 <= x <= 0.5
129      peak relative error 1.9e-35  */
130   pS0 = -8.358099012470680544198472400254596543711E2L,
131   pS1 =  3.674973957689619490312782828051860366493E3L,
132   pS2 = -6.730729094812979665807581609853656623219E3L,
133   pS3 =  6.643843795209060298375552684423454077633E3L,
134   pS4 = -3.817341990928606692235481812252049415993E3L,
135   pS5 =  1.284635388402653715636722822195716476156E3L,
136   pS6 = -2.410736125231549204856567737329112037867E2L,
137   pS7 =  2.219191969382402856557594215833622156220E1L,
138   pS8 = -7.249056260830627156600112195061001036533E-1L,
139   pS9 =  1.055923570937755300061509030361395604448E-3L,
140 
141   qS0 = -5.014859407482408326519083440151745519205E3L,
142   qS1 =  2.430653047950480068881028451580393430537E4L,
143   qS2 = -4.997904737193653607449250593976069726962E4L,
144   qS3 =  5.675712336110456923807959930107347511086E4L,
145   qS4 = -3.881523118339661268482937768522572588022E4L,
146   qS5 =  1.634202194895541569749717032234510811216E4L,
147   qS6 = -4.151452662440709301601820849901296953752E3L,
148   qS7 =  5.956050864057192019085175976175695342168E2L,
149   qS8 = -4.175375777334867025769346564600396877176E1L;
150   /* 1.000000000000000000000000000000000000000E0 */
151 
152 long double
__ieee754_acosl(long double x)153 __ieee754_acosl (long double x)
154 {
155   long double a, z, r, w, p, q, s, t, f2;
156 
157   if (__glibc_unlikely (isnan (x)))
158     return x + x;
159   a = __builtin_fabsl (x);
160   if (a == 1.0L)
161     {
162       if (x > 0.0L)
163 	return 0.0;		/* acos(1) = 0  */
164       else
165 	return (2.0 * pio2_hi) + (2.0 * pio2_lo);	/* acos(-1)= pi */
166     }
167   else if (a > 1.0L)
168     {
169       return (x - x) / (x - x);	/* acos(|x| > 1) is NaN */
170     }
171   if (a < 0.5L)
172     {
173       if (a < 0x1p-106L)
174 	return pio2_hi + pio2_lo;
175       if (a < 0.4375L)
176 	{
177 	  /* Arcsine of x.  */
178 	  z = x * x;
179 	  p = (((((((((pS9 * z
180 		       + pS8) * z
181 		      + pS7) * z
182 		     + pS6) * z
183 		    + pS5) * z
184 		   + pS4) * z
185 		  + pS3) * z
186 		 + pS2) * z
187 		+ pS1) * z
188 	       + pS0) * z;
189 	  q = (((((((( z
190 		       + qS8) * z
191 		     + qS7) * z
192 		    + qS6) * z
193 		   + qS5) * z
194 		  + qS4) * z
195 		 + qS3) * z
196 		+ qS2) * z
197 	       + qS1) * z
198 	    + qS0;
199 	  r = x + x * p / q;
200 	  z = pio2_hi - (r - pio2_lo);
201 	  return z;
202 	}
203       /* .4375 <= |x| < .5 */
204       t = a - 0.4375L;
205       p = ((((((((((P10 * t
206 		    + P9) * t
207 		   + P8) * t
208 		  + P7) * t
209 		 + P6) * t
210 		+ P5) * t
211 	       + P4) * t
212 	      + P3) * t
213 	     + P2) * t
214 	    + P1) * t
215 	   + P0) * t;
216 
217       q = (((((((((t
218 		   + Q9) * t
219 		  + Q8) * t
220 		 + Q7) * t
221 		+ Q6) * t
222 	       + Q5) * t
223 	      + Q4) * t
224 	     + Q3) * t
225 	    + Q2) * t
226 	   + Q1) * t
227 	+ Q0;
228       r = p / q;
229       if (x < 0.0L)
230 	r = pimacosr4375 - r;
231       else
232 	r = acosr4375 + r;
233       return r;
234     }
235   else if (a < 0.625L)
236     {
237       t = a - 0.5625L;
238       p = ((((((((((rS10 * t
239 		    + rS9) * t
240 		   + rS8) * t
241 		  + rS7) * t
242 		 + rS6) * t
243 		+ rS5) * t
244 	       + rS4) * t
245 	      + rS3) * t
246 	     + rS2) * t
247 	    + rS1) * t
248 	   + rS0) * t;
249 
250       q = (((((((((t
251 		   + sS9) * t
252 		  + sS8) * t
253 		 + sS7) * t
254 		+ sS6) * t
255 	       + sS5) * t
256 	      + sS4) * t
257 	     + sS3) * t
258 	    + sS2) * t
259 	   + sS1) * t
260 	+ sS0;
261       if (x < 0.0L)
262 	r = pimacosr5625 - p / q;
263       else
264 	r = acosr5625 + p / q;
265       return r;
266     }
267   else
268     {				/* |x| >= .625 */
269       double shi, slo;
270 
271       z = (one - a) * 0.5;
272       s = sqrtl (z);
273       /* Compute an extended precision square root from
274 	 the Newton iteration  s -> 0.5 * (s + z / s).
275 	 The change w from s to the improved value is
276 	    w = 0.5 * (s + z / s) - s  = (s^2 + z)/2s - s = (z - s^2)/2s.
277 	  Express s = f1 + f2 where f1 * f1 is exactly representable.
278 	  w = (z - s^2)/2s = (z - f1^2 - 2 f1 f2 - f2^2)/2s .
279 	  s + w has extended precision.  */
280       ldbl_unpack (s, &shi, &slo);
281       a = shi;
282       f2 = slo;
283       w = z - a * a;
284       w = w - 2.0 * a * f2;
285       w = w - f2 * f2;
286       w = w / (2.0 * s);
287       /* Arcsine of s.  */
288       p = (((((((((pS9 * z
289 		   + pS8) * z
290 		  + pS7) * z
291 		 + pS6) * z
292 		+ pS5) * z
293 	       + pS4) * z
294 	      + pS3) * z
295 	     + pS2) * z
296 	    + pS1) * z
297 	   + pS0) * z;
298       q = (((((((( z
299 		   + qS8) * z
300 		 + qS7) * z
301 		+ qS6) * z
302 	       + qS5) * z
303 	      + qS4) * z
304 	     + qS3) * z
305 	    + qS2) * z
306 	   + qS1) * z
307 	+ qS0;
308       r = s + (w + s * p / q);
309 
310       if (x < 0.0L)
311 	w = pio2_hi + (pio2_lo - r);
312       else
313 	w = r;
314       return 2.0 * w;
315     }
316 }
317 libm_alias_finite (__ieee754_acosl, __acosl)
318