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