1/* Inline math functions for i387 and SSE.
2 Copyright (C) 1995-2014 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__BEGIN_NAMESPACE_C99
124
125/* Test for negative number. Used in the signbit() macro. */
126__MATH_INLINE int
127__NTH (__signbitf (float __x))
128{
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
137}
138__MATH_INLINE int
139__NTH (__signbit (double __x))
140{
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
149}
150__MATH_INLINE int
151__NTH (__signbitl (long double __x))
152{
153 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
154 return (__u.__i[2] & 0x8000) != 0;
155}
156
157__END_NAMESPACE_C99
158# endif
159#endif
160
161
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. */
169
170# ifdef __USE_ISOC99
171__BEGIN_NAMESPACE_C99
172
173/* Round to nearest integer. */
174# ifdef __SSE_MATH__
175__MATH_INLINE long int
176__NTH (lrintf (float __x))
177{
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;
185}
186# endif
187# ifdef __SSE2_MATH__
188__MATH_INLINE long int
189__NTH (lrint (double __x))
190{
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;
198}
199# endif
200# ifdef __x86_64__
201__extension__
202__MATH_INLINE long long int
203__NTH (llrintf (float __x))
204{
205 long long int __res;
206 /* Mark as volatile since the result is dependent on the state of
207 the SSE control register (the rounding mode). Otherwise GCC might
208 remove these assembler instructions since it does not know about
209 the rounding mode change and cannot currently be told. */
210 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
211 return __res;
212}
213__extension__
214__MATH_INLINE long long int
215__NTH (llrint (double __x))
216{
217 long long int __res;
218 /* Mark as volatile since the result is dependent on the state of
219 the SSE control register (the rounding mode). Otherwise GCC might
220 remove these assembler instructions since it does not know about
221 the rounding mode change and cannot currently be told. */
222 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
223 return __res;
224}
225# endif
226
227# if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
228 && defined __SSE2_MATH__
229/* Determine maximum of two values. */
230__MATH_INLINE float
231__NTH (fmaxf (float __x, float __y))
232{
233# ifdef __AVX__
234 float __res;
235 __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
236 return __res;
237# else
238 __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
239 return __x;
240# endif
241}
242__MATH_INLINE double
243__NTH (fmax (double __x, double __y))
244{
245# ifdef __AVX__
246 float __res;
247 __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
248 return __res;
249# else
250 __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
251 return __x;
252# endif
253}
254
255/* Determine minimum of two values. */
256__MATH_INLINE float
257__NTH (fminf (float __x, float __y))
258{
259# ifdef __AVX__
260 float __res;
261 __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
262 return __res;
263# else
264 __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
265 return __x;
266# endif
267}
268__MATH_INLINE double
269__NTH (fmin (double __x, double __y))
270{
271# ifdef __AVX__
272 float __res;
273 __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
274 return __res;
275# else
276 __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
277 return __x;
278# endif
279}
280# endif
281
282__END_NAMESPACE_C99
283# endif
284
285# if defined __SSE4_1__ && defined __SSE2_MATH__
286# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
287__BEGIN_NAMESPACE_C99
288
289/* Round to nearest integer. */
290__MATH_INLINE double
291__NTH (rint (double __x))
292{
293 double __res;
294 /* Mark as volatile since the result is dependent on the state of
295 the SSE control register (the rounding mode). Otherwise GCC might
296 remove these assembler instructions since it does not know about
297 the rounding mode change and cannot currently be told. */
298 __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
299 return __res;
300}
301__MATH_INLINE float
302__NTH (rintf (float __x))
303{
304 float __res;
305 /* Mark as volatile since the result is dependent on the state of
306 the SSE control register (the rounding mode). Otherwise GCC might
307 remove these assembler instructions since it does not know about
308 the rounding mode change and cannot currently be told. */
309 __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
310 return __res;
311}
312
313# ifdef __USE_ISOC99
314/* Round to nearest integer without raising inexact exception. */
315__MATH_INLINE double
316__NTH (nearbyint (double __x))
317{
318 double __res;
319 /* Mark as volatile since the result is dependent on the state of
320 the SSE control register (the rounding mode). Otherwise GCC might
321 remove these assembler instructions since it does not know about
322 the rounding mode change and cannot currently be told. */
323 __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
324 return __res;
325}
326__MATH_INLINE float
327__NTH (nearbyintf (float __x))
328{
329 float __res;
330 /* Mark as volatile since the result is dependent on the state of
331 the SSE control register (the rounding mode). Otherwise GCC might
332 remove these assembler instructions since it does not know about
333 the rounding mode change and cannot currently be told. */
334 __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
335 return __res;
336}
337# endif
338
339__END_NAMESPACE_C99
340# endif
341
342__BEGIN_NAMESPACE_STD
343/* Smallest integral value not less than X. */
344__MATH_INLINE double
345__NTH (ceil (double __x))
346{
347 double __res;
348 __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x));
349 return __res;
350}
351__END_NAMESPACE_STD
352
353__BEGIN_NAMESPACE_C99
354__MATH_INLINE float
355__NTH (ceilf (float __x))
356{
357 float __res;
358 __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x));
359 return __res;
360}
361__END_NAMESPACE_C99
362
363__BEGIN_NAMESPACE_STD
364/* Largest integer not greater than X. */
365__MATH_INLINE double
366__NTH (floor (double __x))
367{
368 double __res;
369 __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x));
370 return __res;
371}
372__END_NAMESPACE_STD
373
374__BEGIN_NAMESPACE_C99
375__MATH_INLINE float
376__NTH (floorf (float __x))
377{
378 float __res;
379 __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x));
380 return __res;
381}
382__END_NAMESPACE_C99
383# endif
384# endif
385#endif
386
387#ifndef __SSE2_MATH__
388# if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
389 && defined __OPTIMIZE__)
390
391/* The inline functions do not set errno or raise necessarily the
392 correct exceptions. */
393# undef math_errhandling
394
395/* A macro to define float, double, and long double versions of various
396 math functions for the ix87 FPU. FUNC is the function name (which will
397 be suffixed with f and l for the float and long double version,
398 respectively). OP is the name of the FPU operation.
399 We define two sets of macros. The set with the additional NP
400 doesn't add a prototype declaration. */
401
402# if defined __USE_MISC || defined __USE_ISOC99
403# define __inline_mathop(func, op) \
404 __inline_mathop_ (double, func, op) \
405 __inline_mathop_ (float, __CONCAT(func,f), op) \
406 __inline_mathop_ (long double, __CONCAT(func,l), op)
407# define __inline_mathopNP(func, op) \
408 __inline_mathopNP_ (double, func, op) \
409 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
410 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
411# else
412# define __inline_mathop(func, op) \
413 __inline_mathop_ (double, func, op)
414# define __inline_mathopNP(func, op) \
415 __inline_mathopNP_ (double, func, op)
416# endif
417
418# define __inline_mathop_(float_type, func, op) \
419 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
420# define __inline_mathopNP_(float_type, func, op) \
421 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
422
423
424# if defined __USE_MISC || defined __USE_ISOC99
425# define __inline_mathop_decl(func, op, params...) \
426 __inline_mathop_decl_ (double, func, op, params) \
427 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
428 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
429# define __inline_mathop_declNP(func, op, params...) \
430 __inline_mathop_declNP_ (double, func, op, params) \
431 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
432 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
433# else
434# define __inline_mathop_decl(func, op, params...) \
435 __inline_mathop_decl_ (double, func, op, params)
436# define __inline_mathop_declNP(func, op, params...) \
437 __inline_mathop_declNP_ (double, func, op, params)
438# endif
439
440# define __inline_mathop_decl_(float_type, func, op, params...) \
441 __MATH_INLINE float_type func (float_type) __THROW; \
442 __inline_mathop_declNP_ (float_type, func, op, params)
443
444# define __inline_mathop_declNP_(float_type, func, op, params...) \
445 __MATH_INLINE float_type __NTH (func (float_type __x)) \
446 { \
447 register float_type __result; \
448 __asm __volatile__ (op : "=t" (__result) : params); \
449 return __result; \
450 }
451
452
453# if defined __USE_MISC || defined __USE_ISOC99
454# define __inline_mathcode(func, arg, code) \
455 __inline_mathcode_ (double, func, arg, code) \
456 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
457 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
458# define __inline_mathcodeNP(func, arg, code) \
459 __inline_mathcodeNP_ (double, func, arg, code) \
460 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
461 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
462# define __inline_mathcode2(func, arg1, arg2, code) \
463 __inline_mathcode2_ (double, func, arg1, arg2, code) \
464 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
465 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
466# define __inline_mathcodeNP2(func, arg1, arg2, code) \
467 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
468 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
469 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
470# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
471 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
472 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
473 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
474# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
475 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
476 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
477 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
478# else
479# define __inline_mathcode(func, arg, code) \
480 __inline_mathcode_ (double, func, (arg), code)
481# define __inline_mathcodeNP(func, arg, code) \
482 __inline_mathcodeNP_ (double, func, (arg), code)
483# define __inline_mathcode2(func, arg1, arg2, code) \
484 __inline_mathcode2_ (double, func, arg1, arg2, code)
485# define __inline_mathcodeNP2(func, arg1, arg2, code) \
486 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
487# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
488 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
489# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
490 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
491# endif
492
493# define __inline_mathcode_(float_type, func, arg, code) \
494 __MATH_INLINE float_type func (float_type) __THROW; \
495 __inline_mathcodeNP_(float_type, func, arg, code)
496
497# define __inline_mathcodeNP_(float_type, func, arg, code) \
498 __MATH_INLINE float_type __NTH (func (float_type arg)) \
499 { \
500 code; \
501 }
502
503
504# define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
505 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
506 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
507
508# define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
509 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
510 { \
511 code; \
512 }
513
514# define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
515 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
516 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
517
518# define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
519 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
520 float_type arg3)) \
521 { \
522 code; \
523 }
524# endif
525
526
527# if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
528/* Miscellaneous functions */
529
530/* __FAST_MATH__ is defined by gcc -ffast-math. */
531# ifdef __FAST_MATH__
532# ifdef __USE_GNU
533# define __sincos_code \
534 register long double __cosr; \
535 register long double __sinr; \
536 register unsigned int __swtmp; \
537 __asm __volatile__ \
538 ("fsincos\n\t" \
539 "fnstsw %w2\n\t" \
540 "testl $0x400, %2\n\t" \
541 "jz 1f\n\t" \
542 "fldpi\n\t" \
543 "fadd %%st(0)\n\t" \
544 "fxch %%st(1)\n\t" \
545 "2: fprem1\n\t" \
546 "fnstsw %w2\n\t" \
547 "testl $0x400, %2\n\t" \
548 "jnz 2b\n\t" \
549 "fstp %%st(1)\n\t" \
550 "fsincos\n\t" \
551 "1:" \
552 : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \
553 *__sinx = __sinr; \
554 *__cosx = __cosr
555
556__MATH_INLINE void
557__NTH (__sincos (double __x, double *__sinx, double *__cosx))
558{
559 __sincos_code;
560}
561
562__MATH_INLINE void
563__NTH (__sincosf (float __x, float *__sinx, float *__cosx))
564{
565 __sincos_code;
566}
567
568__MATH_INLINE void
569__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
570{
571 __sincos_code;
572}
573# endif
574
575
576/* Optimized inline implementation, sometimes with reduced precision
577 and/or argument range. */
578
579# if __GNUC_PREREQ (3, 5)
580# define __expm1_code \
581 register long double __temp; \
582 __temp = __builtin_expm1l (__x); \
583 return __temp ? __temp : __x
584# else
585# define __expm1_code \
586 register long double __value; \
587 register long double __exponent; \
588 register long double __temp; \
589 __asm __volatile__ \
590 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
591 "fmul %%st(1) # x * log2(e)\n\t" \
592 "fst %%st(1)\n\t" \
593 "frndint # int(x * log2(e))\n\t" \
594 "fxch\n\t" \
595 "fsub %%st(1) # fract(x * log2(e))\n\t" \
596 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
597 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
598 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
599 __asm __volatile__ \
600 ("fscale # 2^int(x * log2(e))\n\t" \
601 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
602 __temp -= 1.0; \
603 __temp += __value; \
604 return __temp ? __temp : __x
605# endif
606__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
607
608# if __GNUC_PREREQ (3, 4)
609__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
610# else
611# define __exp_code \
612 register long double __value; \
613 register long double __exponent; \
614 __asm __volatile__ \
615 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
616 "fmul %%st(1) # x * log2(e)\n\t" \
617 "fst %%st(1)\n\t" \
618 "frndint # int(x * log2(e))\n\t" \
619 "fxch\n\t" \
620 "fsub %%st(1) # fract(x * log2(e))\n\t" \
621 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
622 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
623 __value += 1.0; \
624 __asm __volatile__ \
625 ("fscale" \
626 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
627 return __value
628__inline_mathcodeNP (exp, __x, __exp_code)
629__inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
630# endif
631
632
633# if !__GNUC_PREREQ (3, 5)
634__inline_mathcodeNP (tan, __x, \
635 register long double __value; \
636 register long double __value2 __attribute__ ((__unused__)); \
637 __asm __volatile__ \
638 ("fptan" \
639 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
640 return __value)
641# endif
642# endif /* __FAST_MATH__ */
643
644
645# if __GNUC_PREREQ (3, 4)
646__inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
647 return __builtin_atan2l (__y, __x))
648# else
649# define __atan2_code \
650 register long double __value; \
651 __asm __volatile__ \
652 ("fpatan" \
653 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
654 return __value
655# ifdef __FAST_MATH__
656__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
657# endif
658__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
659# endif
660
661
662# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
663__inline_mathcodeNP2 (fmod, __x, __y, \
664 register long double __value; \
665 __asm __volatile__ \
666 ("1: fprem\n\t" \
667 "fnstsw %%ax\n\t" \
668 "sahf\n\t" \
669 "jp 1b" \
670 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
671 return __value)
672# endif
673
674
675# ifdef __FAST_MATH__
676# if !__GNUC_PREREQ (3,3)
677__inline_mathopNP (sqrt, "fsqrt")
678__inline_mathopNP_ (long double, __sqrtl, "fsqrt")
679# define __libc_sqrtl(n) __sqrtl (n)
680# else
681# define __libc_sqrtl(n) __builtin_sqrtl (n)
682# endif
683# endif
684
685# if __GNUC_PREREQ (2, 8)
686__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
687# if defined __USE_MISC || defined __USE_ISOC99
688__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
689__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
690# endif
691__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
692# else
693__inline_mathop (fabs, "fabs")
694__inline_mathop_ (long double, __fabsl, "fabs")
695# endif
696
697# ifdef __FAST_MATH__
698# if !__GNUC_PREREQ (3, 4)
699/* The argument range of this inline version is reduced. */
700__inline_mathopNP (sin, "fsin")
701/* The argument range of this inline version is reduced. */
702__inline_mathopNP (cos, "fcos")
703
704__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
705# endif
706
707# if !__GNUC_PREREQ (3, 5)
708__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
709
710__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
711__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
712# endif
713
714# if !__GNUC_PREREQ (3, 4)
715__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
716# endif
717# endif /* __FAST_MATH__ */
718
719__inline_mathcode_ (long double, __sgn1l, __x, \
720 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
721 { __xld: __x }; \
722 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
723 __n.__xi[1] = 0x80000000; \
724 __n.__xi[0] = 0; \
725 return __n.__xld)
726
727
728# ifdef __FAST_MATH__
729/* The argument range of the inline version of sinhl is slightly reduced. */
730__inline_mathcodeNP (sinh, __x, \
731 register long double __exm1 = __expm1l (__fabsl (__x)); \
732 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
733
734__inline_mathcodeNP (cosh, __x, \
735 register long double __ex = __expl (__x); \
736 return 0.5 * (__ex + 1.0 / __ex))
737
738__inline_mathcodeNP (tanh, __x, \
739 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
740 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
741# endif
742
743__inline_mathcodeNP (floor, __x, \
744 register long double __value; \
745 register int __ignore; \
746 unsigned short int __cw; \
747 unsigned short int __cwtmp; \
748 __asm __volatile ("fnstcw %3\n\t" \
749 "movzwl %3, %1\n\t" \
750 "andl $0xf3ff, %1\n\t" \
751 "orl $0x0400, %1\n\t" /* rounding down */ \
752 "movw %w1, %2\n\t" \
753 "fldcw %2\n\t" \
754 "frndint\n\t" \
755 "fldcw %3" \
756 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
757 "=m" (__cw) \
758 : "0" (__x)); \
759 return __value)
760
761__inline_mathcodeNP (ceil, __x, \
762 register long double __value; \
763 register int __ignore; \
764 unsigned short int __cw; \
765 unsigned short int __cwtmp; \
766 __asm __volatile ("fnstcw %3\n\t" \
767 "movzwl %3, %1\n\t" \
768 "andl $0xf3ff, %1\n\t" \
769 "orl $0x0800, %1\n\t" /* rounding up */ \
770 "movw %w1, %2\n\t" \
771 "fldcw %2\n\t" \
772 "frndint\n\t" \
773 "fldcw %3" \
774 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
775 "=m" (__cw) \
776 : "0" (__x)); \
777 return __value)
778
779# ifdef __FAST_MATH__
780# define __ldexp_code \
781 register long double __value; \
782 __asm __volatile__ \
783 ("fscale" \
784 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
785 return __value
786
787__MATH_INLINE double
788__NTH (ldexp (double __x, int __y))
789{
790 __ldexp_code;
791}
792# endif
793
794
795/* Optimized versions for some non-standardized functions. */
796# if defined __USE_ISOC99 || defined __USE_MISC
797
798# ifdef __FAST_MATH__
799__inline_mathcodeNP (expm1, __x, __expm1_code)
800
801/* We cannot rely on M_SQRT being defined. So we do it for ourself
802 here. */
803# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
804
805# if !__GNUC_PREREQ (3, 5)
806__inline_mathcodeNP (log1p, __x, \
807 register long double __value; \
808 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
809 __value = logl (1.0 + __x); \
810 else \
811 __asm __volatile__ \
812 ("fldln2\n\t" \
813 "fxch\n\t" \
814 "fyl2xp1" \
815 : "=t" (__value) : "0" (__x) : "st(1)"); \
816 return __value)
817# endif
818
819
820/* The argument range of the inline version of asinhl is slightly reduced. */
821__inline_mathcodeNP (asinh, __x, \
822 register long double __y = __fabsl (__x); \
823 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
824 * __sgn1l (__x)))
825
826__inline_mathcodeNP (acosh, __x, \
827 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
828
829__inline_mathcodeNP (atanh, __x, \
830 register long double __y = __fabsl (__x); \
831 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
832
833/* The argument range of the inline version of hypotl is slightly reduced. */
834__inline_mathcodeNP2 (hypot, __x, __y,
835 return __libc_sqrtl (__x * __x + __y * __y))
836
837# if !__GNUC_PREREQ (3, 5)
838__inline_mathcodeNP(logb, __x, \
839 register long double __value; \
840 register long double __junk; \
841 __asm __volatile__ \
842 ("fxtract\n\t" \
843 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
844 return __value)
845# endif
846
847# endif
848# endif
849
850# ifdef __USE_ISOC99
851# ifdef __FAST_MATH__
852
853# if !__GNUC_PREREQ (3, 5)
854__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
855# endif
856
857__MATH_INLINE float
858__NTH (ldexpf (float __x, int __y))
859{
860 __ldexp_code;
861}
862
863__MATH_INLINE long double
864__NTH (ldexpl (long double __x, int __y))
865{
866 __ldexp_code;
867}
868
869__inline_mathopNP (rint, "frndint")
870# endif /* __FAST_MATH__ */
871
872# define __lrint_code \
873 long int __lrintres; \
874 __asm__ __volatile__ \
875 ("fistpl %0" \
876 : "=m" (__lrintres) : "t" (__x) : "st"); \
877 return __lrintres
878__MATH_INLINE long int
879__NTH (lrintf (float __x))
880{
881 __lrint_code;
882}
883__MATH_INLINE long int
884__NTH (lrint (double __x))
885{
886 __lrint_code;
887}
888__MATH_INLINE long int
889__NTH (lrintl (long double __x))
890{
891 __lrint_code;
892}
893# undef __lrint_code
894
895# define __llrint_code \
896 long long int __llrintres; \
897 __asm__ __volatile__ \
898 ("fistpll %0" \
899 : "=m" (__llrintres) : "t" (__x) : "st"); \
900 return __llrintres
901__extension__
902__MATH_INLINE long long int
903__NTH (llrintf (float __x))
904{
905 __llrint_code;
906}
907__extension__
908__MATH_INLINE long long int
909__NTH (llrint (double __x))
910{
911 __llrint_code;
912}
913__extension__
914__MATH_INLINE long long int
915__NTH (llrintl (long double __x))
916{
917 __llrint_code;
918}
919# undef __llrint_code
920
921# endif
922
923
924# ifdef __USE_MISC
925
926# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
927__inline_mathcodeNP2 (drem, __x, __y, \
928 register double __value; \
929 register int __clobbered; \
930 __asm __volatile__ \
931 ("1: fprem1\n\t" \
932 "fstsw %%ax\n\t" \
933 "sahf\n\t" \
934 "jp 1b" \
935 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
936 return __value)
937# endif
938
939
940/* This function is used in the `isfinite' macro. */
941__MATH_INLINE int
942__NTH (__finite (double __x))
943{
944 return (__extension__
945 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
946 | 0x800fffffu) + 1) >> 31));
947}
948
949# endif /* __USE_MISC */
950
951/* Undefine some of the large macros which are not used anymore. */
952# undef __atan2_code
953# ifdef __FAST_MATH__
954# undef __expm1_code
955# undef __exp_code
956# undef __sincos_code
957# endif /* __FAST_MATH__ */
958
959# endif /* __NO_MATH_INLINES */
960
961
962/* This code is used internally in the GNU libc. */
963# ifdef __LIBC_INTERNAL_MATH_INLINES
964__inline_mathop (__ieee754_sqrt, "fsqrt")
965__inline_mathcode2 (__ieee754_atan2, __y, __x,
966 register long double __value;
967 __asm __volatile__ ("fpatan\n\t"
968 : "=t" (__value)
969 : "0" (__x), "u" (__y) : "st(1)");
970 return __value;)
971# endif
972
973#endif /* !__SSE2_MATH__ */
974