Update copyright notices with scripts/update-copyrights.
[glibc.git] / sysdeps / x86 / fpu / bits / mathinline.h
blob838c13cd8ddbce60eae4b8d7a8f1a76ab203f7e8
1 /* Inline math functions for i387 and SSE.
2 Copyright (C) 1995-2013 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #ifndef _MATH_H
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
21 #endif
23 #ifndef __extern_always_inline
24 # define __MATH_INLINE __inline
25 #else
26 # define __MATH_INLINE __extern_always_inline
27 #endif
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; })
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; })
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; })
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; })
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; })
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; })
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; })
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; })
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; })
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 */
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 __BEGIN_NAMESPACE_C99
125 /* Test for negative number. Used in the signbit() macro. */
126 __MATH_INLINE int
127 __NTH (__signbitf (float __x))
129 # ifdef __SSE2_MATH__
130 int __m;
131 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
132 return (__m & 0x8) != 0;
133 # else
134 __extension__ union { float __f; int __i; } __u = { __f: __x };
135 return __u.__i < 0;
136 # endif
138 __MATH_INLINE int
139 __NTH (__signbit (double __x))
141 # ifdef __SSE2_MATH__
142 int __m;
143 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x));
144 return (__m & 0x80) != 0;
145 # else
146 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
147 return __u.__i[1] < 0;
148 # endif
150 __MATH_INLINE int
151 __NTH (__signbitl (long double __x))
153 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
154 return (__u.__i[2] & 0x8000) != 0;
157 __END_NAMESPACE_C99
158 # endif
159 #endif
162 /* The gcc, version 2.7 or below, has problems with all this inlining
163 code. So disable it for this version of the compiler. */
164 #if __GNUC_PREREQ (2, 8)
165 # if !__GNUC_PREREQ (3, 4) && !defined __NO_MATH_INLINES \
166 && defined __OPTIMIZE__
167 /* GCC 3.4 introduced builtins for all functions below, so
168 there's no need to define any of these inline functions. */
170 # ifdef __USE_ISOC99
171 __BEGIN_NAMESPACE_C99
173 /* Round to nearest integer. */
174 # ifdef __SSE_MATH__
175 __MATH_INLINE long int
176 __NTH (lrintf (float __x))
178 long int __res;
179 /* Mark as volatile since the result is dependent on the state of
180 the SSE control register (the rounding mode). Otherwise GCC might
181 remove these assembler instructions since it does not know about
182 the rounding mode change and cannot currently be told. */
183 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
184 return __res;
186 # endif
187 # ifdef __SSE2_MATH__
188 __MATH_INLINE long int
189 __NTH (lrint (double __x))
191 long int __res;
192 /* Mark as volatile since the result is dependent on the state of
193 the SSE control register (the rounding mode). Otherwise GCC might
194 remove these assembler instructions since it does not know about
195 the rounding mode change and cannot currently be told. */
196 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
197 return __res;
199 # endif
200 # ifdef __x86_64__
201 __MATH_INLINE long long int
202 __NTH (llrintf (float __x))
204 long long int __res;
205 /* Mark as volatile since the result is dependent on the state of
206 the SSE control register (the rounding mode). Otherwise GCC might
207 remove these assembler instructions since it does not know about
208 the rounding mode change and cannot currently be told. */
209 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
210 return __res;
212 __MATH_INLINE long long int
213 __NTH (llrint (double __x))
215 long long int __res;
216 /* Mark as volatile since the result is dependent on the state of
217 the SSE control register (the rounding mode). Otherwise GCC might
218 remove these assembler instructions since it does not know about
219 the rounding mode change and cannot currently be told. */
220 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
221 return __res;
223 # endif
225 # if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
226 && defined __SSE2_MATH__
227 /* Determine maximum of two values. */
228 __MATH_INLINE float
229 __NTH (fmaxf (float __x, float __y))
231 # ifdef __AVX__
232 float __res;
233 __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
234 return __res;
235 # else
236 __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
237 return __x;
238 # endif
240 __MATH_INLINE double
241 __NTH (fmax (double __x, double __y))
243 # ifdef __AVX__
244 float __res;
245 __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
246 return __res;
247 # else
248 __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
249 return __x;
250 # endif
253 /* Determine minimum of two values. */
254 __MATH_INLINE float
255 __NTH (fminf (float __x, float __y))
257 # ifdef __AVX__
258 float __res;
259 __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
260 return __res;
261 # else
262 __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
263 return __x;
264 # endif
266 __MATH_INLINE double
267 __NTH (fmin (double __x, double __y))
269 # ifdef __AVX__
270 float __res;
271 __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
272 return __res;
273 # else
274 __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
275 return __x;
276 # endif
278 # endif
280 __END_NAMESPACE_C99
281 # endif
283 # if defined __SSE4_1__ && defined __SSE2_MATH__
284 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
285 __BEGIN_NAMESPACE_C99
287 /* Round to nearest integer. */
288 __MATH_INLINE double
289 __NTH (rint (double __x))
291 double __res;
292 /* Mark as volatile since the result is dependent on the state of
293 the SSE control register (the rounding mode). Otherwise GCC might
294 remove these assembler instructions since it does not know about
295 the rounding mode change and cannot currently be told. */
296 __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
297 return __res;
299 __MATH_INLINE float
300 __NTH (rintf (float __x))
302 float __res;
303 /* Mark as volatile since the result is dependent on the state of
304 the SSE control register (the rounding mode). Otherwise GCC might
305 remove these assembler instructions since it does not know about
306 the rounding mode change and cannot currently be told. */
307 __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
308 return __res;
311 # ifdef __USE_ISOC99
312 /* Round to nearest integer without raising inexact exception. */
313 __MATH_INLINE double
314 __NTH (nearbyint (double __x))
316 double __res;
317 /* Mark as volatile since the result is dependent on the state of
318 the SSE control register (the rounding mode). Otherwise GCC might
319 remove these assembler instructions since it does not know about
320 the rounding mode change and cannot currently be told. */
321 __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
322 return __res;
324 __MATH_INLINE float
325 __NTH (nearbyintf (float __x))
327 float __res;
328 /* Mark as volatile since the result is dependent on the state of
329 the SSE control register (the rounding mode). Otherwise GCC might
330 remove these assembler instructions since it does not know about
331 the rounding mode change and cannot currently be told. */
332 __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
333 return __res;
335 # endif
337 __END_NAMESPACE_C99
338 # endif
340 __BEGIN_NAMESPACE_STD
341 /* Smallest integral value not less than X. */
342 __MATH_INLINE double
343 __NTH (ceil (double __x))
345 double __res;
346 __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x));
347 return __res;
349 __END_NAMESPACE_STD
351 __BEGIN_NAMESPACE_C99
352 __MATH_INLINE float
353 __NTH (ceilf (float __x))
355 float __res;
356 __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x));
357 return __res;
359 __END_NAMESPACE_C99
361 __BEGIN_NAMESPACE_STD
362 /* Largest integer not greater than X. */
363 __MATH_INLINE double
364 __NTH (floor (double __x))
366 double __res;
367 __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x));
368 return __res;
370 __END_NAMESPACE_STD
372 __BEGIN_NAMESPACE_C99
373 __MATH_INLINE float
374 __NTH (floorf (float __x))
376 float __res;
377 __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x));
378 return __res;
380 __END_NAMESPACE_C99
381 # endif
382 # endif
383 #endif
385 #ifndef __x86_64__
386 # if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
387 && defined __OPTIMIZE__)
389 /* The inline functions do not set errno or raise necessarily the
390 correct exceptions. */
391 # undef math_errhandling
393 /* A macro to define float, double, and long double versions of various
394 math functions for the ix87 FPU. FUNC is the function name (which will
395 be suffixed with f and l for the float and long double version,
396 respectively). OP is the name of the FPU operation.
397 We define two sets of macros. The set with the additional NP
398 doesn't add a prototype declaration. */
400 # if defined __USE_MISC || defined __USE_ISOC99
401 # define __inline_mathop(func, op) \
402 __inline_mathop_ (double, func, op) \
403 __inline_mathop_ (float, __CONCAT(func,f), op) \
404 __inline_mathop_ (long double, __CONCAT(func,l), op)
405 # define __inline_mathopNP(func, op) \
406 __inline_mathopNP_ (double, func, op) \
407 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
408 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
409 # else
410 # define __inline_mathop(func, op) \
411 __inline_mathop_ (double, func, op)
412 # define __inline_mathopNP(func, op) \
413 __inline_mathopNP_ (double, func, op)
414 # endif
416 # define __inline_mathop_(float_type, func, op) \
417 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
418 # define __inline_mathopNP_(float_type, func, op) \
419 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
422 # if defined __USE_MISC || defined __USE_ISOC99
423 # define __inline_mathop_decl(func, op, params...) \
424 __inline_mathop_decl_ (double, func, op, params) \
425 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
426 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
427 # define __inline_mathop_declNP(func, op, params...) \
428 __inline_mathop_declNP_ (double, func, op, params) \
429 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
430 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
431 # else
432 # define __inline_mathop_decl(func, op, params...) \
433 __inline_mathop_decl_ (double, func, op, params)
434 # define __inline_mathop_declNP(func, op, params...) \
435 __inline_mathop_declNP_ (double, func, op, params)
436 # endif
438 # define __inline_mathop_decl_(float_type, func, op, params...) \
439 __MATH_INLINE float_type func (float_type) __THROW; \
440 __inline_mathop_declNP_ (float_type, func, op, params)
442 # define __inline_mathop_declNP_(float_type, func, op, params...) \
443 __MATH_INLINE float_type __NTH (func (float_type __x)) \
445 register float_type __result; \
446 __asm __volatile__ (op : "=t" (__result) : params); \
447 return __result; \
451 # if defined __USE_MISC || defined __USE_ISOC99
452 # define __inline_mathcode(func, arg, code) \
453 __inline_mathcode_ (double, func, arg, code) \
454 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
455 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
456 # define __inline_mathcodeNP(func, arg, code) \
457 __inline_mathcodeNP_ (double, func, arg, code) \
458 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
459 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
460 # define __inline_mathcode2(func, arg1, arg2, code) \
461 __inline_mathcode2_ (double, func, arg1, arg2, code) \
462 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
463 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
464 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
465 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
466 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
467 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
468 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
469 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
470 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
471 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
472 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
473 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
474 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
475 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
476 # else
477 # define __inline_mathcode(func, arg, code) \
478 __inline_mathcode_ (double, func, (arg), code)
479 # define __inline_mathcodeNP(func, arg, code) \
480 __inline_mathcodeNP_ (double, func, (arg), code)
481 # define __inline_mathcode2(func, arg1, arg2, code) \
482 __inline_mathcode2_ (double, func, arg1, arg2, code)
483 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
484 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
485 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
486 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
487 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
488 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
489 # endif
491 # define __inline_mathcode_(float_type, func, arg, code) \
492 __MATH_INLINE float_type func (float_type) __THROW; \
493 __inline_mathcodeNP_(float_type, func, arg, code)
495 # define __inline_mathcodeNP_(float_type, func, arg, code) \
496 __MATH_INLINE float_type __NTH (func (float_type arg)) \
498 code; \
502 # define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
503 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
504 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
506 # define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
507 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
509 code; \
512 # define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
513 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
514 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
516 # define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
517 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
518 float_type arg3)) \
520 code; \
522 # endif
525 # if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
526 /* Miscellaneous functions */
528 /* __FAST_MATH__ is defined by gcc -ffast-math. */
529 # ifdef __FAST_MATH__
530 # ifdef __USE_GNU
531 # define __sincos_code \
532 register long double __cosr; \
533 register long double __sinr; \
534 register unsigned int __swtmp; \
535 __asm __volatile__ \
536 ("fsincos\n\t" \
537 "fnstsw %w2\n\t" \
538 "testl $0x400, %2\n\t" \
539 "jz 1f\n\t" \
540 "fldpi\n\t" \
541 "fadd %%st(0)\n\t" \
542 "fxch %%st(1)\n\t" \
543 "2: fprem1\n\t" \
544 "fnstsw %w2\n\t" \
545 "testl $0x400, %2\n\t" \
546 "jnz 2b\n\t" \
547 "fstp %%st(1)\n\t" \
548 "fsincos\n\t" \
549 "1:" \
550 : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \
551 *__sinx = __sinr; \
552 *__cosx = __cosr
554 __MATH_INLINE void
555 __NTH (__sincos (double __x, double *__sinx, double *__cosx))
557 __sincos_code;
560 __MATH_INLINE void
561 __NTH (__sincosf (float __x, float *__sinx, float *__cosx))
563 __sincos_code;
566 __MATH_INLINE void
567 __NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
569 __sincos_code;
571 # endif
574 /* Optimized inline implementation, sometimes with reduced precision
575 and/or argument range. */
577 # if __GNUC_PREREQ (3, 5)
578 # define __expm1_code \
579 register long double __temp; \
580 __temp = __builtin_expm1l (__x); \
581 return __temp ? __temp : __x
582 # else
583 # define __expm1_code \
584 register long double __value; \
585 register long double __exponent; \
586 register long double __temp; \
587 __asm __volatile__ \
588 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
589 "fmul %%st(1) # x * log2(e)\n\t" \
590 "fst %%st(1)\n\t" \
591 "frndint # int(x * log2(e))\n\t" \
592 "fxch\n\t" \
593 "fsub %%st(1) # fract(x * log2(e))\n\t" \
594 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
595 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
596 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
597 __asm __volatile__ \
598 ("fscale # 2^int(x * log2(e))\n\t" \
599 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
600 __temp -= 1.0; \
601 __temp += __value; \
602 return __temp ? __temp : __x
603 # endif
604 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
606 # if __GNUC_PREREQ (3, 4)
607 __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
608 # else
609 # define __exp_code \
610 register long double __value; \
611 register long double __exponent; \
612 __asm __volatile__ \
613 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
614 "fmul %%st(1) # x * log2(e)\n\t" \
615 "fst %%st(1)\n\t" \
616 "frndint # int(x * log2(e))\n\t" \
617 "fxch\n\t" \
618 "fsub %%st(1) # fract(x * log2(e))\n\t" \
619 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
620 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
621 __value += 1.0; \
622 __asm __volatile__ \
623 ("fscale" \
624 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
625 return __value
626 __inline_mathcodeNP (exp, __x, __exp_code)
627 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
628 # endif
631 # if !__GNUC_PREREQ (3, 5)
632 __inline_mathcodeNP (tan, __x, \
633 register long double __value; \
634 register long double __value2 __attribute__ ((__unused__)); \
635 __asm __volatile__ \
636 ("fptan" \
637 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
638 return __value)
639 # endif
640 # endif /* __FAST_MATH__ */
643 # if __GNUC_PREREQ (3, 4)
644 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
645 return __builtin_atan2l (__y, __x))
646 # else
647 # define __atan2_code \
648 register long double __value; \
649 __asm __volatile__ \
650 ("fpatan" \
651 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
652 return __value
653 # ifdef __FAST_MATH__
654 __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
655 # endif
656 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
657 # endif
660 # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
661 __inline_mathcodeNP2 (fmod, __x, __y, \
662 register long double __value; \
663 __asm __volatile__ \
664 ("1: fprem\n\t" \
665 "fnstsw %%ax\n\t" \
666 "sahf\n\t" \
667 "jp 1b" \
668 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
669 return __value)
670 # endif
673 # ifdef __FAST_MATH__
674 # if !__GNUC_PREREQ (3,3)
675 __inline_mathopNP (sqrt, "fsqrt")
676 __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
677 # define __libc_sqrtl(n) __sqrtl (n)
678 # else
679 # define __libc_sqrtl(n) __builtin_sqrtl (n)
680 # endif
681 # endif
683 # if __GNUC_PREREQ (2, 8)
684 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
685 # if defined __USE_MISC || defined __USE_ISOC99
686 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
687 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
688 # endif
689 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
690 # else
691 __inline_mathop (fabs, "fabs")
692 __inline_mathop_ (long double, __fabsl, "fabs")
693 # endif
695 # ifdef __FAST_MATH__
696 # if !__GNUC_PREREQ (3, 4)
697 /* The argument range of this inline version is reduced. */
698 __inline_mathopNP (sin, "fsin")
699 /* The argument range of this inline version is reduced. */
700 __inline_mathopNP (cos, "fcos")
702 __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
703 # endif
705 # if !__GNUC_PREREQ (3, 5)
706 __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
708 __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
709 __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
710 # endif
712 # if !__GNUC_PREREQ (3, 4)
713 __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
714 # endif
715 # endif /* __FAST_MATH__ */
717 __inline_mathcode_ (long double, __sgn1l, __x, \
718 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
719 { __xld: __x }; \
720 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
721 __n.__xi[1] = 0x80000000; \
722 __n.__xi[0] = 0; \
723 return __n.__xld)
726 # ifdef __FAST_MATH__
727 /* The argument range of the inline version of sinhl is slightly reduced. */
728 __inline_mathcodeNP (sinh, __x, \
729 register long double __exm1 = __expm1l (__fabsl (__x)); \
730 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
732 __inline_mathcodeNP (cosh, __x, \
733 register long double __ex = __expl (__x); \
734 return 0.5 * (__ex + 1.0 / __ex))
736 __inline_mathcodeNP (tanh, __x, \
737 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
738 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
739 # endif
741 __inline_mathcodeNP (floor, __x, \
742 register long double __value; \
743 register int __ignore; \
744 unsigned short int __cw; \
745 unsigned short int __cwtmp; \
746 __asm __volatile ("fnstcw %3\n\t" \
747 "movzwl %3, %1\n\t" \
748 "andl $0xf3ff, %1\n\t" \
749 "orl $0x0400, %1\n\t" /* rounding down */ \
750 "movw %w1, %2\n\t" \
751 "fldcw %2\n\t" \
752 "frndint\n\t" \
753 "fldcw %3" \
754 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
755 "=m" (__cw) \
756 : "0" (__x)); \
757 return __value)
759 __inline_mathcodeNP (ceil, __x, \
760 register long double __value; \
761 register int __ignore; \
762 unsigned short int __cw; \
763 unsigned short int __cwtmp; \
764 __asm __volatile ("fnstcw %3\n\t" \
765 "movzwl %3, %1\n\t" \
766 "andl $0xf3ff, %1\n\t" \
767 "orl $0x0800, %1\n\t" /* rounding up */ \
768 "movw %w1, %2\n\t" \
769 "fldcw %2\n\t" \
770 "frndint\n\t" \
771 "fldcw %3" \
772 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
773 "=m" (__cw) \
774 : "0" (__x)); \
775 return __value)
777 # ifdef __FAST_MATH__
778 # define __ldexp_code \
779 register long double __value; \
780 __asm __volatile__ \
781 ("fscale" \
782 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
783 return __value
785 __MATH_INLINE double
786 __NTH (ldexp (double __x, int __y))
788 __ldexp_code;
790 # endif
793 /* Optimized versions for some non-standardized functions. */
794 # if defined __USE_ISOC99 || defined __USE_MISC
796 # ifdef __FAST_MATH__
797 __inline_mathcodeNP (expm1, __x, __expm1_code)
799 /* We cannot rely on M_SQRT being defined. So we do it for ourself
800 here. */
801 # define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
803 # if !__GNUC_PREREQ (3, 5)
804 __inline_mathcodeNP (log1p, __x, \
805 register long double __value; \
806 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
807 __value = logl (1.0 + __x); \
808 else \
809 __asm __volatile__ \
810 ("fldln2\n\t" \
811 "fxch\n\t" \
812 "fyl2xp1" \
813 : "=t" (__value) : "0" (__x) : "st(1)"); \
814 return __value)
815 # endif
818 /* The argument range of the inline version of asinhl is slightly reduced. */
819 __inline_mathcodeNP (asinh, __x, \
820 register long double __y = __fabsl (__x); \
821 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
822 * __sgn1l (__x)))
824 __inline_mathcodeNP (acosh, __x, \
825 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
827 __inline_mathcodeNP (atanh, __x, \
828 register long double __y = __fabsl (__x); \
829 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
831 /* The argument range of the inline version of hypotl is slightly reduced. */
832 __inline_mathcodeNP2 (hypot, __x, __y,
833 return __libc_sqrtl (__x * __x + __y * __y))
835 # if !__GNUC_PREREQ (3, 5)
836 __inline_mathcodeNP(logb, __x, \
837 register long double __value; \
838 register long double __junk; \
839 __asm __volatile__ \
840 ("fxtract\n\t" \
841 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
842 return __value)
843 # endif
845 # endif
846 # endif
848 # ifdef __USE_ISOC99
849 # ifdef __FAST_MATH__
851 # if !__GNUC_PREREQ (3, 5)
852 __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
853 # endif
855 __MATH_INLINE float
856 __NTH (ldexpf (float __x, int __y))
858 __ldexp_code;
861 __MATH_INLINE long double
862 __NTH (ldexpl (long double __x, int __y))
864 __ldexp_code;
867 __inline_mathopNP (rint, "frndint")
868 # endif /* __FAST_MATH__ */
870 # define __lrint_code \
871 long int __lrintres; \
872 __asm__ __volatile__ \
873 ("fistpl %0" \
874 : "=m" (__lrintres) : "t" (__x) : "st"); \
875 return __lrintres
876 __MATH_INLINE long int
877 __NTH (lrintf (float __x))
879 __lrint_code;
881 __MATH_INLINE long int
882 __NTH (lrint (double __x))
884 __lrint_code;
886 __MATH_INLINE long int
887 __NTH (lrintl (long double __x))
889 __lrint_code;
891 # undef __lrint_code
893 # define __llrint_code \
894 long long int __llrintres; \
895 __asm__ __volatile__ \
896 ("fistpll %0" \
897 : "=m" (__llrintres) : "t" (__x) : "st"); \
898 return __llrintres
899 __MATH_INLINE long long int
900 __NTH (llrintf (float __x))
902 __llrint_code;
904 __MATH_INLINE long long int
905 __NTH (llrint (double __x))
907 __llrint_code;
909 __MATH_INLINE long long int
910 __NTH (llrintl (long double __x))
912 __llrint_code;
914 # undef __llrint_code
916 # endif
919 # ifdef __USE_MISC
921 # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
922 __inline_mathcodeNP2 (drem, __x, __y, \
923 register double __value; \
924 register int __clobbered; \
925 __asm __volatile__ \
926 ("1: fprem1\n\t" \
927 "fstsw %%ax\n\t" \
928 "sahf\n\t" \
929 "jp 1b" \
930 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
931 return __value)
932 # endif
935 /* This function is used in the `isfinite' macro. */
936 __MATH_INLINE int
937 __NTH (__finite (double __x))
939 return (__extension__
940 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
941 | 0x800fffffu) + 1) >> 31));
944 # endif /* __USE_MISC */
946 /* Undefine some of the large macros which are not used anymore. */
947 # undef __atan2_code
948 # ifdef __FAST_MATH__
949 # undef __expm1_code
950 # undef __exp_code
951 # undef __sincos_code
952 # endif /* __FAST_MATH__ */
954 # endif /* __NO_MATH_INLINES */
957 /* This code is used internally in the GNU libc. */
958 # ifdef __LIBC_INTERNAL_MATH_INLINES
959 __inline_mathop (__ieee754_sqrt, "fsqrt")
960 __inline_mathcode2 (__ieee754_atan2, __y, __x,
961 register long double __value;
962 __asm __volatile__ ("fpatan\n\t"
963 : "=t" (__value)
964 : "0" (__x), "u" (__y) : "st(1)");
965 return __value;)
966 # endif
968 #endif /* !__x86_64__ */