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