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