]> git.ipfire.org Git - thirdparty/gcc.git/blob - libquadmath/math/powq.c
Update most of libquadmath/math/ from glibc, automate update (PR libquadmath/68686).
[thirdparty/gcc.git] / libquadmath / math / powq.c
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 /* Expansions and modifications for 128-bit long double are
13 Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
14 and are incorporated herein by permission of the author. The author
15 reserves the right to distribute this material elsewhere under different
16 copying permissions. These modifications are distributed here under
17 the following terms:
18
19 This library is free software; you can redistribute it and/or
20 modify it under the terms of the GNU Lesser General Public
21 License as published by the Free Software Foundation; either
22 version 2.1 of the License, or (at your option) any later version.
23
24 This library is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 Lesser General Public License for more details.
28
29 You should have received a copy of the GNU Lesser General Public
30 License along with this library; if not, see
31 <http://www.gnu.org/licenses/>. */
32
33 /* powq(x,y) return x**y
34 *
35 * n
36 * Method: Let x = 2 * (1+f)
37 * 1. Compute and return log2(x) in two pieces:
38 * log2(x) = w1 + w2,
39 * where w1 has 113-53 = 60 bit trailing zeros.
40 * 2. Perform y*log2(x) = n+y' by simulating muti-precision
41 * arithmetic, where |y'|<=0.5.
42 * 3. Return x**y = 2**n*exp(y'*log2)
43 *
44 * Special cases:
45 * 1. (anything) ** 0 is 1
46 * 2. (anything) ** 1 is itself
47 * 3. (anything) ** NAN is NAN
48 * 4. NAN ** (anything except 0) is NAN
49 * 5. +-(|x| > 1) ** +INF is +INF
50 * 6. +-(|x| > 1) ** -INF is +0
51 * 7. +-(|x| < 1) ** +INF is +0
52 * 8. +-(|x| < 1) ** -INF is +INF
53 * 9. +-1 ** +-INF is NAN
54 * 10. +0 ** (+anything except 0, NAN) is +0
55 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
56 * 12. +0 ** (-anything except 0, NAN) is +INF
57 * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
58 * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
59 * 15. +INF ** (+anything except 0,NAN) is +INF
60 * 16. +INF ** (-anything except 0,NAN) is +0
61 * 17. -INF ** (anything) = -0 ** (-anything)
62 * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
63 * 19. (-anything except 0 and inf) ** (non-integer) is NAN
64 *
65 */
66
67 #include "quadmath-imp.h"
68
69 static const __float128 bp[] = {
70 1,
71 1.5Q,
72 };
73
74 /* log_2(1.5) */
75 static const __float128 dp_h[] = {
76 0.0,
77 5.8496250072115607565592654282227158546448E-1Q
78 };
79
80 /* Low part of log_2(1.5) */
81 static const __float128 dp_l[] = {
82 0.0,
83 1.0579781240112554492329533686862998106046E-16Q
84 };
85
86 static const __float128 zero = 0,
87 one = 1,
88 two = 2,
89 two113 = 1.0384593717069655257060992658440192E34Q,
90 huge = 1.0e3000Q,
91 tiny = 1.0e-3000Q;
92
93 /* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2))
94 z = (x-1)/(x+1)
95 1 <= x <= 1.25
96 Peak relative error 2.3e-37 */
97 static const __float128 LN[] =
98 {
99 -3.0779177200290054398792536829702930623200E1Q,
100 6.5135778082209159921251824580292116201640E1Q,
101 -4.6312921812152436921591152809994014413540E1Q,
102 1.2510208195629420304615674658258363295208E1Q,
103 -9.9266909031921425609179910128531667336670E-1Q
104 };
105 static const __float128 LD[] =
106 {
107 -5.129862866715009066465422805058933131960E1Q,
108 1.452015077564081884387441590064272782044E2Q,
109 -1.524043275549860505277434040464085593165E2Q,
110 7.236063513651544224319663428634139768808E1Q,
111 -1.494198912340228235853027849917095580053E1Q
112 /* 1.0E0 */
113 };
114
115 /* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2)))
116 0 <= x <= 0.5
117 Peak relative error 5.7e-38 */
118 static const __float128 PN[] =
119 {
120 5.081801691915377692446852383385968225675E8Q,
121 9.360895299872484512023336636427675327355E6Q,
122 4.213701282274196030811629773097579432957E4Q,
123 5.201006511142748908655720086041570288182E1Q,
124 9.088368420359444263703202925095675982530E-3Q,
125 };
126 static const __float128 PD[] =
127 {
128 3.049081015149226615468111430031590411682E9Q,
129 1.069833887183886839966085436512368982758E8Q,
130 8.259257717868875207333991924545445705394E5Q,
131 1.872583833284143212651746812884298360922E3Q,
132 /* 1.0E0 */
133 };
134
135 static const __float128
136 /* ln 2 */
137 lg2 = 6.9314718055994530941723212145817656807550E-1Q,
138 lg2_h = 6.9314718055994528622676398299518041312695E-1Q,
139 lg2_l = 2.3190468138462996154948554638754786504121E-17Q,
140 ovt = 8.0085662595372944372e-0017Q,
141 /* 2/(3*log(2)) */
142 cp = 9.6179669392597560490661645400126142495110E-1Q,
143 cp_h = 9.6179669392597555432899980587535537779331E-1Q,
144 cp_l = 5.0577616648125906047157785230014751039424E-17Q;
145
146 __float128
147 powq (__float128 x, __float128 y)
148 {
149 __float128 z, ax, z_h, z_l, p_h, p_l;
150 __float128 y1, t1, t2, r, s, sgn, t, u, v, w;
151 __float128 s2, s_h, s_l, t_h, t_l, ay;
152 int32_t i, j, k, yisint, n;
153 uint32_t ix, iy;
154 int32_t hx, hy;
155 ieee854_float128 o, p, q;
156
157 p.value = x;
158 hx = p.words32.w0;
159 ix = hx & 0x7fffffff;
160
161 q.value = y;
162 hy = q.words32.w0;
163 iy = hy & 0x7fffffff;
164
165
166 /* y==zero: x**0 = 1 */
167 if ((iy | q.words32.w1 | q.words32.w2 | q.words32.w3) == 0
168 && !issignalingq (x))
169 return one;
170
171 /* 1.0**y = 1; -1.0**+-Inf = 1 */
172 if (x == one && !issignalingq (y))
173 return one;
174 if (x == -1 && iy == 0x7fff0000
175 && (q.words32.w1 | q.words32.w2 | q.words32.w3) == 0)
176 return one;
177
178 /* +-NaN return x+y */
179 if ((ix > 0x7fff0000)
180 || ((ix == 0x7fff0000)
181 && ((p.words32.w1 | p.words32.w2 | p.words32.w3) != 0))
182 || (iy > 0x7fff0000)
183 || ((iy == 0x7fff0000)
184 && ((q.words32.w1 | q.words32.w2 | q.words32.w3) != 0)))
185 return x + y;
186
187 /* determine if y is an odd int when x < 0
188 * yisint = 0 ... y is not an integer
189 * yisint = 1 ... y is an odd int
190 * yisint = 2 ... y is an even int
191 */
192 yisint = 0;
193 if (hx < 0)
194 {
195 if (iy >= 0x40700000) /* 2^113 */
196 yisint = 2; /* even integer y */
197 else if (iy >= 0x3fff0000) /* 1.0 */
198 {
199 if (floorq (y) == y)
200 {
201 z = 0.5 * y;
202 if (floorq (z) == z)
203 yisint = 2;
204 else
205 yisint = 1;
206 }
207 }
208 }
209
210 /* special value of y */
211 if ((q.words32.w1 | q.words32.w2 | q.words32.w3) == 0)
212 {
213 if (iy == 0x7fff0000) /* y is +-inf */
214 {
215 if (((ix - 0x3fff0000) | p.words32.w1 | p.words32.w2 | p.words32.w3)
216 == 0)
217 return y - y; /* +-1**inf is NaN */
218 else if (ix >= 0x3fff0000) /* (|x|>1)**+-inf = inf,0 */
219 return (hy >= 0) ? y : zero;
220 else /* (|x|<1)**-,+inf = inf,0 */
221 return (hy < 0) ? -y : zero;
222 }
223 if (iy == 0x3fff0000)
224 { /* y is +-1 */
225 if (hy < 0)
226 return one / x;
227 else
228 return x;
229 }
230 if (hy == 0x40000000)
231 return x * x; /* y is 2 */
232 if (hy == 0x3ffe0000)
233 { /* y is 0.5 */
234 if (hx >= 0) /* x >= +0 */
235 return sqrtq (x);
236 }
237 }
238
239 ax = fabsq (x);
240 /* special value of x */
241 if ((p.words32.w1 | p.words32.w2 | p.words32.w3) == 0)
242 {
243 if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000)
244 {
245 z = ax; /*x is +-0,+-inf,+-1 */
246 if (hy < 0)
247 z = one / z; /* z = (1/|x|) */
248 if (hx < 0)
249 {
250 if (((ix - 0x3fff0000) | yisint) == 0)
251 {
252 z = (z - z) / (z - z); /* (-1)**non-int is NaN */
253 }
254 else if (yisint == 1)
255 z = -z; /* (x<0)**odd = -(|x|**odd) */
256 }
257 return z;
258 }
259 }
260
261 /* (x<0)**(non-int) is NaN */
262 if (((((uint32_t) hx >> 31) - 1) | yisint) == 0)
263 return (x - x) / (x - x);
264
265 /* sgn (sign of result -ve**odd) = -1 else = 1 */
266 sgn = one;
267 if (((((uint32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
268 sgn = -one; /* (-ve)**(odd int) */
269
270 /* |y| is huge.
271 2^-16495 = 1/2 of smallest representable value.
272 If (1 - 1/131072)^y underflows, y > 1.4986e9 */
273 if (iy > 0x401d654b)
274 {
275 /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
276 if (iy > 0x407d654b)
277 {
278 if (ix <= 0x3ffeffff)
279 return (hy < 0) ? huge * huge : tiny * tiny;
280 if (ix >= 0x3fff0000)
281 return (hy > 0) ? huge * huge : tiny * tiny;
282 }
283 /* over/underflow if x is not close to one */
284 if (ix < 0x3ffeffff)
285 return (hy < 0) ? sgn * huge * huge : sgn * tiny * tiny;
286 if (ix > 0x3fff0000)
287 return (hy > 0) ? sgn * huge * huge : sgn * tiny * tiny;
288 }
289
290 ay = y > 0 ? y : -y;
291 if (ay < 0x1p-128)
292 y = y < 0 ? -0x1p-128 : 0x1p-128;
293
294 n = 0;
295 /* take care subnormal number */
296 if (ix < 0x00010000)
297 {
298 ax *= two113;
299 n -= 113;
300 o.value = ax;
301 ix = o.words32.w0;
302 }
303 n += ((ix) >> 16) - 0x3fff;
304 j = ix & 0x0000ffff;
305 /* determine interval */
306 ix = j | 0x3fff0000; /* normalize ix */
307 if (j <= 0x3988)
308 k = 0; /* |x|<sqrt(3/2) */
309 else if (j < 0xbb67)
310 k = 1; /* |x|<sqrt(3) */
311 else
312 {
313 k = 0;
314 n += 1;
315 ix -= 0x00010000;
316 }
317
318 o.value = ax;
319 o.words32.w0 = ix;
320 ax = o.value;
321
322 /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
323 u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
324 v = one / (ax + bp[k]);
325 s = u * v;
326 s_h = s;
327
328 o.value = s_h;
329 o.words32.w3 = 0;
330 o.words32.w2 &= 0xf8000000;
331 s_h = o.value;
332 /* t_h=ax+bp[k] High */
333 t_h = ax + bp[k];
334 o.value = t_h;
335 o.words32.w3 = 0;
336 o.words32.w2 &= 0xf8000000;
337 t_h = o.value;
338 t_l = ax - (t_h - bp[k]);
339 s_l = v * ((u - s_h * t_h) - s_h * t_l);
340 /* compute log(ax) */
341 s2 = s * s;
342 u = LN[0] + s2 * (LN[1] + s2 * (LN[2] + s2 * (LN[3] + s2 * LN[4])));
343 v = LD[0] + s2 * (LD[1] + s2 * (LD[2] + s2 * (LD[3] + s2 * (LD[4] + s2))));
344 r = s2 * s2 * u / v;
345 r += s_l * (s_h + s);
346 s2 = s_h * s_h;
347 t_h = 3.0 + s2 + r;
348 o.value = t_h;
349 o.words32.w3 = 0;
350 o.words32.w2 &= 0xf8000000;
351 t_h = o.value;
352 t_l = r - ((t_h - 3.0) - s2);
353 /* u+v = s*(1+...) */
354 u = s_h * t_h;
355 v = s_l * t_h + t_l * s;
356 /* 2/(3log2)*(s+...) */
357 p_h = u + v;
358 o.value = p_h;
359 o.words32.w3 = 0;
360 o.words32.w2 &= 0xf8000000;
361 p_h = o.value;
362 p_l = v - (p_h - u);
363 z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */
364 z_l = cp_l * p_h + p_l * cp + dp_l[k];
365 /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
366 t = (__float128) n;
367 t1 = (((z_h + z_l) + dp_h[k]) + t);
368 o.value = t1;
369 o.words32.w3 = 0;
370 o.words32.w2 &= 0xf8000000;
371 t1 = o.value;
372 t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
373
374 /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
375 y1 = y;
376 o.value = y1;
377 o.words32.w3 = 0;
378 o.words32.w2 &= 0xf8000000;
379 y1 = o.value;
380 p_l = (y - y1) * t1 + y * t2;
381 p_h = y1 * t1;
382 z = p_l + p_h;
383 o.value = z;
384 j = o.words32.w0;
385 if (j >= 0x400d0000) /* z >= 16384 */
386 {
387 /* if z > 16384 */
388 if (((j - 0x400d0000) | o.words32.w1 | o.words32.w2 | o.words32.w3) != 0)
389 return sgn * huge * huge; /* overflow */
390 else
391 {
392 if (p_l + ovt > z - p_h)
393 return sgn * huge * huge; /* overflow */
394 }
395 }
396 else if ((j & 0x7fffffff) >= 0x400d01b9) /* z <= -16495 */
397 {
398 /* z < -16495 */
399 if (((j - 0xc00d01bc) | o.words32.w1 | o.words32.w2 | o.words32.w3)
400 != 0)
401 return sgn * tiny * tiny; /* underflow */
402 else
403 {
404 if (p_l <= z - p_h)
405 return sgn * tiny * tiny; /* underflow */
406 }
407 }
408 /* compute 2**(p_h+p_l) */
409 i = j & 0x7fffffff;
410 k = (i >> 16) - 0x3fff;
411 n = 0;
412 if (i > 0x3ffe0000)
413 { /* if |z| > 0.5, set n = [z+0.5] */
414 n = floorq (z + 0.5Q);
415 t = n;
416 p_h -= t;
417 }
418 t = p_l + p_h;
419 o.value = t;
420 o.words32.w3 = 0;
421 o.words32.w2 &= 0xf8000000;
422 t = o.value;
423 u = t * lg2_h;
424 v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
425 z = u + v;
426 w = v - (z - u);
427 /* exp(z) */
428 t = z * z;
429 u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4])));
430 v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t)));
431 t1 = z - t * u / v;
432 r = (z * t1) / (t1 - two) - (w + z * w);
433 z = one - (r - z);
434 o.value = z;
435 j = o.words32.w0;
436 j += (n << 16);
437 if ((j >> 16) <= 0)
438 {
439 z = scalbnq (z, n); /* subnormal output */
440 __float128 force_underflow = z * z;
441 math_force_eval (force_underflow);
442 }
443 else
444 {
445 o.words32.w0 = j;
446 z = o.value;
447 }
448 return sgn * z;
449 }