Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / i386 / fpu / bits / mathinline.h
blob276acf8e7195c4d862c3ef19257208270a58925f
1 /* Inline math functions for i387.
2 Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2003,2004,2006,2007,2009,
3 2010 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef _MATH_H
22 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #endif
25 #ifndef __extern_inline
26 # define __MATH_INLINE __inline
27 #else
28 # define __MATH_INLINE __extern_inline
29 #endif
32 #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
33 /* GCC 2.97 and up have builtins that actually can be used. */
34 # if !__GNUC_PREREQ (2,97)
35 /* ISO C99 defines some macros to perform unordered comparisons. The
36 ix87 FPU supports this with special opcodes and we should use them.
37 These must not be inline functions since we have to be able to handle
38 all floating-point types. */
39 # undef isgreater
40 # undef isgreaterequal
41 # undef isless
42 # undef islessequal
43 # undef islessgreater
44 # undef isunordered
45 # ifdef __i686__
46 /* For the PentiumPro and more recent processors we can provide
47 better code. */
48 # define isgreater(x, y) \
49 ({ register char __result; \
50 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
51 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
52 __result; })
53 # define isgreaterequal(x, y) \
54 ({ register char __result; \
55 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
56 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
57 __result; })
59 # define isless(x, y) \
60 ({ register char __result; \
61 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
62 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
63 __result; })
65 # define islessequal(x, y) \
66 ({ register char __result; \
67 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
68 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
69 __result; })
71 # define islessgreater(x, y) \
72 ({ register char __result; \
73 __asm__ ("fucomip %%st(1), %%st; setne %%al" \
74 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
75 __result; })
77 # define isunordered(x, y) \
78 ({ register char __result; \
79 __asm__ ("fucomip %%st(1), %%st; setp %%al" \
80 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
81 __result; })
82 # else
83 /* This is the dumb, portable code for i386 and above. */
84 # define isgreater(x, y) \
85 ({ register char __result; \
86 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
87 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
88 __result; })
90 # define isgreaterequal(x, y) \
91 ({ register char __result; \
92 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
93 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
94 __result; })
96 # define isless(x, y) \
97 ({ register char __result; \
98 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
99 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
100 __result; })
102 # define islessequal(x, y) \
103 ({ register char __result; \
104 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
105 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
106 __result; })
108 # define islessgreater(x, y) \
109 ({ register char __result; \
110 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \
111 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
112 __result; })
114 # define isunordered(x, y) \
115 ({ register char __result; \
116 __asm__ ("fucompp; fnstsw; sahf; setp %%al" \
117 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
118 __result; })
119 # endif /* __i686__ */
120 # endif /* GCC 2.97 */
122 /* The gcc, version 2.7 or below, has problems with all this inlining
123 code. So disable it for this version of the compiler. */
124 # if __GNUC_PREREQ (2, 8)
125 /* Test for negative number. Used in the signbit() macro. */
126 __MATH_INLINE int
127 __NTH (__signbitf (float __x))
129 __extension__ union { float __f; int __i; } __u = { __f: __x };
130 return __u.__i < 0;
132 __MATH_INLINE int
133 __NTH (__signbit (double __x))
135 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
136 return __u.__i[1] < 0;
138 __MATH_INLINE int
139 __NTH (__signbitl (long double __x))
141 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
142 return (__u.__i[2] & 0x8000) != 0;
144 # endif
145 #endif
148 /* The gcc, version 2.7 or below, has problems with all this inlining
149 code. So disable it for this version of the compiler. */
150 #if __GNUC_PREREQ (2, 8)
152 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
153 && defined __OPTIMIZE__)
155 /* The inline functions do not set errno or raise necessarily the
156 correct exceptions. */
157 # undef math_errhandling
159 /* A macro to define float, double, and long double versions of various
160 math functions for the ix87 FPU. FUNC is the function name (which will
161 be suffixed with f and l for the float and long double version,
162 respectively). OP is the name of the FPU operation.
163 We define two sets of macros. The set with the additional NP
164 doesn't add a prototype declaration. */
166 #if defined __USE_MISC || defined __USE_ISOC99
167 # define __inline_mathop(func, op) \
168 __inline_mathop_ (double, func, op) \
169 __inline_mathop_ (float, __CONCAT(func,f), op) \
170 __inline_mathop_ (long double, __CONCAT(func,l), op)
171 # define __inline_mathopNP(func, op) \
172 __inline_mathopNP_ (double, func, op) \
173 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
174 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
175 #else
176 # define __inline_mathop(func, op) \
177 __inline_mathop_ (double, func, op)
178 # define __inline_mathopNP(func, op) \
179 __inline_mathopNP_ (double, func, op)
180 #endif
182 #define __inline_mathop_(float_type, func, op) \
183 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
184 #define __inline_mathopNP_(float_type, func, op) \
185 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
188 #if defined __USE_MISC || defined __USE_ISOC99
189 # define __inline_mathop_decl(func, op, params...) \
190 __inline_mathop_decl_ (double, func, op, params) \
191 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
192 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
193 # define __inline_mathop_declNP(func, op, params...) \
194 __inline_mathop_declNP_ (double, func, op, params) \
195 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
196 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
197 #else
198 # define __inline_mathop_decl(func, op, params...) \
199 __inline_mathop_decl_ (double, func, op, params)
200 # define __inline_mathop_declNP(func, op, params...) \
201 __inline_mathop_declNP_ (double, func, op, params)
202 #endif
204 #define __inline_mathop_decl_(float_type, func, op, params...) \
205 __MATH_INLINE float_type func (float_type) __THROW; \
206 __inline_mathop_declNP_ (float_type, func, op, params)
208 #define __inline_mathop_declNP_(float_type, func, op, params...) \
209 __MATH_INLINE float_type __NTH (func (float_type __x)) \
211 register float_type __result; \
212 __asm __volatile__ (op : "=t" (__result) : params); \
213 return __result; \
217 #if defined __USE_MISC || defined __USE_ISOC99
218 # define __inline_mathcode(func, arg, code) \
219 __inline_mathcode_ (double, func, arg, code) \
220 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
221 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
222 # define __inline_mathcodeNP(func, arg, code) \
223 __inline_mathcodeNP_ (double, func, arg, code) \
224 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
225 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
226 # define __inline_mathcode2(func, arg1, arg2, code) \
227 __inline_mathcode2_ (double, func, arg1, arg2, code) \
228 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
229 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
230 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
231 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
232 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
233 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
234 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
235 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
236 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
237 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
238 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
239 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
240 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
241 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
242 #else
243 # define __inline_mathcode(func, arg, code) \
244 __inline_mathcode_ (double, func, (arg), code)
245 # define __inline_mathcodeNP(func, arg, code) \
246 __inline_mathcodeNP_ (double, func, (arg), code)
247 # define __inline_mathcode2(func, arg1, arg2, code) \
248 __inline_mathcode2_ (double, func, arg1, arg2, code)
249 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
250 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
251 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
252 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
253 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
254 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
255 #endif
257 #define __inline_mathcode_(float_type, func, arg, code) \
258 __MATH_INLINE float_type func (float_type) __THROW; \
259 __inline_mathcodeNP_(float_type, func, arg, code)
261 #define __inline_mathcodeNP_(float_type, func, arg, code) \
262 __MATH_INLINE float_type __NTH (func (float_type arg)) \
264 code; \
268 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
269 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
270 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
272 #define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
273 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
275 code; \
278 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
279 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
280 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
282 #define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
283 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
284 float_type arg3)) \
286 code; \
288 #endif
291 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
292 /* Miscellaneous functions */
294 __inline_mathcode (__sgn, __x, \
295 return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
297 /* __FAST_MATH__ is defined by gcc -ffast-math. */
298 #ifdef __FAST_MATH__
299 __inline_mathcode (__pow2, __x, \
300 register long double __value; \
301 register long double __exponent; \
302 __extension__ long long int __p = (long long int) __x; \
303 if (__x == (long double) __p) \
305 __asm __volatile__ \
306 ("fscale" \
307 : "=t" (__value) : "0" (1.0), "u" (__x)); \
308 return __value; \
310 __asm __volatile__ \
311 ("fld %%st(0)\n\t" \
312 "frndint # int(x)\n\t" \
313 "fxch\n\t" \
314 "fsub %%st(1) # fract(x)\n\t" \
315 "f2xm1 # 2^(fract(x)) - 1\n\t" \
316 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
317 __value += 1.0; \
318 __asm __volatile__ \
319 ("fscale" \
320 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
321 return __value)
323 # ifdef __USE_GNU
324 # define __sincos_code \
325 register long double __cosr; \
326 register long double __sinr; \
327 __asm __volatile__ \
328 ("fsincos\n\t" \
329 "fnstsw %%ax\n\t" \
330 "testl $0x400, %%eax\n\t" \
331 "jz 1f\n\t" \
332 "fldpi\n\t" \
333 "fadd %%st(0)\n\t" \
334 "fxch %%st(1)\n\t" \
335 "2: fprem1\n\t" \
336 "fnstsw %%ax\n\t" \
337 "testl $0x400, %%eax\n\t" \
338 "jnz 2b\n\t" \
339 "fstp %%st(1)\n\t" \
340 "fsincos\n\t" \
341 "1:" \
342 : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
343 *__sinx = __sinr; \
344 *__cosx = __cosr
346 __MATH_INLINE void
347 __NTH (__sincos (double __x, double *__sinx, double *__cosx))
349 __sincos_code;
352 __MATH_INLINE void
353 __NTH (__sincosf (float __x, float *__sinx, float *__cosx))
355 __sincos_code;
358 __MATH_INLINE void
359 __NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
361 __sincos_code;
363 # endif
366 /* Optimized inline implementation, sometimes with reduced precision
367 and/or argument range. */
369 # if __GNUC_PREREQ (3, 5)
370 # define __expm1_code \
371 register long double __temp; \
372 __temp = __builtin_expm1l (__x); \
373 return __temp ? __temp : __x
374 # else
375 # define __expm1_code \
376 register long double __value; \
377 register long double __exponent; \
378 register long double __temp; \
379 __asm __volatile__ \
380 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
381 "fmul %%st(1) # x * log2(e)\n\t" \
382 "fst %%st(1)\n\t" \
383 "frndint # int(x * log2(e))\n\t" \
384 "fxch\n\t" \
385 "fsub %%st(1) # fract(x * log2(e))\n\t" \
386 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
387 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
388 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
389 __asm __volatile__ \
390 ("fscale # 2^int(x * log2(e))\n\t" \
391 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
392 __temp -= 1.0; \
393 __temp += __value; \
394 return __temp ? __temp : __x
395 # endif
396 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
398 # if __GNUC_PREREQ (3, 4)
399 __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
400 # else
401 # define __exp_code \
402 register long double __value; \
403 register long double __exponent; \
404 __asm __volatile__ \
405 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
406 "fmul %%st(1) # x * log2(e)\n\t" \
407 "fst %%st(1)\n\t" \
408 "frndint # int(x * log2(e))\n\t" \
409 "fxch\n\t" \
410 "fsub %%st(1) # fract(x * log2(e))\n\t" \
411 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
412 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
413 __value += 1.0; \
414 __asm __volatile__ \
415 ("fscale" \
416 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
417 return __value
418 __inline_mathcodeNP (exp, __x, __exp_code)
419 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
420 # endif
423 # if !__GNUC_PREREQ (3, 5)
424 __inline_mathcodeNP (tan, __x, \
425 register long double __value; \
426 register long double __value2 __attribute__ ((__unused__)); \
427 __asm __volatile__ \
428 ("fptan" \
429 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
430 return __value)
431 # endif
432 #endif /* __FAST_MATH__ */
435 #if __GNUC_PREREQ (3, 4)
436 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
437 return __builtin_atan2l (__y, __x))
438 #else
439 # define __atan2_code \
440 register long double __value; \
441 __asm __volatile__ \
442 ("fpatan" \
443 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
444 return __value
445 # ifdef __FAST_MATH__
446 __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
447 # endif
448 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
449 #endif
452 #if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
453 __inline_mathcodeNP2 (fmod, __x, __y, \
454 register long double __value; \
455 __asm __volatile__ \
456 ("1: fprem\n\t" \
457 "fnstsw %%ax\n\t" \
458 "sahf\n\t" \
459 "jp 1b" \
460 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
461 return __value)
462 #endif
465 #ifdef __FAST_MATH__
466 # if !__GNUC_PREREQ (3,3)
467 __inline_mathopNP (sqrt, "fsqrt")
468 __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
469 # define __libc_sqrtl(n) __sqrtl (n)
470 # else
471 # define __libc_sqrtl(n) __builtin_sqrtl (n)
472 # endif
473 #endif
475 #if __GNUC_PREREQ (2, 8)
476 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
477 # if defined __USE_MISC || defined __USE_ISOC99
478 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
479 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
480 # endif
481 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
482 #else
483 __inline_mathop (fabs, "fabs")
484 __inline_mathop_ (long double, __fabsl, "fabs")
485 #endif
487 #ifdef __FAST_MATH__
488 # if !__GNUC_PREREQ (3, 4)
489 /* The argument range of this inline version is reduced. */
490 __inline_mathopNP (sin, "fsin")
491 /* The argument range of this inline version is reduced. */
492 __inline_mathopNP (cos, "fcos")
494 __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
495 # endif
497 # if !__GNUC_PREREQ (3, 5)
498 __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
500 __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
501 __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
502 # endif
504 # if !__GNUC_PREREQ (3, 4)
505 __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
506 # endif
507 #endif /* __FAST_MATH__ */
509 __inline_mathcode_ (long double, __sgn1l, __x, \
510 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
511 { __xld: __x }; \
512 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
513 __n.__xi[1] = 0x80000000; \
514 __n.__xi[0] = 0; \
515 return __n.__xld)
518 #ifdef __FAST_MATH__
519 /* The argument range of the inline version of sinhl is slightly reduced. */
520 __inline_mathcodeNP (sinh, __x, \
521 register long double __exm1 = __expm1l (__fabsl (__x)); \
522 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
524 __inline_mathcodeNP (cosh, __x, \
525 register long double __ex = __expl (__x); \
526 return 0.5 * (__ex + 1.0 / __ex))
528 __inline_mathcodeNP (tanh, __x, \
529 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
530 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
531 #endif
533 __inline_mathcodeNP (floor, __x, \
534 register long double __value; \
535 register int __ignore; \
536 unsigned short int __cw; \
537 unsigned short int __cwtmp; \
538 __asm __volatile ("fnstcw %3\n\t" \
539 "movzwl %3, %1\n\t" \
540 "andl $0xf3ff, %1\n\t" \
541 "orl $0x0400, %1\n\t" /* rounding down */ \
542 "movw %w1, %2\n\t" \
543 "fldcw %2\n\t" \
544 "frndint\n\t" \
545 "fldcw %3" \
546 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
547 "=m" (__cw) \
548 : "0" (__x)); \
549 return __value)
551 __inline_mathcodeNP (ceil, __x, \
552 register long double __value; \
553 register int __ignore; \
554 unsigned short int __cw; \
555 unsigned short int __cwtmp; \
556 __asm __volatile ("fnstcw %3\n\t" \
557 "movzwl %3, %1\n\t" \
558 "andl $0xf3ff, %1\n\t" \
559 "orl $0x0800, %1\n\t" /* rounding up */ \
560 "movw %w1, %2\n\t" \
561 "fldcw %2\n\t" \
562 "frndint\n\t" \
563 "fldcw %3" \
564 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
565 "=m" (__cw) \
566 : "0" (__x)); \
567 return __value)
569 #ifdef __FAST_MATH__
570 # define __ldexp_code \
571 register long double __value; \
572 __asm __volatile__ \
573 ("fscale" \
574 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
575 return __value
577 __MATH_INLINE double
578 __NTH (ldexp (double __x, int __y))
580 __ldexp_code;
582 #endif
585 /* Optimized versions for some non-standardized functions. */
586 #if defined __USE_ISOC99 || defined __USE_MISC
588 # ifdef __FAST_MATH__
589 __inline_mathcodeNP (expm1, __x, __expm1_code)
591 /* We cannot rely on M_SQRT being defined. So we do it for ourself
592 here. */
593 # define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
595 # if !__GNUC_PREREQ (3, 5)
596 __inline_mathcodeNP (log1p, __x, \
597 register long double __value; \
598 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
599 __value = logl (1.0 + __x); \
600 else \
601 __asm __volatile__ \
602 ("fldln2\n\t" \
603 "fxch\n\t" \
604 "fyl2xp1" \
605 : "=t" (__value) : "0" (__x) : "st(1)"); \
606 return __value)
607 # endif
610 /* The argument range of the inline version of asinhl is slightly reduced. */
611 __inline_mathcodeNP (asinh, __x, \
612 register long double __y = __fabsl (__x); \
613 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
614 * __sgn1l (__x)))
616 __inline_mathcodeNP (acosh, __x, \
617 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
619 __inline_mathcodeNP (atanh, __x, \
620 register long double __y = __fabsl (__x); \
621 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
623 /* The argument range of the inline version of hypotl is slightly reduced. */
624 __inline_mathcodeNP2 (hypot, __x, __y,
625 return __libc_sqrtl (__x * __x + __y * __y))
627 # if !__GNUC_PREREQ (3, 5)
628 __inline_mathcodeNP(logb, __x, \
629 register long double __value; \
630 register long double __junk; \
631 __asm __volatile__ \
632 ("fxtract\n\t" \
633 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
634 return __value)
635 # endif
637 # endif
638 #endif
640 #ifdef __USE_ISOC99
641 # ifdef __FAST_MATH__
643 # if !__GNUC_PREREQ (3, 5)
644 __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
645 # endif
647 __MATH_INLINE float
648 __NTH (ldexpf (float __x, int __y))
650 __ldexp_code;
653 __MATH_INLINE long double
654 __NTH (ldexpl (long double __x, int __y))
656 __ldexp_code;
659 __inline_mathopNP (rint, "frndint")
660 # endif /* __FAST_MATH__ */
662 # define __lrint_code \
663 long int __lrintres; \
664 __asm__ __volatile__ \
665 ("fistpl %0" \
666 : "=m" (__lrintres) : "t" (__x) : "st"); \
667 return __lrintres
668 __MATH_INLINE long int
669 __NTH (lrintf (float __x))
671 __lrint_code;
673 __MATH_INLINE long int
674 __NTH (lrint (double __x))
676 __lrint_code;
678 __MATH_INLINE long int
679 __NTH (lrintl (long double __x))
681 __lrint_code;
683 # undef __lrint_code
685 # define __llrint_code \
686 long long int __llrintres; \
687 __asm__ __volatile__ \
688 ("fistpll %0" \
689 : "=m" (__llrintres) : "t" (__x) : "st"); \
690 return __llrintres
691 __MATH_INLINE long long int
692 __NTH (llrintf (float __x))
694 __llrint_code;
696 __MATH_INLINE long long int
697 __NTH (llrint (double __x))
699 __llrint_code;
701 __MATH_INLINE long long int
702 __NTH (llrintl (long double __x))
704 __llrint_code;
706 # undef __llrint_code
708 #endif
711 #ifdef __USE_MISC
713 # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
714 __inline_mathcodeNP2 (drem, __x, __y, \
715 register double __value; \
716 register int __clobbered; \
717 __asm __volatile__ \
718 ("1: fprem1\n\t" \
719 "fstsw %%ax\n\t" \
720 "sahf\n\t" \
721 "jp 1b" \
722 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
723 return __value)
724 # endif
727 /* This function is used in the `isfinite' macro. */
728 __MATH_INLINE int
729 __NTH (__finite (double __x))
731 return (__extension__
732 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
733 | 0x800fffffu) + 1) >> 31));
736 /* Miscellaneous functions */
737 # ifdef __FAST_MATH__
738 __inline_mathcode (__coshm1, __x, \
739 register long double __exm1 = __expm1l (__fabsl (__x)); \
740 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
742 __inline_mathcode (__acosh1p, __x, \
743 return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0)))
745 # endif /* __FAST_MATH__ */
746 #endif /* __USE_MISC */
748 /* Undefine some of the large macros which are not used anymore. */
749 #undef __atan2_code
750 #ifdef __FAST_MATH__
751 # undef __expm1_code
752 # undef __exp_code
753 # undef __sincos_code
754 #endif /* __FAST_MATH__ */
756 #endif /* __NO_MATH_INLINES */
759 /* This code is used internally in the GNU libc. */
760 #ifdef __LIBC_INTERNAL_MATH_INLINES
761 __inline_mathop (__ieee754_sqrt, "fsqrt")
762 __inline_mathcode2 (__ieee754_atan2, __y, __x,
763 register long double __value;
764 __asm __volatile__ ("fpatan\n\t"
765 : "=t" (__value)
766 : "0" (__x), "u" (__y) : "st(1)");
767 return __value;)
768 #endif
770 #endif /* __GNUC__ */