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