Add __extension__ to signbit definitions to calm down gcc.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / fpu / bits / mathinline.h
1 /* Inline math functions for i387.
2    Copyright (C) 1995, 1996, 1997, 1998, 1999 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_ISOC9X && defined __GNUC__ && __GNUC__ >= 2
33 /* ISO C 9X 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 # ifdef __i686__
38 /* For the PentiumPro and more recent processors we can provide
39    better code.  */
40 #  define isgreater(x, y) \
41      ({ register char __result;                                               \
42         __asm__ ("fucomip %%st(1), %%st; seta %%al"                           \
43                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
44         __result; })
45 #  define isgreaterequal(x, y) \
46      ({ register char __result;                                               \
47         __asm__ ("fucomip %%st(1), %%st; setae %%al"                          \
48                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
49         __result; })
50
51 #  define isless(x, y) \
52      ({ register char __result;                                               \
53         __asm__ ("fucomip %%st(1), %%st; seta %%al"                           \
54                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
55         __result; })
56
57 #  define islessequal(x, y) \
58      ({ register char __result;                                               \
59         __asm__ ("fucomip %%st(1), %%st; setae %%al"                          \
60                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
61         __result; })
62
63 #  define islessgreater(x, y) \
64      ({ register char __result;                                               \
65         __asm__ ("fucomip %%st(1), %%st; setne %%al"                          \
66                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
67         __result; })
68
69 #  define isunordered(x, y) \
70      ({ register char __result;                                               \
71         __asm__ ("fucomip %%st(1), %%st; setp %%al"                           \
72                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
73         __result; })
74 # else
75 /* This is the dumb, portable code for i386 and above.  */
76 #  define isgreater(x, y) \
77      ({ register char __result;                                               \
78         __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"              \
79                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
80         __result; })
81
82 #  define isgreaterequal(x, y) \
83      ({ register char __result;                                               \
84         __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"              \
85                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
86         __result; })
87
88 #  define isless(x, y) \
89      ({ register char __result;                                               \
90         __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"              \
91                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
92         __result; })
93
94 #  define islessequal(x, y) \
95      ({ register char __result;                                               \
96         __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"              \
97                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
98         __result; })
99
100 #  define islessgreater(x, y) \
101      ({ register char __result;                                               \
102         __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al"              \
103                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
104         __result; })
105
106 #  define isunordered(x, y) \
107      ({ register char __result;                                               \
108         __asm__ ("fucompp; fnstsw; sahf; setp %%al"                           \
109                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
110         __result; })
111 # endif /* __i686__ */
112
113 /* Test for negative number.  Used in the signbit() macro.  */
114 __MATH_INLINE int
115 __signbitf (float __x)
116 {
117   __extension__ union { float __f; int __i; } __u = { __f: __x };
118   return __u.__i < 0;
119 }
120 __MATH_INLINE int
121 __signbit (double __x)
122 {
123   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
124   return __u.__i[1] < 0;
125 }
126 __MATH_INLINE int
127 __signbitl (long double __x)
128 {
129   __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
130   return (__u.__i[2] & 0x8000) != 0;
131 }
132 #endif
133
134
135 /* The gcc, version 2.7 or below, has problems with all this inlining
136    code.  So disable it for this version of the compiler.  */
137 #if defined __GNUC__ && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7))
138
139 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
140      && defined __OPTIMIZE__)
141
142 /* A macro to define float, double, and long double versions of various
143    math functions for the ix87 FPU.  FUNC is the function name (which will
144    be suffixed with f and l for the float and long double version,
145    respectively).  OP is the name of the FPU operation.  */
146
147 #if defined __USE_MISC || defined __USE_ISOC9X
148 # define __inline_mathop(func, op) \
149   __inline_mathop_ (double, func, op)                                         \
150   __inline_mathop_ (float, __CONCAT(func,f), op)                              \
151   __inline_mathop_ (long double, __CONCAT(func,l), op)
152 #else
153 # define __inline_mathop(func, op) \
154   __inline_mathop_ (double, func, op)
155 #endif
156
157 #define __inline_mathop_(float_type, func, op) \
158   __inline_mathop_decl_ (float_type, func, op, "0" (__x))
159
160
161 #if defined __USE_MISC || defined __USE_ISOC9X
162 # define __inline_mathop_decl(func, op, params...) \
163   __inline_mathop_decl_ (double, func, op, params)                            \
164   __inline_mathop_decl_ (float, __CONCAT(func,f), op, params)                 \
165   __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
166 #else
167 # define __inline_mathop_decl(func, op, params...) \
168   __inline_mathop_decl_ (double, func, op, params)
169 #endif
170
171 #define __inline_mathop_decl_(float_type, func, op, params...) \
172   __MATH_INLINE float_type func (float_type);                                 \
173   __MATH_INLINE float_type func (float_type __x)                              \
174   {                                                                           \
175     register float_type __result;                                             \
176     __asm __volatile__ (op : "=t" (__result) : params);                       \
177     return __result;                                                          \
178   }
179
180
181 #if defined __USE_MISC || defined __USE_ISOC9X
182 # define __inline_mathcode(func, arg, code) \
183   __inline_mathcode_ (double, func, arg, code)                                \
184   __inline_mathcode_ (float, __CONCAT(func,f), arg, code)                     \
185   __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
186 # define __inline_mathcode2(func, arg1, arg2, code) \
187   __inline_mathcode2_ (double, func, arg1, arg2, code)                        \
188   __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code)             \
189   __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
190 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
191   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)                  \
192   __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)       \
193   __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
194 #else
195 # define __inline_mathcode(func, arg, code) \
196   __inline_mathcode_ (double, func, (arg), code)
197 # define __inline_mathcode2(func, arg1, arg2, code) \
198   __inline_mathcode2_ (double, func, arg1, arg2, code)
199 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
200   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
201 #endif
202
203 #define __inline_mathcode_(float_type, func, arg, code) \
204   __MATH_INLINE float_type func (float_type);                                 \
205   __MATH_INLINE float_type func (float_type arg)                              \
206   {                                                                           \
207     code;                                                                     \
208   }
209
210 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
211   __MATH_INLINE float_type func (float_type, float_type);                     \
212   __MATH_INLINE float_type func (float_type arg1, float_type arg2)            \
213   {                                                                           \
214     code;                                                                     \
215   }
216
217 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
218   __MATH_INLINE float_type func (float_type, float_type, float_type);         \
219   __MATH_INLINE float_type func (float_type arg1, float_type arg2,            \
220                                  float_type arg3)                             \
221   {                                                                           \
222     code;                                                                     \
223   }
224 #endif
225
226
227 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
228 /* Miscellaneous functions */
229
230 __inline_mathcode (__sgn, __x, \
231   return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
232
233 __inline_mathcode (__pow2, __x, \
234   register long double __value;                                               \
235   register long double __exponent;                                            \
236   __extension__ long long int __p = (long long int) __x;                      \
237   if (__x == (long double) __p)                                               \
238     {                                                                         \
239       __asm __volatile__                                                      \
240         ("fscale"                                                             \
241          : "=t" (__value) : "0" (1.0), "u" (__x));                            \
242       return __value;                                                         \
243     }                                                                         \
244   __asm __volatile__                                                          \
245     ("fld       %%st(0)\n\t"                                                  \
246      "frndint                   # int(x)\n\t"                                 \
247      "fxch\n\t"                                                               \
248      "fsub      %%st(1)         # fract(x)\n\t"                               \
249      "f2xm1                     # 2^(fract(x)) - 1\n\t"                       \
250      : "=t" (__value), "=u" (__exponent) : "0" (__x));                        \
251   __value += 1.0;                                                             \
252   __asm __volatile__                                                          \
253     ("fscale"                                                                 \
254      : "=t" (__value) : "0" (__value), "u" (__exponent));                     \
255   return __value)
256
257 #define __sincos_code \
258   register long double __cosr;                                                \
259   register long double __sinr;                                                \
260   __asm __volatile__                                                          \
261     ("fsincos\n\t"                                                            \
262      "fnstsw    %%ax\n\t"                                                     \
263      "testl     $0x400, %%eax\n\t"                                            \
264      "jz        1f\n\t"                                                       \
265      "fldpi\n\t"                                                              \
266      "fadd      %%st(0)\n\t"                                                  \
267      "fxch      %%st(1)\n\t"                                                  \
268      "2: fprem1\n\t"                                                          \
269      "fnstsw    %%ax\n\t"                                                     \
270      "testl     $0x400, %%eax\n\t"                                            \
271      "jnz       2b\n\t"                                                       \
272      "fstp      %%st(1)\n\t"                                                  \
273      "fsincos\n\t"                                                            \
274      "1:"                                                                     \
275      : "=t" (__cosr), "=u" (__sinr) : "0" (__x));                             \
276   *__sinx = __sinr;                                                           \
277   *__cosx = __cosr
278
279 __MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx);
280 __MATH_INLINE void
281 __sincos (double __x, double *__sinx, double *__cosx)
282 {
283   __sincos_code;
284 }
285
286 __MATH_INLINE void __sincosf (float __x, float *__sinx, float *__cosx);
287 __MATH_INLINE void
288 __sincosf (float __x, float *__sinx, float *__cosx)
289 {
290   __sincos_code;
291 }
292
293 __MATH_INLINE void __sincosl (long double __x, long double *__sinx,
294                               long double *__cosx);
295 __MATH_INLINE void
296 __sincosl (long double __x, long double *__sinx, long double *__cosx)
297 {
298   __sincos_code;
299 }
300
301
302 /* Optimized inline implementation, sometimes with reduced precision
303    and/or argument range.  */
304
305 #define __expm1_code \
306   register long double __value;                                               \
307   register long double __exponent;                                            \
308   register long double __temp;                                                \
309   __asm __volatile__                                                          \
310     ("fldl2e                    # e^x - 1 = 2^(x * log2(e)) - 1\n\t"          \
311      "fmul      %%st(1)         # x * log2(e)\n\t"                            \
312      "fst       %%st(1)\n\t"                                                  \
313      "frndint                   # int(x * log2(e))\n\t"                       \
314      "fxch\n\t"                                                               \
315      "fsub      %%st(1)         # fract(x * log2(e))\n\t"                     \
316      "f2xm1                     # 2^(fract(x * log2(e))) - 1\n\t"             \
317      "fscale                    # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
318      : "=t" (__value), "=u" (__exponent) : "0" (__x));                        \
319   __asm __volatile__                                                          \
320     ("fscale                    # 2^int(x * log2(e))\n\t"                     \
321      : "=t" (__temp) : "0" (1.0), "u" (__exponent));                          \
322   __temp -= 1.0;                                                              \
323   return __temp + __value
324 __inline_mathcode_ (long double, __expm1l, __x, __expm1_code)
325
326
327 #define __exp_code \
328   register long double __value;                                               \
329   register long double __exponent;                                            \
330   __asm __volatile__                                                          \
331     ("fldl2e                    # e^x = 2^(x * log2(e))\n\t"                  \
332      "fmul      %%st(1)         # x * log2(e)\n\t"                            \
333      "fst       %%st(1)\n\t"                                                  \
334      "frndint                   # int(x * log2(e))\n\t"                       \
335      "fxch\n\t"                                                               \
336      "fsub      %%st(1)         # fract(x * log2(e))\n\t"                     \
337      "f2xm1                     # 2^(fract(x * log2(e))) - 1\n\t"             \
338      : "=t" (__value), "=u" (__exponent) : "0" (__x));                        \
339   __value += 1.0;                                                             \
340   __asm __volatile__                                                          \
341     ("fscale"                                                                 \
342      : "=t" (__value) : "0" (__value), "u" (__exponent));                     \
343   return __value
344 __inline_mathcode (exp, __x, __exp_code)
345 __inline_mathcode_ (long double, __expl, __x, __exp_code)
346
347
348 __inline_mathcode (tan, __x, \
349   register long double __value;                                               \
350   register long double __value2 __attribute__ ((__unused__));                 \
351   __asm __volatile__                                                          \
352     ("fptan"                                                                  \
353      : "=t" (__value2), "=u" (__value) : "0" (__x));                          \
354   return __value)
355
356
357 #define __atan2_code \
358   register long double __value;                                               \
359   __asm __volatile__                                                          \
360     ("fpatan\n\t"                                                             \
361      : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)");                      \
362   return __value
363 __inline_mathcode2 (atan2, __y, __x, __atan2_code)
364 __inline_mathcode2_ (long double, __atan2l, __y, __x, __atan2_code)
365
366
367 __inline_mathcode2 (fmod, __x, __y, \
368   register long double __value;                                               \
369   __asm __volatile__                                                          \
370     ("1:        fprem\n\t"                                                    \
371      "fnstsw    %%ax\n\t"                                                     \
372      "sahf\n\t"                                                               \
373      "jp        1b"                                                           \
374      : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");                   \
375   return __value)
376
377
378 __inline_mathcode2 (pow, __x, __y, \
379   register long double __value;                                               \
380   register long double __exponent;                                            \
381   __extension__ long long int __p = (long long int) __y;                      \
382   if (__x == 0.0 && __y > 0.0)                                                \
383     return 0.0;                                                               \
384   if (__y == (double) __p)                                                    \
385     {                                                                         \
386       long double __r = 1.0;                                                  \
387       if (__p == 0)                                                           \
388         return 1.0;                                                           \
389       if (__p < 0)                                                            \
390         {                                                                     \
391           __p = -__p;                                                         \
392           __x = 1.0 / __x;                                                    \
393         }                                                                     \
394       while (1)                                                               \
395         {                                                                     \
396           if (__p & 1)                                                        \
397             __r *= __x;                                                       \
398           __p >>= 1;                                                          \
399           if (__p == 0)                                                       \
400             return __r;                                                       \
401           __x *= __x;                                                         \
402         }                                                                     \
403       /* NOTREACHED */                                                        \
404     }                                                                         \
405   __asm __volatile__                                                          \
406     ("fyl2x" : "=t" (__value) : "0" (__x), "u" (1.0) : "st(1)");              \
407   __asm __volatile__                                                          \
408     ("fmul      %%st(1)         # y * log2(x)\n\t"                            \
409      "fst       %%st(1)\n\t"                                                  \
410      "frndint                   # int(y * log2(x))\n\t"                       \
411      "fxch\n\t"                                                               \
412      "fsub      %%st(1)         # fract(y * log2(x))\n\t"                     \
413      "f2xm1                     # 2^(fract(y * log2(x))) - 1\n\t"             \
414      : "=t" (__value), "=u" (__exponent) : "0" (__y), "1" (__value));         \
415   __value += 1.0;                                                             \
416   __asm __volatile__                                                          \
417     ("fscale"                                                                 \
418      : "=t" (__value) : "0" (__value), "u" (__exponent));                     \
419   return __value)
420
421
422 __inline_mathop (sqrt, "fsqrt")
423 __inline_mathop_ (long double, __sqrtl, "fsqrt")
424
425 #if defined __GNUC__ && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 8)
426 __inline_mathcode_ (double, fabs, __x, return __builtin_fabs (__x))
427 __inline_mathcode_ (float, fabsf, __x, return __builtin_fabsf (__x))
428 __inline_mathcode_ (long double, fabsl, __x, return __builtin_fabsl (__x))
429 __inline_mathcode_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
430 #else
431 __inline_mathop (fabs, "fabs")
432 __inline_mathop_ (long double, __fabsl, "fabs")
433 #endif
434
435 /* The argument range of this inline version is reduced.  */
436 __inline_mathop (sin, "fsin")
437 /* The argument range of this inline version is reduced.  */
438 __inline_mathop (cos, "fcos")
439
440 __inline_mathop (atan, "fld1; fpatan")
441 __inline_mathop (log, "fldln2; fxch; fyl2x")
442 __inline_mathop (log10, "fldlg2; fxch; fyl2x")
443
444 __inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
445 __inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
446
447 __inline_mathcode_ (long double, __sgn1l, __x, return __x >= 0.0 ? 1.0 : -1.0)
448
449
450 /* The argument range of the inline version of sinhl is slightly reduced.  */
451 __inline_mathcode (sinh, __x, \
452   register long double __exm1 = __expm1l (__fabsl (__x));                     \
453   return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
454
455 __inline_mathcode (cosh, __x, \
456   register long double __ex = __expl (__x);                                   \
457   return 0.5 * (__ex + 1.0 / __ex))
458
459 __inline_mathcode (tanh, __x, \
460   register long double __exm1 = __expm1l (-__fabsl (__x + __x));              \
461   return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
462
463
464 __inline_mathcode (floor, __x, \
465   register long double __value;                                               \
466   __volatile unsigned short int __cw;                                         \
467   __volatile unsigned short int __cwtmp;                                      \
468   __asm __volatile ("fnstcw %0" : "=m" (__cw));                               \
469   __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */                     \
470   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                            \
471   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));                  \
472   __asm __volatile ("fldcw %0" : : "m" (__cw));                               \
473   return __value)
474
475 __inline_mathcode (ceil, __x, \
476   register long double __value;                                               \
477   __volatile unsigned short int __cw;                                         \
478   __volatile unsigned short int __cwtmp;                                      \
479   __asm __volatile ("fnstcw %0" : "=m" (__cw));                               \
480   __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */                       \
481   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                            \
482   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));                  \
483   __asm __volatile ("fldcw %0" : : "m" (__cw));                               \
484   return __value)
485
486 #define __ldexp_code \
487   register long double __value;                                               \
488   __asm __volatile__                                                          \
489     ("fscale"                                                                 \
490      : "=t" (__value) : "0" (__x), "u" ((long double) __y));                  \
491   return __value
492
493 __MATH_INLINE double ldexp (double __x, int __y);
494 __MATH_INLINE double
495 ldexp (double __x, int __y)
496 {
497   __ldexp_code;
498 }
499
500
501 /* Optimized versions for some non-standardized functions.  */
502 #if defined __USE_ISOC9X || defined __USE_MISC
503
504 __inline_mathcode (expm1, __x, __expm1_code)
505
506 /* We cannot rely on M_SQRT being defined.  So we do it for ourself
507    here.  */
508 # define __M_SQRT2      1.41421356237309504880L /* sqrt(2) */
509
510 __inline_mathcode (log1p, __x, \
511   register long double __value;                                               \
512   if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2)                                 \
513     __value = logl (1.0 + __x);                                               \
514   else                                                                        \
515     __asm __volatile__                                                        \
516       ("fldln2\n\t"                                                           \
517        "fxch\n\t"                                                             \
518        "fyl2xp1"                                                              \
519        : "=t" (__value) : "0" (__x));                                         \
520   return __value)
521
522
523 /* The argument range of the inline version of asinhl is slightly reduced.  */
524 __inline_mathcode (asinh, __x, \
525   register long double  __y = __fabsl (__x);                                  \
526   return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y)        \
527           * __sgn1l (__x)))
528
529 __inline_mathcode (acosh, __x, \
530   return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
531
532 __inline_mathcode (atanh, __x, \
533   register long double __y = __fabsl (__x);                                   \
534   return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
535
536 /* The argument range of the inline version of hypotl is slightly reduced.  */
537 __inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
538
539 __inline_mathcode(logb, __x, \
540   register long double __value;                                               \
541   register long double __junk;                                                \
542   __asm __volatile__                                                          \
543     ("fxtract\n\t"                                                            \
544      : "=t" (__junk), "=u" (__value) : "0" (__x));                            \
545   return __value)
546
547 #endif
548
549 #ifdef __USE_ISOC9X
550 __inline_mathop(log2, "fld1; fxch; fyl2x")
551
552 __MATH_INLINE float ldexpf (float __x, int __y);
553 __MATH_INLINE float
554 ldexpf (float __x, int __y)
555 {
556   __ldexp_code;
557 }
558
559 __MATH_INLINE long double ldexpl (long double __x, int __y);
560 __MATH_INLINE long double
561 ldexpl (long double __x, int __y)
562 {
563   __ldexp_code;
564 }
565
566 __inline_mathcode3 (fma, __x, __y, __z, return (__x * __y) + __z)
567
568 __inline_mathop(rint, "frndint")
569
570 #define __lrint_code \
571   long int __lrintres;                                                        \
572   __asm__ __volatile__                                                        \
573     ("fistpl %0"                                                              \
574      : "=m" (__lrintres) : "t" (__x) : "st");                                 \
575   return __lrintres
576 __MATH_INLINE long int
577 lrintf (float __x)
578 {
579   __lrint_code;
580 }
581 __MATH_INLINE long int
582 lrint (double __x)
583 {
584   __lrint_code;
585 }
586 __MATH_INLINE long int
587 lrintl (long double __x)
588 {
589   __lrint_code;
590 }
591 #undef __lrint_code
592
593 #define __llrint_code \
594   long long int __llrintres;                                                  \
595   __asm__ __volatile__                                                        \
596     ("fistpll %0"                                                             \
597      : "=m" (__llrintres) : "t" (__x) : "st");                                \
598   return __llrintres
599 __MATH_INLINE long long int
600 llrintf (float __x)
601 {
602   __llrint_code;
603 }
604 __MATH_INLINE long long int
605 llrint (double __x)
606 {
607   __llrint_code;
608 }
609 __MATH_INLINE long long int
610 llrintl (long double __x)
611 {
612   __llrint_code;
613 }
614 #undef __llrint_code
615
616 #endif
617
618
619 #ifdef __USE_MISC
620
621 __inline_mathcode2 (drem, __x, __y, \
622   register double __value;                                                    \
623   register int __clobbered;                                                   \
624   __asm __volatile__                                                          \
625     ("1:        fprem1\n\t"                                                   \
626      "fstsw     %%ax\n\t"                                                     \
627      "sahf\n\t"                                                               \
628      "jp        1b"                                                           \
629      : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc");    \
630   return __value)
631
632
633 /* This function is used in the `isfinite' macro.  */
634 __MATH_INLINE int __finite (double __x) __attribute__ ((__const__));
635 __MATH_INLINE int
636 __finite (double __x)
637 {
638   return (__extension__
639           (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
640              | 0x800fffff) + 1) >> 31));
641 }
642
643 /* Miscellaneous functions */
644
645 __inline_mathcode (__coshm1, __x, \
646   register long double __exm1 = __expm1l (__fabsl (__x));                     \
647   return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
648
649 __inline_mathcode (__acosh1p, __x, \
650   return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
651
652 #endif /* __USE_MISC  */
653
654 /* Undefine some of the large macros which are not used anymore.  */
655 #undef __expm1_code
656 #undef __exp_code
657 #undef __atan2_code
658 #undef __sincos_code
659
660 #endif /* __NO_MATH_INLINES  */
661
662
663 /* This code is used internally in the GNU libc.  */
664 #ifdef __LIBC_INTERNAL_MATH_INLINES
665 __inline_mathop (__ieee754_sqrt, "fsqrt")
666 __inline_mathcode2 (__ieee754_atan2, __y, __x,
667                     register long double __value;
668                     __asm __volatile__ ("fpatan\n\t"
669                                         : "=t" (__value)
670                                         : "0" (__x), "u" (__y) : "st(1)");
671                     return __value;)
672 #endif
673
674 #endif /* __GNUC__  */