Back to index

glibc  2.9
mathinline.h
Go to the documentation of this file.
00001 /* Inline math functions for i387.
00002    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2003,2004,2006,2007
00003    Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #ifndef _MATH_H
00023 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
00024 #endif
00025 
00026 #ifndef __extern_inline
00027 # define __MATH_INLINE __inline
00028 #else
00029 # define __MATH_INLINE __extern_inline
00030 #endif
00031 
00032 
00033 #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
00034 /* GCC 2.97 and up have builtins that actually can be used.  */
00035 # if !__GNUC_PREREQ (2,97)
00036 /* ISO C99 defines some macros to perform unordered comparisons.  The
00037    ix87 FPU supports this with special opcodes and we should use them.
00038    These must not be inline functions since we have to be able to handle
00039    all floating-point types.  */
00040 #  undef isgreater
00041 #  undef isgreaterequal
00042 #  undef isless
00043 #  undef islessequal
00044 #  undef islessgreater
00045 #  undef isunordered
00046 #  ifdef __i686__
00047 /* For the PentiumPro and more recent processors we can provide
00048    better code.  */
00049 #   define isgreater(x, y) \
00050      ({ register char __result;                                             \
00051        __asm__ ("fucomip %%st(1), %%st; seta %%al"                          \
00052                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
00053        __result; })
00054 #   define isgreaterequal(x, y) \
00055      ({ register char __result;                                             \
00056        __asm__ ("fucomip %%st(1), %%st; setae %%al"                         \
00057                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
00058        __result; })
00059 
00060 #   define isless(x, y) \
00061      ({ register char __result;                                             \
00062        __asm__ ("fucomip %%st(1), %%st; seta %%al"                          \
00063                : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
00064        __result; })
00065 
00066 #   define islessequal(x, y) \
00067      ({ register char __result;                                             \
00068        __asm__ ("fucomip %%st(1), %%st; setae %%al"                         \
00069                : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
00070        __result; })
00071 
00072 #   define islessgreater(x, y) \
00073      ({ register char __result;                                             \
00074        __asm__ ("fucomip %%st(1), %%st; setne %%al"                         \
00075                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
00076        __result; })
00077 
00078 #   define isunordered(x, y) \
00079      ({ register char __result;                                             \
00080        __asm__ ("fucomip %%st(1), %%st; setp %%al"                          \
00081                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
00082        __result; })
00083 #  else
00084 /* This is the dumb, portable code for i386 and above.  */
00085 #   define isgreater(x, y) \
00086      ({ register char __result;                                             \
00087        __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"             \
00088                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
00089        __result; })
00090 
00091 #   define isgreaterequal(x, y) \
00092      ({ register char __result;                                             \
00093        __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"             \
00094                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
00095        __result; })
00096 
00097 #   define isless(x, y) \
00098      ({ register char __result;                                             \
00099        __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"             \
00100                : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
00101        __result; })
00102 
00103 #   define islessequal(x, y) \
00104      ({ register char __result;                                             \
00105        __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"             \
00106                : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
00107        __result; })
00108 
00109 #   define islessgreater(x, y) \
00110      ({ register char __result;                                             \
00111        __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al"             \
00112                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
00113        __result; })
00114 
00115 #   define isunordered(x, y) \
00116      ({ register char __result;                                             \
00117        __asm__ ("fucompp; fnstsw; sahf; setp %%al"                          \
00118                : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
00119        __result; })
00120 #  endif /* __i686__ */
00121 # endif       /* GCC 2.97 */
00122 
00123 /* The gcc, version 2.7 or below, has problems with all this inlining
00124    code.  So disable it for this version of the compiler.  */
00125 # if __GNUC_PREREQ (2, 8)
00126 /* Test for negative number.  Used in the signbit() macro.  */
00127 __MATH_INLINE int
00128 __NTH (__signbitf (float __x))
00129 {
00130   __extension__ union { float __f; int __i; } __u = { __f: __x };
00131   return __u.__i < 0;
00132 }
00133 __MATH_INLINE int
00134 __NTH (__signbit (double __x))
00135 {
00136   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
00137   return __u.__i[1] < 0;
00138 }
00139 __MATH_INLINE int
00140 __NTH (__signbitl (long double __x))
00141 {
00142   __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
00143   return (__u.__i[2] & 0x8000) != 0;
00144 }
00145 # endif
00146 #endif
00147 
00148 
00149 /* The gcc, version 2.7 or below, has problems with all this inlining
00150    code.  So disable it for this version of the compiler.  */
00151 #if __GNUC_PREREQ (2, 8)
00152 
00153 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
00154      && defined __OPTIMIZE__)
00155 
00156 /* A macro to define float, double, and long double versions of various
00157    math functions for the ix87 FPU.  FUNC is the function name (which will
00158    be suffixed with f and l for the float and long double version,
00159    respectively).  OP is the name of the FPU operation.
00160    We define two sets of macros.  The set with the additional NP
00161    doesn't add a prototype declaration.  */
00162 
00163 #if defined __USE_MISC || defined __USE_ISOC99
00164 # define __inline_mathop(func, op) \
00165   __inline_mathop_ (double, func, op)                                       \
00166   __inline_mathop_ (float, __CONCAT(func,f), op)                     \
00167   __inline_mathop_ (long double, __CONCAT(func,l), op)
00168 # define __inline_mathopNP(func, op) \
00169   __inline_mathopNP_ (double, func, op)                                     \
00170   __inline_mathopNP_ (float, __CONCAT(func,f), op)                          \
00171   __inline_mathopNP_ (long double, __CONCAT(func,l), op)
00172 #else
00173 # define __inline_mathop(func, op) \
00174   __inline_mathop_ (double, func, op)
00175 # define __inline_mathopNP(func, op) \
00176   __inline_mathopNP_ (double, func, op)
00177 #endif
00178 
00179 #define __inline_mathop_(float_type, func, op) \
00180   __inline_mathop_decl_ (float_type, func, op, "0" (__x))
00181 #define __inline_mathopNP_(float_type, func, op) \
00182   __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
00183 
00184 
00185 #if defined __USE_MISC || defined __USE_ISOC99
00186 # define __inline_mathop_decl(func, op, params...) \
00187   __inline_mathop_decl_ (double, func, op, params)                          \
00188   __inline_mathop_decl_ (float, __CONCAT(func,f), op, params)               \
00189   __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
00190 # define __inline_mathop_declNP(func, op, params...) \
00191   __inline_mathop_declNP_ (double, func, op, params)                        \
00192   __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params)                    \
00193   __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
00194 #else
00195 # define __inline_mathop_decl(func, op, params...) \
00196   __inline_mathop_decl_ (double, func, op, params)
00197 # define __inline_mathop_declNP(func, op, params...) \
00198   __inline_mathop_declNP_ (double, func, op, params)
00199 #endif
00200 
00201 #define __inline_mathop_decl_(float_type, func, op, params...) \
00202   __MATH_INLINE float_type func (float_type) __THROW;                       \
00203   __inline_mathop_declNP_ (float_type, func, op, params)
00204 
00205 #define __inline_mathop_declNP_(float_type, func, op, params...) \
00206   __MATH_INLINE float_type __NTH (func (float_type __x))                    \
00207   {                                                                  \
00208     register float_type __result;                                    \
00209     __asm __volatile__ (op : "=t" (__result) : params);                     \
00210     return __result;                                                 \
00211   }
00212 
00213 
00214 #if defined __USE_MISC || defined __USE_ISOC99
00215 # define __inline_mathcode(func, arg, code) \
00216   __inline_mathcode_ (double, func, arg, code)                              \
00217   __inline_mathcode_ (float, __CONCAT(func,f), arg, code)                   \
00218   __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
00219 # define __inline_mathcodeNP(func, arg, code) \
00220   __inline_mathcodeNP_ (double, func, arg, code)                     \
00221   __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code)                 \
00222   __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
00223 # define __inline_mathcode2(func, arg1, arg2, code) \
00224   __inline_mathcode2_ (double, func, arg1, arg2, code)                      \
00225   __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code)           \
00226   __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
00227 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
00228   __inline_mathcodeNP2_ (double, func, arg1, arg2, code)                    \
00229   __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code)         \
00230   __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
00231 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
00232   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)                \
00233   __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)            \
00234   __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
00235 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
00236   __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)              \
00237   __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)     \
00238   __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
00239 #else
00240 # define __inline_mathcode(func, arg, code) \
00241   __inline_mathcode_ (double, func, (arg), code)
00242 # define __inline_mathcodeNP(func, arg, code) \
00243   __inline_mathcodeNP_ (double, func, (arg), code)
00244 # define __inline_mathcode2(func, arg1, arg2, code) \
00245   __inline_mathcode2_ (double, func, arg1, arg2, code)
00246 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
00247   __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
00248 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
00249   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
00250 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
00251   __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
00252 #endif
00253 
00254 #define __inline_mathcode_(float_type, func, arg, code) \
00255   __MATH_INLINE float_type func (float_type) __THROW;                       \
00256   __inline_mathcodeNP_(float_type, func, arg, code)
00257 
00258 #define __inline_mathcodeNP_(float_type, func, arg, code) \
00259   __MATH_INLINE float_type __NTH (func (float_type arg))                    \
00260   {                                                                  \
00261     code;                                                            \
00262   }
00263 
00264 
00265 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
00266   __MATH_INLINE float_type func (float_type, float_type) __THROW;           \
00267   __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
00268 
00269 #define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
00270   __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2))    \
00271   {                                                                  \
00272     code;                                                            \
00273   }
00274 
00275 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
00276   __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
00277   __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
00278 
00279 #define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
00280   __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2,     \
00281                                    float_type arg3))                 \
00282   {                                                                  \
00283     code;                                                            \
00284   }
00285 #endif
00286 
00287 
00288 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
00289 /* Miscellaneous functions */
00290 
00291 __inline_mathcode (__sgn, __x, \
00292   return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
00293 
00294 /* __FAST_MATH__ is defined by gcc -ffast-math.  */
00295 #ifdef __FAST_MATH__
00296 __inline_mathcode (__pow2, __x, \
00297   register long double __value;                                             \
00298   register long double __exponent;                                   \
00299   __extension__ long long int __p = (long long int) __x;                    \
00300   if (__x == (long double) __p)                                             \
00301     {                                                                \
00302       __asm __volatile__                                             \
00303        ("fscale"                                                     \
00304         : "=t" (__value) : "0" (1.0), "u" (__x));                           \
00305       return __value;                                                       \
00306     }                                                                \
00307   __asm __volatile__                                                 \
00308     ("fld     %%st(0)\n\t"                                           \
00309      "frndint               # int(x)\n\t"                            \
00310      "fxch\n\t"                                                             \
00311      "fsub    %%st(1)              # fract(x)\n\t"                                 \
00312      "f2xm1                 # 2^(fract(x)) - 1\n\t"                         \
00313      : "=t" (__value), "=u" (__exponent) : "0" (__x));                      \
00314   __value += 1.0;                                                    \
00315   __asm __volatile__                                                 \
00316     ("fscale"                                                        \
00317      : "=t" (__value) : "0" (__value), "u" (__exponent));                   \
00318   return __value)
00319 
00320 # ifdef __USE_GNU
00321 #  define __sincos_code \
00322   register long double __cosr;                                              \
00323   register long double __sinr;                                              \
00324   __asm __volatile__                                                 \
00325     ("fsincos\n\t"                                                   \
00326      "fnstsw  %%ax\n\t"                                              \
00327      "testl   $0x400, %%eax\n\t"                                     \
00328      "jz      1f\n\t"                                                       \
00329      "fldpi\n\t"                                                     \
00330      "fadd    %%st(0)\n\t"                                           \
00331      "fxch    %%st(1)\n\t"                                           \
00332      "2: fprem1\n\t"                                                 \
00333      "fnstsw  %%ax\n\t"                                              \
00334      "testl   $0x400, %%eax\n\t"                                     \
00335      "jnz     2b\n\t"                                                       \
00336      "fstp    %%st(1)\n\t"                                           \
00337      "fsincos\n\t"                                                   \
00338      "1:"                                                            \
00339      : "=t" (__cosr), "=u" (__sinr) : "0" (__x));                           \
00340   *__sinx = __sinr;                                                  \
00341   *__cosx = __cosr
00342 
00343 __MATH_INLINE void
00344 __NTH (__sincos (double __x, double *__sinx, double *__cosx))
00345 {
00346   __sincos_code;
00347 }
00348 
00349 __MATH_INLINE void
00350 __NTH (__sincosf (float __x, float *__sinx, float *__cosx))
00351 {
00352   __sincos_code;
00353 }
00354 
00355 __MATH_INLINE void
00356 __NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
00357 {
00358   __sincos_code;
00359 }
00360 # endif
00361 
00362 
00363 /* Optimized inline implementation, sometimes with reduced precision
00364    and/or argument range.  */
00365 
00366 # if __GNUC_PREREQ (3, 5)
00367 #  define __expm1_code \
00368   register long double __temp;                                              \
00369   __temp = __builtin_expm1l (__x);                                   \
00370   return __temp ? __temp : __x
00371 # else
00372 #  define __expm1_code \
00373   register long double __value;                                             \
00374   register long double __exponent;                                   \
00375   register long double __temp;                                              \
00376   __asm __volatile__                                                 \
00377     ("fldl2e                # e^x - 1 = 2^(x * log2(e)) - 1\n\t"            \
00378      "fmul    %%st(1)              # x * log2(e)\n\t"                       \
00379      "fst     %%st(1)\n\t"                                           \
00380      "frndint               # int(x * log2(e))\n\t"                         \
00381      "fxch\n\t"                                                             \
00382      "fsub    %%st(1)              # fract(x * log2(e))\n\t"                \
00383      "f2xm1                 # 2^(fract(x * log2(e))) - 1\n\t"        \
00384      "fscale                # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
00385      : "=t" (__value), "=u" (__exponent) : "0" (__x));                      \
00386   __asm __volatile__                                                 \
00387     ("fscale                # 2^int(x * log2(e))\n\t"                \
00388      : "=t" (__temp) : "0" (1.0), "u" (__exponent));                        \
00389   __temp -= 1.0;                                                     \
00390   __temp += __value;                                                 \
00391   return __temp ? __temp : __x
00392 # endif
00393 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
00394 
00395 # if __GNUC_PREREQ (3, 4)
00396 __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
00397 # else
00398 #  define __exp_code \
00399   register long double __value;                                             \
00400   register long double __exponent;                                   \
00401   __asm __volatile__                                                 \
00402     ("fldl2e                # e^x = 2^(x * log2(e))\n\t"                    \
00403      "fmul    %%st(1)              # x * log2(e)\n\t"                       \
00404      "fst     %%st(1)\n\t"                                           \
00405      "frndint               # int(x * log2(e))\n\t"                         \
00406      "fxch\n\t"                                                             \
00407      "fsub    %%st(1)              # fract(x * log2(e))\n\t"                \
00408      "f2xm1                 # 2^(fract(x * log2(e))) - 1\n\t"        \
00409      : "=t" (__value), "=u" (__exponent) : "0" (__x));                      \
00410   __value += 1.0;                                                    \
00411   __asm __volatile__                                                 \
00412     ("fscale"                                                        \
00413      : "=t" (__value) : "0" (__value), "u" (__exponent));                   \
00414   return __value
00415 __inline_mathcodeNP (exp, __x, __exp_code)
00416 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
00417 # endif
00418 
00419 
00420 # if !__GNUC_PREREQ (3, 5)
00421 __inline_mathcodeNP (tan, __x, \
00422   register long double __value;                                             \
00423   register long double __value2 __attribute__ ((__unused__));               \
00424   __asm __volatile__                                                 \
00425     ("fptan"                                                         \
00426      : "=t" (__value2), "=u" (__value) : "0" (__x));                        \
00427   return __value)
00428 # endif
00429 #endif /* __FAST_MATH__ */
00430 
00431 
00432 #if __GNUC_PREREQ (3, 4)
00433 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
00434                      return __builtin_atan2l (__y, __x))
00435 #else
00436 # define __atan2_code \
00437   register long double __value;                                             \
00438   __asm __volatile__                                                 \
00439     ("fpatan"                                                        \
00440      : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)");                    \
00441   return __value
00442 # ifdef __FAST_MATH__
00443 __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
00444 # endif
00445 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
00446 #endif
00447 
00448 
00449 #if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
00450 __inline_mathcodeNP2 (fmod, __x, __y, \
00451   register long double __value;                                             \
00452   __asm __volatile__                                                 \
00453     ("1:      fprem\n\t"                                             \
00454      "fnstsw  %%ax\n\t"                                              \
00455      "sahf\n\t"                                                             \
00456      "jp      1b"                                                    \
00457      : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");                 \
00458   return __value)
00459 #endif
00460 
00461 
00462 #ifdef __FAST_MATH__
00463 # if !__GNUC_PREREQ (3,3)
00464 __inline_mathopNP (sqrt, "fsqrt")
00465 __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
00466 #  define __libc_sqrtl(n) __sqrtl (n)
00467 # else
00468 #  define __libc_sqrtl(n) __builtin_sqrtl (n)
00469 # endif
00470 #endif
00471 
00472 #if __GNUC_PREREQ (2, 8)
00473 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
00474 # if defined __USE_MISC || defined __USE_ISOC99
00475 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
00476 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
00477 # endif
00478 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
00479 #else
00480 __inline_mathop (fabs, "fabs")
00481 __inline_mathop_ (long double, __fabsl, "fabs")
00482 #endif
00483 
00484 #ifdef __FAST_MATH__
00485 # if !__GNUC_PREREQ (3, 4)
00486 /* The argument range of this inline version is reduced.  */
00487 __inline_mathopNP (sin, "fsin")
00488 /* The argument range of this inline version is reduced.  */
00489 __inline_mathopNP (cos, "fcos")
00490 
00491 __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
00492 # endif
00493 
00494 # if !__GNUC_PREREQ (3, 5)
00495 __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
00496 
00497 __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
00498 __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
00499 # endif
00500 
00501 # if !__GNUC_PREREQ (3, 4)
00502 __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
00503 # endif
00504 #endif /* __FAST_MATH__ */
00505 
00506 __inline_mathcode_ (long double, __sgn1l, __x, \
00507   __extension__ union { long double __xld; unsigned int __xi[3]; } __n =      \
00508     { __xld: __x };                                                  \
00509   __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff;                     \
00510   __n.__xi[1] = 0x80000000;                                          \
00511   __n.__xi[0] = 0;                                                   \
00512   return __n.__xld)
00513 
00514 
00515 #ifdef __FAST_MATH__
00516 /* The argument range of the inline version of sinhl is slightly reduced.  */
00517 __inline_mathcodeNP (sinh, __x, \
00518   register long double __exm1 = __expm1l (__fabsl (__x));                   \
00519   return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
00520 
00521 __inline_mathcodeNP (cosh, __x, \
00522   register long double __ex = __expl (__x);                                 \
00523   return 0.5 * (__ex + 1.0 / __ex))
00524 
00525 __inline_mathcodeNP (tanh, __x, \
00526   register long double __exm1 = __expm1l (-__fabsl (__x + __x));            \
00527   return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
00528 #endif
00529 
00530 __inline_mathcodeNP (floor, __x, \
00531   register long double __value;                                             \
00532   register int __ignore;                                             \
00533   unsigned short int __cw;                                           \
00534   unsigned short int __cwtmp;                                               \
00535   __asm __volatile ("fnstcw %3\n\t"                                         \
00536                   "movzwl %3, %1\n\t"                                       \
00537                   "andl $0xf3ff, %1\n\t"                             \
00538                   "orl $0x0400, %1\n\t"   /* rounding down */        \
00539                   "movw %w1, %2\n\t"                                        \
00540                   "fldcw %2\n\t"                                     \
00541                   "frndint\n\t"                                      \
00542                   "fldcw %3"                                                \
00543                   : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp),       \
00544                     "=m" (__cw)                                      \
00545                   : "0" (__x));                                      \
00546   return __value)
00547 
00548 __inline_mathcodeNP (ceil, __x, \
00549   register long double __value;                                             \
00550   register int __ignore;                                             \
00551   unsigned short int __cw;                                           \
00552   unsigned short int __cwtmp;                                               \
00553   __asm __volatile ("fnstcw %3\n\t"                                         \
00554                   "movzwl %3, %1\n\t"                                       \
00555                   "andl $0xf3ff, %1\n\t"                             \
00556                   "orl $0x0800, %1\n\t"   /* rounding up */          \
00557                   "movw %w1, %2\n\t"                                        \
00558                   "fldcw %2\n\t"                                     \
00559                   "frndint\n\t"                                      \
00560                   "fldcw %3"                                                \
00561                   : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp),       \
00562                     "=m" (__cw)                                      \
00563                   : "0" (__x));                                      \
00564   return __value)
00565 
00566 #ifdef __FAST_MATH__
00567 # define __ldexp_code \
00568   register long double __value;                                             \
00569   __asm __volatile__                                                 \
00570     ("fscale"                                                        \
00571      : "=t" (__value) : "0" (__x), "u" ((long double) __y));                \
00572   return __value
00573 
00574 __MATH_INLINE double
00575 __NTH (ldexp (double __x, int __y))
00576 {
00577   __ldexp_code;
00578 }
00579 #endif
00580 
00581 
00582 /* Optimized versions for some non-standardized functions.  */
00583 #if defined __USE_ISOC99 || defined __USE_MISC
00584 
00585 # ifdef __FAST_MATH__
00586 __inline_mathcodeNP (expm1, __x, __expm1_code)
00587 
00588 /* We cannot rely on M_SQRT being defined.  So we do it for ourself
00589    here.  */
00590 #  define __M_SQRT2  1.41421356237309504880L     /* sqrt(2) */
00591 
00592 #  if !__GNUC_PREREQ (3, 5)
00593 __inline_mathcodeNP (log1p, __x, \
00594   register long double __value;                                             \
00595   if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2)                               \
00596     __value = logl (1.0 + __x);                                             \
00597   else                                                               \
00598     __asm __volatile__                                                      \
00599       ("fldln2\n\t"                                                  \
00600        "fxch\n\t"                                                    \
00601        "fyl2xp1"                                                     \
00602        : "=t" (__value) : "0" (__x) : "st(1)");                             \
00603   return __value)
00604 #  endif
00605 
00606 
00607 /* The argument range of the inline version of asinhl is slightly reduced.  */
00608 __inline_mathcodeNP (asinh, __x, \
00609   register long double  __y = __fabsl (__x);                                \
00610   return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y)   \
00611          * __sgn1l (__x)))
00612 
00613 __inline_mathcodeNP (acosh, __x, \
00614   return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
00615 
00616 __inline_mathcodeNP (atanh, __x, \
00617   register long double __y = __fabsl (__x);                                 \
00618   return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
00619 
00620 /* The argument range of the inline version of hypotl is slightly reduced.  */
00621 __inline_mathcodeNP2 (hypot, __x, __y,
00622                     return __libc_sqrtl (__x * __x + __y * __y))
00623 
00624 #  if !__GNUC_PREREQ (3, 5)
00625 __inline_mathcodeNP(logb, __x, \
00626   register long double __value;                                             \
00627   register long double __junk;                                              \
00628   __asm __volatile__                                                 \
00629     ("fxtract\n\t"                                                   \
00630      : "=t" (__junk), "=u" (__value) : "0" (__x));                          \
00631   return __value)
00632 #  endif
00633 
00634 # endif
00635 #endif
00636 
00637 #ifdef __USE_ISOC99
00638 # ifdef __FAST_MATH__
00639 
00640 #  if !__GNUC_PREREQ (3, 5)
00641 __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
00642 #  endif
00643 
00644 __MATH_INLINE float
00645 __NTH (ldexpf (float __x, int __y))
00646 {
00647   __ldexp_code;
00648 }
00649 
00650 __MATH_INLINE long double
00651 __NTH (ldexpl (long double __x, int __y))
00652 {
00653   __ldexp_code;
00654 }
00655 
00656 __inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z)
00657 
00658 __inline_mathopNP (rint, "frndint")
00659 # endif /* __FAST_MATH__ */
00660 
00661 # define __lrint_code \
00662   long int __lrintres;                                                      \
00663   __asm__ __volatile__                                                      \
00664     ("fistpl %0"                                                     \
00665      : "=m" (__lrintres) : "t" (__x) : "st");                               \
00666   return __lrintres
00667 __MATH_INLINE long int
00668 __NTH (lrintf (float __x))
00669 {
00670   __lrint_code;
00671 }
00672 __MATH_INLINE long int
00673 __NTH (lrint (double __x))
00674 {
00675   __lrint_code;
00676 }
00677 __MATH_INLINE long int
00678 __NTH (lrintl (long double __x))
00679 {
00680   __lrint_code;
00681 }
00682 # undef __lrint_code
00683 
00684 # define __llrint_code \
00685   long long int __llrintres;                                                \
00686   __asm__ __volatile__                                                      \
00687     ("fistpll %0"                                                    \
00688      : "=m" (__llrintres) : "t" (__x) : "st");                              \
00689   return __llrintres
00690 __MATH_INLINE long long int
00691 __NTH (llrintf (float __x))
00692 {
00693   __llrint_code;
00694 }
00695 __MATH_INLINE long long int
00696 __NTH (llrint (double __x))
00697 {
00698   __llrint_code;
00699 }
00700 __MATH_INLINE long long int
00701 __NTH (llrintl (long double __x))
00702 {
00703   __llrint_code;
00704 }
00705 # undef __llrint_code
00706 
00707 #endif
00708 
00709 
00710 #ifdef __USE_MISC
00711 
00712 # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
00713 __inline_mathcodeNP2 (drem, __x, __y, \
00714   register double __value;                                           \
00715   register int __clobbered;                                          \
00716   __asm __volatile__                                                 \
00717     ("1:      fprem1\n\t"                                            \
00718      "fstsw   %%ax\n\t"                                              \
00719      "sahf\n\t"                                                             \
00720      "jp      1b"                                                    \
00721      : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc");    \
00722   return __value)
00723 # endif
00724 
00725 
00726 /* This function is used in the `isfinite' macro.  */
00727 __MATH_INLINE int
00728 __NTH (__finite (double __x))
00729 {
00730   return (__extension__
00731          (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
00732             | 0x800fffffu) + 1) >> 31));
00733 }
00734 
00735 /* Miscellaneous functions */
00736 # ifdef __FAST_MATH__
00737 __inline_mathcode (__coshm1, __x, \
00738   register long double __exm1 = __expm1l (__fabsl (__x));                   \
00739   return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
00740 
00741 __inline_mathcode (__acosh1p, __x, \
00742   return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0)))
00743 
00744 # endif /* __FAST_MATH__ */
00745 #endif /* __USE_MISC  */
00746 
00747 /* Undefine some of the large macros which are not used anymore.  */
00748 #undef __atan2_code
00749 #ifdef __FAST_MATH__
00750 # undef __expm1_code
00751 # undef __exp_code
00752 # undef __sincos_code
00753 #endif /* __FAST_MATH__ */
00754 
00755 #endif /* __NO_MATH_INLINES  */
00756 
00757 
00758 /* This code is used internally in the GNU libc.  */
00759 #ifdef __LIBC_INTERNAL_MATH_INLINES
00760 __inline_mathop (__ieee754_sqrt, "fsqrt")
00761 __inline_mathcode2 (__ieee754_atan2, __y, __x,
00762                   register long double __value;
00763                   __asm __volatile__ ("fpatan\n\t"
00764                                    : "=t" (__value)
00765                                    : "0" (__x), "u" (__y) : "st(1)");
00766                   return __value;)
00767 #endif
00768 
00769 #endif /* __GNUC__  */