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