1/* Inline math functions for i387 and SSE.
2 Copyright (C) 1995-2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19#ifndef _MATH_H
20# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
21#endif
22
23#ifndef __extern_always_inline
24# define __MATH_INLINE __inline
25#else
26# define __MATH_INLINE __extern_always_inline
27#endif
28
29
30#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
31/* GCC 2.97 and up have builtins that actually can be used. */
32# if !__GNUC_PREREQ (2,97)
33/* ISO C99 defines some macros to perform unordered comparisons. The
34 ix87 FPU supports this with special opcodes and we should use them.
35 These must not be inline functions since we have to be able to handle
36 all floating-point types. */
37# undef isgreater
38# undef isgreaterequal
39# undef isless
40# undef islessequal
41# undef islessgreater
42# undef isunordered
43# ifdef __i686__
44/* For the PentiumPro and more recent processors we can provide
45 better code. */
46# define isgreater(x, y) \
47 ({ register char __result; \
48 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
49 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
50 __result; })
51# define isgreaterequal(x, y) \
52 ({ register char __result; \
53 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
54 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
55 __result; })
56
57# define isless(x, y) \
58 ({ register char __result; \
59 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
60 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
61 __result; })
62
63# define islessequal(x, y) \
64 ({ register char __result; \
65 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
66 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
67 __result; })
68
69# define islessgreater(x, y) \
70 ({ register char __result; \
71 __asm__ ("fucomip %%st(1), %%st; setne %%al" \
72 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
73 __result; })
74
75# define isunordered(x, y) \
76 ({ register char __result; \
77 __asm__ ("fucomip %%st(1), %%st; setp %%al" \
78 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
79 __result; })
80# else
81/* This is the dumb, portable code for i386 and above. */
82# define isgreater(x, y) \
83 ({ register char __result; \
84 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
85 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
86 __result; })
87
88# define isgreaterequal(x, y) \
89 ({ register char __result; \
90 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
91 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
92 __result; })
93
94# define isless(x, y) \
95 ({ register char __result; \
96 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
97 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
98 __result; })
99
100# define islessequal(x, y) \
101 ({ register char __result; \
102 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
103 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
104 __result; })
105
106# define islessgreater(x, y) \
107 ({ register char __result; \
108 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \
109 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
110 __result; })
111
112# define isunordered(x, y) \
113 ({ register char __result; \
114 __asm__ ("fucompp; fnstsw; sahf; setp %%al" \
115 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
116 __result; })
117# endif /* __i686__ */
118# endif /* GCC 2.97 */
119
120/* The gcc, version 2.7 or below, has problems with all this inlining
121 code. So disable it for this version of the compiler. */
122# if __GNUC_PREREQ (2, 8)
123
124/* Test for negative number. Used in the signbit() macro. */
125__MATH_INLINE int
126__NTH (__signbitf (float __x))
127{
128# ifdef __SSE2_MATH__
129 int __m;
130 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
131 return (__m & 0x8) != 0;
132# else
133 __extension__ union { float __f; int __i; } __u = { __f: __x };
134 return __u.__i < 0;
135# endif
136}
137__MATH_INLINE int
138__NTH (__signbit (double __x))
139{
140# ifdef __SSE2_MATH__
141 int __m;
142 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
143 return (__m & 0x80) != 0;
144# else
145 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
146 return __u.__i[1] < 0;
147# endif
148}
149__MATH_INLINE int
150__NTH (__signbitl (long double __x))
151{
152 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
153 return (__u.__i[2] & 0x8000) != 0;
154}
155
156# endif
157#endif
158
159
160/* The gcc, version 2.7 or below, has problems with all this inlining
161 code. So disable it for this version of the compiler. */
162#if __GNUC_PREREQ (2, 8)
163# if !__GNUC_PREREQ (3, 4) && !defined __NO_MATH_INLINES \
164 && defined __OPTIMIZE__
165/* GCC 3.4 introduced builtins for all functions below, so
166 there's no need to define any of these inline functions. */
167
168# ifdef __USE_ISOC99
169
170/* Round to nearest integer. */
171# ifdef __SSE_MATH__
172__MATH_INLINE long int
173__NTH (lrintf (float __x))
174{
175 long int __res;
176 /* Mark as volatile since the result is dependent on the state of
177 the SSE control register (the rounding mode). Otherwise GCC might
178 remove these assembler instructions since it does not know about
179 the rounding mode change and cannot currently be told. */
180 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
181 return __res;
182}
183# endif
184# ifdef __SSE2_MATH__
185__MATH_INLINE long int
186__NTH (lrint (double __x))
187{
188 long int __res;
189 /* Mark as volatile since the result is dependent on the state of
190 the SSE control register (the rounding mode). Otherwise GCC might
191 remove these assembler instructions since it does not know about
192 the rounding mode change and cannot currently be told. */
193 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
194 return __res;
195}
196# endif
197# ifdef __x86_64__
198__extension__
199__MATH_INLINE long long int
200__NTH (llrintf (float __x))
201{
202 long long int __res;
203 /* Mark as volatile since the result is dependent on the state of
204 the SSE control register (the rounding mode). Otherwise GCC might
205 remove these assembler instructions since it does not know about
206 the rounding mode change and cannot currently be told. */
207 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
208 return __res;
209}
210__extension__
211__MATH_INLINE long long int
212__NTH (llrint (double __x))
213{
214 long long int __res;
215 /* Mark as volatile since the result is dependent on the state of
216 the SSE control register (the rounding mode). Otherwise GCC might
217 remove these assembler instructions since it does not know about
218 the rounding mode change and cannot currently be told. */
219 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
220 return __res;
221}
222# endif
223
224# if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
225 && defined __SSE2_MATH__
226/* Determine maximum of two values. */
227__MATH_INLINE float
228__NTH (fmaxf (float __x, float __y))
229{
230# ifdef __AVX__
231 float __res;
232 __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
233 return __res;
234# else
235 __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
236 return __x;
237# endif
238}
239__MATH_INLINE double
240__NTH (fmax (double __x, double __y))
241{
242# ifdef __AVX__
243 float __res;
244 __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
245 return __res;
246# else
247 __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
248 return __x;
249# endif
250}
251
252/* Determine minimum of two values. */
253__MATH_INLINE float
254__NTH (fminf (float __x, float __y))
255{
256# ifdef __AVX__
257 float __res;
258 __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
259 return __res;
260# else
261 __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
262 return __x;
263# endif
264}
265__MATH_INLINE double
266__NTH (fmin (double __x, double __y))
267{
268# ifdef __AVX__
269 float __res;
270 __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
271 return __res;
272# else
273 __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
274 return __x;
275# endif
276}
277# endif
278
279# endif
280
281# if defined __SSE4_1__ && defined __SSE2_MATH__
282# if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
283
284/* Round to nearest integer. */
285__MATH_INLINE double
286__NTH (rint (double __x))
287{
288 double __res;
289 /* Mark as volatile since the result is dependent on the state of
290 the SSE control register (the rounding mode). Otherwise GCC might
291 remove these assembler instructions since it does not know about
292 the rounding mode change and cannot currently be told. */
293 __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
294 return __res;
295}
296__MATH_INLINE float
297__NTH (rintf (float __x))
298{
299 float __res;
300 /* Mark as volatile since the result is dependent on the state of
301 the SSE control register (the rounding mode). Otherwise GCC might
302 remove these assembler instructions since it does not know about
303 the rounding mode change and cannot currently be told. */
304 __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
305 return __res;
306}
307
308# ifdef __USE_ISOC99
309/* Round to nearest integer without raising inexact exception. */
310__MATH_INLINE double
311__NTH (nearbyint (double __x))
312{
313 double __res;
314 /* Mark as volatile since the result is dependent on the state of
315 the SSE control register (the rounding mode). Otherwise GCC might
316 remove these assembler instructions since it does not know about
317 the rounding mode change and cannot currently be told. */
318 __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
319 return __res;
320}
321__MATH_INLINE float
322__NTH (nearbyintf (float __x))
323{
324 float __res;
325 /* Mark as volatile since the result is dependent on the state of
326 the SSE control register (the rounding mode). Otherwise GCC might
327 remove these assembler instructions since it does not know about
328 the rounding mode change and cannot currently be told. */
329 __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
330 return __res;
331}
332# endif
333
334# endif
335
336/* Smallest integral value not less than X. */
337__MATH_INLINE double
338__NTH (ceil (double __x))
339{
340 double __res;
341 __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x));
342 return __res;
343}
344
345__MATH_INLINE float
346__NTH (ceilf (float __x))
347{
348 float __res;
349 __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x));
350 return __res;
351}
352
353/* Largest integer not greater than X. */
354__MATH_INLINE double
355__NTH (floor (double __x))
356{
357 double __res;
358 __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x));
359 return __res;
360}
361
362__MATH_INLINE float
363__NTH (floorf (float __x))
364{
365 float __res;
366 __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x));
367 return __res;
368}
369# endif
370# endif
371#endif
372
373/* Disable x87 inlines when -fpmath=sse is passed and also when we're building
374 on x86_64. Older gcc (gcc-3.2 for example) does not define __SSE2_MATH__
375 for x86_64. */
376#if !defined __SSE2_MATH__ && !defined __x86_64__
377# if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
378 && defined __OPTIMIZE__)
379
380/* The inline functions do not set errno or raise necessarily the
381 correct exceptions. */
382# undef math_errhandling
383
384/* A macro to define float, double, and long double versions of various
385 math functions for the ix87 FPU. FUNC is the function name (which will
386 be suffixed with f and l for the float and long double version,
387 respectively). OP is the name of the FPU operation.
388 We define two sets of macros. The set with the additional NP
389 doesn't add a prototype declaration. */
390
391# ifdef __USE_ISOC99
392# define __inline_mathop(func, op) \
393 __inline_mathop_ (double, func, op) \
394 __inline_mathop_ (float, __CONCAT(func,f), op) \
395 __inline_mathop_ (long double, __CONCAT(func,l), op)
396# define __inline_mathopNP(func, op) \
397 __inline_mathopNP_ (double, func, op) \
398 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
399 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
400# else
401# define __inline_mathop(func, op) \
402 __inline_mathop_ (double, func, op)
403# define __inline_mathopNP(func, op) \
404 __inline_mathopNP_ (double, func, op)
405# endif
406
407# define __inline_mathop_(float_type, func, op) \
408 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
409# define __inline_mathopNP_(float_type, func, op) \
410 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
411
412
413# ifdef __USE_ISOC99
414# define __inline_mathop_decl(func, op, params...) \
415 __inline_mathop_decl_ (double, func, op, params) \
416 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
417 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
418# define __inline_mathop_declNP(func, op, params...) \
419 __inline_mathop_declNP_ (double, func, op, params) \
420 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
421 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
422# else
423# define __inline_mathop_decl(func, op, params...) \
424 __inline_mathop_decl_ (double, func, op, params)
425# define __inline_mathop_declNP(func, op, params...) \
426 __inline_mathop_declNP_ (double, func, op, params)
427# endif
428
429# define __inline_mathop_decl_(float_type, func, op, params...) \
430 __MATH_INLINE float_type func (float_type) __THROW; \
431 __inline_mathop_declNP_ (float_type, func, op, params)
432
433# define __inline_mathop_declNP_(float_type, func, op, params...) \
434 __MATH_INLINE float_type __NTH (func (float_type __x)) \
435 { \
436 register float_type __result; \
437 __asm __volatile__ (op : "=t" (__result) : params); \
438 return __result; \
439 }
440
441
442# ifdef __USE_ISOC99
443# define __inline_mathcode(func, arg, code) \
444 __inline_mathcode_ (double, func, arg, code) \
445 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
446 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
447# define __inline_mathcodeNP(func, arg, code) \
448 __inline_mathcodeNP_ (double, func, arg, code) \
449 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
450 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
451# define __inline_mathcode2(func, arg1, arg2, code) \
452 __inline_mathcode2_ (double, func, arg1, arg2, code) \
453 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
454 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
455# define __inline_mathcodeNP2(func, arg1, arg2, code) \
456 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
457 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
458 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
459# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
460 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
461 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
462 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
463# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
464 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
465 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
466 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
467# else
468# define __inline_mathcode(func, arg, code) \
469 __inline_mathcode_ (double, func, (arg), code)
470# define __inline_mathcodeNP(func, arg, code) \
471 __inline_mathcodeNP_ (double, func, (arg), code)
472# define __inline_mathcode2(func, arg1, arg2, code) \
473 __inline_mathcode2_ (double, func, arg1, arg2, code)
474# define __inline_mathcodeNP2(func, arg1, arg2, code) \
475 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
476# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
477 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
478# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
479 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
480# endif
481
482# define __inline_mathcode_(float_type, func, arg, code) \
483 __MATH_INLINE float_type func (float_type) __THROW; \
484 __inline_mathcodeNP_(float_type, func, arg, code)
485
486# define __inline_mathcodeNP_(float_type, func, arg, code) \
487 __MATH_INLINE float_type __NTH (func (float_type arg)) \
488 { \
489 code; \
490 }
491
492
493# define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
494 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
495 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
496
497# define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
498 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
499 { \
500 code; \
501 }
502
503# define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
504 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
505 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
506
507# define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
508 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
509 float_type arg3)) \
510 { \
511 code; \
512 }
513# endif
514
515
516# if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
517/* Miscellaneous functions */
518
519/* __FAST_MATH__ is defined by gcc -ffast-math. */
520# ifdef __FAST_MATH__
521# ifdef __USE_GNU
522# define __sincos_code \
523 register long double __cosr; \
524 register long double __sinr; \
525 register unsigned int __swtmp; \
526 __asm __volatile__ \
527 ("fsincos\n\t" \
528 "fnstsw %w2\n\t" \
529 "testl $0x400, %2\n\t" \
530 "jz 1f\n\t" \
531 "fldpi\n\t" \
532 "fadd %%st(0)\n\t" \
533 "fxch %%st(1)\n\t" \
534 "2: fprem1\n\t" \
535 "fnstsw %w2\n\t" \
536 "testl $0x400, %2\n\t" \
537 "jnz 2b\n\t" \
538 "fstp %%st(1)\n\t" \
539 "fsincos\n\t" \
540 "1:" \
541 : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \
542 *__sinx = __sinr; \
543 *__cosx = __cosr
544
545__MATH_INLINE void
546__NTH (__sincos (double __x, double *__sinx, double *__cosx))
547{
548 __sincos_code;
549}
550
551__MATH_INLINE void
552__NTH (__sincosf (float __x, float *__sinx, float *__cosx))
553{
554 __sincos_code;
555}
556
557__MATH_INLINE void
558__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
559{
560 __sincos_code;
561}
562# endif
563
564
565/* Optimized inline implementation, sometimes with reduced precision
566 and/or argument range. */
567
568# if __GNUC_PREREQ (3, 5)
569# define __expm1_code \
570 register long double __temp; \
571 __temp = __builtin_expm1l (__x); \
572 return __temp ? __temp : __x
573# else
574# define __expm1_code \
575 register long double __value; \
576 register long double __exponent; \
577 register long double __temp; \
578 __asm __volatile__ \
579 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
580 "fmul %%st(1) # x * log2(e)\n\t" \
581 "fst %%st(1)\n\t" \
582 "frndint # int(x * log2(e))\n\t" \
583 "fxch\n\t" \
584 "fsub %%st(1) # fract(x * log2(e))\n\t" \
585 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
586 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
587 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
588 __asm __volatile__ \
589 ("fscale # 2^int(x * log2(e))\n\t" \
590 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
591 __temp -= 1.0; \
592 __temp += __value; \
593 return __temp ? __temp : __x
594# endif
595__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
596
597# if __GNUC_PREREQ (3, 4)
598__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
599# else
600# define __exp_code \
601 register long double __value; \
602 register long double __exponent; \
603 __asm __volatile__ \
604 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
605 "fmul %%st(1) # x * log2(e)\n\t" \
606 "fst %%st(1)\n\t" \
607 "frndint # int(x * log2(e))\n\t" \
608 "fxch\n\t" \
609 "fsub %%st(1) # fract(x * log2(e))\n\t" \
610 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
611 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
612 __value += 1.0; \
613 __asm __volatile__ \
614 ("fscale" \
615 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
616 return __value
617__inline_mathcodeNP (exp, __x, __exp_code)
618__inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
619# endif
620
621
622# if !__GNUC_PREREQ (3, 5)
623__inline_mathcodeNP (tan, __x, \
624 register long double __value; \
625 register long double __value2 __attribute__ ((__unused__)); \
626 __asm __volatile__ \
627 ("fptan" \
628 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
629 return __value)
630# endif
631# endif /* __FAST_MATH__ */
632
633
634# if __GNUC_PREREQ (3, 4)
635__inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
636 return __builtin_atan2l (__y, __x))
637# else
638# define __atan2_code \
639 register long double __value; \
640 __asm __volatile__ \
641 ("fpatan" \
642 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
643 return __value
644# ifdef __FAST_MATH__
645__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
646# endif
647__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
648# endif
649
650
651# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
652__inline_mathcodeNP2 (fmod, __x, __y, \
653 register long double __value; \
654 __asm __volatile__ \
655 ("1: fprem\n\t" \
656 "fnstsw %%ax\n\t" \
657 "sahf\n\t" \
658 "jp 1b" \
659 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
660 return __value)
661# endif
662
663
664# ifdef __FAST_MATH__
665# if !__GNUC_PREREQ (3,3)
666__inline_mathopNP (sqrt, "fsqrt")
667__inline_mathopNP_ (long double, __sqrtl, "fsqrt")
668# define __libc_sqrtl(n) __sqrtl (n)
669# else
670# define __libc_sqrtl(n) __builtin_sqrtl (n)
671# endif
672# endif
673
674# if __GNUC_PREREQ (2, 8)
675__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
676# ifdef __USE_ISOC99
677__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
678__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
679# endif
680__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
681# else
682__inline_mathop (fabs, "fabs")
683__inline_mathop_ (long double, __fabsl, "fabs")
684# endif
685
686# ifdef __FAST_MATH__
687# if !__GNUC_PREREQ (3, 4)
688/* The argument range of this inline version is reduced. */
689__inline_mathopNP (sin, "fsin")
690/* The argument range of this inline version is reduced. */
691__inline_mathopNP (cos, "fcos")
692
693__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
694# endif
695
696# if !__GNUC_PREREQ (3, 5)
697__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
698
699__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
700__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
701# endif
702
703# if !__GNUC_PREREQ (3, 4)
704__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
705# endif
706# endif /* __FAST_MATH__ */
707
708__inline_mathcode_ (long double, __sgn1l, __x, \
709 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
710 { __xld: __x }; \
711 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
712 __n.__xi[1] = 0x80000000; \
713 __n.__xi[0] = 0; \
714 return __n.__xld)
715
716
717# ifdef __FAST_MATH__
718/* The argument range of the inline version of sinhl is slightly reduced. */
719__inline_mathcodeNP (sinh, __x, \
720 register long double __exm1 = __expm1l (__fabsl (__x)); \
721 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
722
723__inline_mathcodeNP (cosh, __x, \
724 register long double __ex = __expl (__x); \
725 return 0.5 * (__ex + 1.0 / __ex))
726
727__inline_mathcodeNP (tanh, __x, \
728 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
729 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
730# endif
731
732__inline_mathcodeNP (floor, __x, \
733 register long double __value; \
734 register int __ignore; \
735 unsigned short int __cw; \
736 unsigned short int __cwtmp; \
737 __asm __volatile ("fnstcw %3\n\t" \
738 "movzwl %3, %1\n\t" \
739 "andl $0xf3ff, %1\n\t" \
740 "orl $0x0400, %1\n\t" /* rounding down */ \
741 "movw %w1, %2\n\t" \
742 "fldcw %2\n\t" \
743 "frndint\n\t" \
744 "fldcw %3" \
745 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
746 "=m" (__cw) \
747 : "0" (__x)); \
748 return __value)
749
750__inline_mathcodeNP (ceil, __x, \
751 register long double __value; \
752 register int __ignore; \
753 unsigned short int __cw; \
754 unsigned short int __cwtmp; \
755 __asm __volatile ("fnstcw %3\n\t" \
756 "movzwl %3, %1\n\t" \
757 "andl $0xf3ff, %1\n\t" \
758 "orl $0x0800, %1\n\t" /* rounding up */ \
759 "movw %w1, %2\n\t" \
760 "fldcw %2\n\t" \
761 "frndint\n\t" \
762 "fldcw %3" \
763 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
764 "=m" (__cw) \
765 : "0" (__x)); \
766 return __value)
767
768# ifdef __FAST_MATH__
769# define __ldexp_code \
770 register long double __value; \
771 __asm __volatile__ \
772 ("fscale" \
773 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
774 return __value
775
776__MATH_INLINE double
777__NTH (ldexp (double __x, int __y))
778{
779 __ldexp_code;
780}
781# endif
782
783
784/* Optimized versions for some non-standardized functions. */
785# ifdef __USE_ISOC99
786
787# ifdef __FAST_MATH__
788__inline_mathcodeNP (expm1, __x, __expm1_code)
789
790/* We cannot rely on M_SQRT being defined. So we do it for ourself
791 here. */
792# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
793
794# if !__GNUC_PREREQ (3, 5)
795__inline_mathcodeNP (log1p, __x, \
796 register long double __value; \
797 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
798 __value = logl (1.0 + __x); \
799 else \
800 __asm __volatile__ \
801 ("fldln2\n\t" \
802 "fxch\n\t" \
803 "fyl2xp1" \
804 : "=t" (__value) : "0" (__x) : "st(1)"); \
805 return __value)
806# endif
807
808
809/* The argument range of the inline version of asinhl is slightly reduced. */
810__inline_mathcodeNP (asinh, __x, \
811 register long double __y = __fabsl (__x); \
812 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
813 * __sgn1l (__x)))
814
815__inline_mathcodeNP (acosh, __x, \
816 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
817
818__inline_mathcodeNP (atanh, __x, \
819 register long double __y = __fabsl (__x); \
820 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
821
822/* The argument range of the inline version of hypotl is slightly reduced. */
823__inline_mathcodeNP2 (hypot, __x, __y,
824 return __libc_sqrtl (__x * __x + __y * __y))
825
826# if !__GNUC_PREREQ (3, 5)
827__inline_mathcodeNP(logb, __x, \
828 register long double __value; \
829 register long double __junk; \
830 __asm __volatile__ \
831 ("fxtract\n\t" \
832 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
833 return __value)
834# endif
835
836# endif
837# endif
838
839# ifdef __USE_ISOC99
840# ifdef __FAST_MATH__
841
842# if !__GNUC_PREREQ (3, 5)
843__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
844# endif
845
846__MATH_INLINE float
847__NTH (ldexpf (float __x, int __y))
848{
849 __ldexp_code;
850}
851
852__MATH_INLINE long double
853__NTH (ldexpl (long double __x, int __y))
854{
855 __ldexp_code;
856}
857
858__inline_mathopNP (rint, "frndint")
859# endif /* __FAST_MATH__ */
860
861# define __lrint_code \
862 long int __lrintres; \
863 __asm__ __volatile__ \
864 ("fistpl %0" \
865 : "=m" (__lrintres) : "t" (__x) : "st"); \
866 return __lrintres
867__MATH_INLINE long int
868__NTH (lrintf (float __x))
869{
870 __lrint_code;
871}
872__MATH_INLINE long int
873__NTH (lrint (double __x))
874{
875 __lrint_code;
876}
877__MATH_INLINE long int
878__NTH (lrintl (long double __x))
879{
880 __lrint_code;
881}
882# undef __lrint_code
883
884# define __llrint_code \
885 long long int __llrintres; \
886 __asm__ __volatile__ \
887 ("fistpll %0" \
888 : "=m" (__llrintres) : "t" (__x) : "st"); \
889 return __llrintres
890__extension__
891__MATH_INLINE long long int
892__NTH (llrintf (float __x))
893{
894 __llrint_code;
895}
896__extension__
897__MATH_INLINE long long int
898__NTH (llrint (double __x))
899{
900 __llrint_code;
901}
902__extension__
903__MATH_INLINE long long int
904__NTH (llrintl (long double __x))
905{
906 __llrint_code;
907}
908# undef __llrint_code
909
910# endif
911
912
913# ifdef __USE_MISC
914
915# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
916__inline_mathcodeNP2 (drem, __x, __y, \
917 register double __value; \
918 register int __clobbered; \
919 __asm __volatile__ \
920 ("1: fprem1\n\t" \
921 "fstsw %%ax\n\t" \
922 "sahf\n\t" \
923 "jp 1b" \
924 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
925 return __value)
926# endif
927
928
929/* This function is used in the `isfinite' macro. */
930__MATH_INLINE int
931__NTH (__finite (double __x))
932{
933 return (__extension__
934 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
935 | 0x800fffffu) + 1) >> 31));
936}
937
938# endif /* __USE_MISC */
939
940/* Undefine some of the large macros which are not used anymore. */
941# undef __atan2_code
942# ifdef __FAST_MATH__
943# undef __expm1_code
944# undef __exp_code
945# undef __sincos_code
946# endif /* __FAST_MATH__ */
947
948# endif /* __NO_MATH_INLINES */
949
950
951/* This code is used internally in the GNU libc. */
952# ifdef __LIBC_INTERNAL_MATH_INLINES
953__inline_mathop (__ieee754_sqrt, "fsqrt")
954__inline_mathcode2_ (long double, __ieee754_atan2l, __y, __x,
955 register long double __value;
956 __asm __volatile__ ("fpatan\n\t"
957 : "=t" (__value)
958 : "0" (__x), "u" (__y) : "st(1)");
959 return __value;)
960# endif
961
962#endif /* !__SSE2_MATH__ && !__x86_64__ */
963