Blame sysdeps/x86/fpu/bits/mathinline.h

Packit 6c4009
/* Inline math functions for i387 and SSE.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef _MATH_H
Packit 6c4009
# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef __extern_always_inline
Packit 6c4009
# define __MATH_INLINE __inline
Packit 6c4009
#else
Packit 6c4009
# define __MATH_INLINE __extern_always_inline
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Disable x87 inlines when -fpmath=sse is passed and also when we're building
Packit 6c4009
   on x86_64.  Older gcc (gcc-3.2 for example) does not define __SSE2_MATH__
Packit 6c4009
   for x86_64.  */
Packit 6c4009
#if !defined __SSE2_MATH__ && !defined __x86_64__
Packit 6c4009
# if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
Packit 6c4009
     && defined __OPTIMIZE__)
Packit 6c4009
Packit 6c4009
/* The inline functions do not set errno or raise necessarily the
Packit 6c4009
   correct exceptions.  */
Packit 6c4009
#  undef math_errhandling
Packit 6c4009
Packit 6c4009
/* A macro to define float, double, and long double versions of various
Packit 6c4009
   math functions for the ix87 FPU.  FUNC is the function name (which will
Packit 6c4009
   be suffixed with f and l for the float and long double version,
Packit 6c4009
   respectively).  OP is the name of the FPU operation.
Packit 6c4009
   We define two sets of macros.  The set with the additional NP
Packit 6c4009
   doesn't add a prototype declaration.  */
Packit 6c4009
Packit 6c4009
#  ifdef __USE_ISOC99
Packit 6c4009
#   define __inline_mathop(func, op) \
Packit 6c4009
  __inline_mathop_ (double, func, op)					      \
Packit 6c4009
  __inline_mathop_ (float, __CONCAT(func,f), op)			      \
Packit 6c4009
  __inline_mathop_ (long double, __CONCAT(func,l), op)
Packit 6c4009
#   define __inline_mathopNP(func, op) \
Packit 6c4009
  __inline_mathopNP_ (double, func, op)					      \
Packit 6c4009
  __inline_mathopNP_ (float, __CONCAT(func,f), op)			      \
Packit 6c4009
  __inline_mathopNP_ (long double, __CONCAT(func,l), op)
Packit 6c4009
#  else
Packit 6c4009
#   define __inline_mathop(func, op) \
Packit 6c4009
  __inline_mathop_ (double, func, op)
Packit 6c4009
#   define __inline_mathopNP(func, op) \
Packit 6c4009
  __inline_mathopNP_ (double, func, op)
Packit 6c4009
#  endif
Packit 6c4009
Packit 6c4009
#  define __inline_mathop_(float_type, func, op) \
Packit 6c4009
  __inline_mathop_decl_ (float_type, func, op, "0" (__x))
Packit 6c4009
#  define __inline_mathopNP_(float_type, func, op) \
Packit 6c4009
  __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
Packit 6c4009
Packit 6c4009
Packit 6c4009
#  ifdef __USE_ISOC99
Packit 6c4009
#   define __inline_mathop_decl(func, op, params...) \
Packit 6c4009
  __inline_mathop_decl_ (double, func, op, params)			      \
Packit 6c4009
  __inline_mathop_decl_ (float, __CONCAT(func,f), op, params)		      \
Packit 6c4009
  __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
Packit 6c4009
#   define __inline_mathop_declNP(func, op, params...) \
Packit 6c4009
  __inline_mathop_declNP_ (double, func, op, params)			      \
Packit 6c4009
  __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params)		      \
Packit 6c4009
  __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
Packit 6c4009
#  else
Packit 6c4009
#   define __inline_mathop_decl(func, op, params...) \
Packit 6c4009
  __inline_mathop_decl_ (double, func, op, params)
Packit 6c4009
#   define __inline_mathop_declNP(func, op, params...) \
Packit 6c4009
  __inline_mathop_declNP_ (double, func, op, params)
Packit 6c4009
#  endif
Packit 6c4009
Packit 6c4009
#  define __inline_mathop_decl_(float_type, func, op, params...) \
Packit 6c4009
  __MATH_INLINE float_type func (float_type) __THROW;			      \
Packit 6c4009
  __inline_mathop_declNP_ (float_type, func, op, params)
Packit 6c4009
Packit 6c4009
#  define __inline_mathop_declNP_(float_type, func, op, params...) \
Packit 6c4009
  __MATH_INLINE float_type __NTH (func (float_type __x))		      \
Packit 6c4009
  {									      \
Packit 6c4009
    register float_type __result;					      \
Packit 6c4009
    __asm __volatile__ (op : "=t" (__result) : params);			      \
Packit 6c4009
    return __result;							      \
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
Packit 6c4009
#  ifdef __USE_ISOC99
Packit 6c4009
#   define __inline_mathcode(func, arg, code) \
Packit 6c4009
  __inline_mathcode_ (double, func, arg, code)				      \
Packit 6c4009
  __inline_mathcode_ (float, __CONCAT(func,f), arg, code)		      \
Packit 6c4009
  __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
Packit 6c4009
#   define __inline_mathcodeNP(func, arg, code) \
Packit 6c4009
  __inline_mathcodeNP_ (double, func, arg, code)			      \
Packit 6c4009
  __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code)		      \
Packit 6c4009
  __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
Packit 6c4009
#   define __inline_mathcode2(func, arg1, arg2, code) \
Packit 6c4009
  __inline_mathcode2_ (double, func, arg1, arg2, code)			      \
Packit 6c4009
  __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code)	      \
Packit 6c4009
  __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
Packit 6c4009
#   define __inline_mathcodeNP2(func, arg1, arg2, code) \
Packit 6c4009
  __inline_mathcodeNP2_ (double, func, arg1, arg2, code)		      \
Packit 6c4009
  __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code)	      \
Packit 6c4009
  __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
Packit 6c4009
#   define __inline_mathcode3(func, arg1, arg2, arg3, code) \
Packit 6c4009
  __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)		      \
Packit 6c4009
  __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)	      \
Packit 6c4009
  __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
Packit 6c4009
#   define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
Packit 6c4009
  __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)		      \
Packit 6c4009
  __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)     \
Packit 6c4009
  __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
Packit 6c4009
#  else
Packit 6c4009
#   define __inline_mathcode(func, arg, code) \
Packit 6c4009
  __inline_mathcode_ (double, func, (arg), code)
Packit 6c4009
#   define __inline_mathcodeNP(func, arg, code) \
Packit 6c4009
  __inline_mathcodeNP_ (double, func, (arg), code)
Packit 6c4009
#   define __inline_mathcode2(func, arg1, arg2, code) \
Packit 6c4009
  __inline_mathcode2_ (double, func, arg1, arg2, code)
Packit 6c4009
#   define __inline_mathcodeNP2(func, arg1, arg2, code) \
Packit 6c4009
  __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
Packit 6c4009
#   define __inline_mathcode3(func, arg1, arg2, arg3, code) \
Packit 6c4009
  __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
Packit 6c4009
#   define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
Packit 6c4009
  __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
Packit 6c4009
#  endif
Packit 6c4009
Packit 6c4009
#  define __inline_mathcode_(float_type, func, arg, code) \
Packit 6c4009
  __MATH_INLINE float_type func (float_type) __THROW;			      \
Packit 6c4009
  __inline_mathcodeNP_(float_type, func, arg, code)
Packit 6c4009
Packit 6c4009
#  define __inline_mathcodeNP_(float_type, func, arg, code) \
Packit 6c4009
  __MATH_INLINE float_type __NTH (func (float_type arg))		      \
Packit 6c4009
  {									      \
Packit 6c4009
    code;								      \
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
Packit 6c4009
#  define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
Packit 6c4009
  __MATH_INLINE float_type func (float_type, float_type) __THROW;	      \
Packit 6c4009
  __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
Packit 6c4009
Packit 6c4009
#  define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
Packit 6c4009
  __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2))    \
Packit 6c4009
  {									      \
Packit 6c4009
    code;								      \
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
#  define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
Packit 6c4009
  __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
Packit 6c4009
  __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
Packit 6c4009
Packit 6c4009
#  define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
Packit 6c4009
  __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2,     \
Packit 6c4009
					float_type arg3))		      \
Packit 6c4009
  {									      \
Packit 6c4009
    code;								      \
Packit 6c4009
  }
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
# if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
Packit 6c4009
/* Miscellaneous functions  */
Packit 6c4009
Packit 6c4009
/* __FAST_MATH__ is defined by gcc -ffast-math.  */
Packit 6c4009
#  ifdef __FAST_MATH__
Packit 6c4009
/* Optimized inline implementation, sometimes with reduced precision
Packit 6c4009
   and/or argument range.  */
Packit 6c4009
Packit 6c4009
#   if __GNUC_PREREQ (3, 5)
Packit 6c4009
#    define __expm1_code \
Packit 6c4009
  register long double __temp;						      \
Packit 6c4009
  __temp = __builtin_expm1l (__x);					      \
Packit 6c4009
  return __temp ? __temp : __x
Packit 6c4009
#   else
Packit 6c4009
#    define __expm1_code \
Packit 6c4009
  register long double __value;						      \
Packit 6c4009
  register long double __exponent;					      \
Packit 6c4009
  register long double __temp;						      \
Packit 6c4009
  __asm __volatile__							      \
Packit 6c4009
    ("fldl2e			# e^x - 1 = 2^(x * log2(e)) - 1\n\t"	      \
Packit 6c4009
     "fmul	%%st(1)		# x * log2(e)\n\t"			      \
Packit 6c4009
     "fst	%%st(1)\n\t"						      \
Packit 6c4009
     "frndint			# int(x * log2(e))\n\t"			      \
Packit 6c4009
     "fxch\n\t"								      \
Packit 6c4009
     "fsub	%%st(1)		# fract(x * log2(e))\n\t"		      \
Packit 6c4009
     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"	      \
Packit 6c4009
     "fscale			# 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
Packit 6c4009
     : "=t" (__value), "=u" (__exponent) : "0" (__x));			      \
Packit 6c4009
  __asm __volatile__							      \
Packit 6c4009
    ("fscale			# 2^int(x * log2(e))\n\t"		      \
Packit 6c4009
     : "=t" (__temp) : "0" (1.0), "u" (__exponent));			      \
Packit 6c4009
  __temp -= 1.0;							      \
Packit 6c4009
  __temp += __value;							      \
Packit 6c4009
  return __temp ? __temp : __x
Packit 6c4009
#   endif
Packit 6c4009
__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
Packit 6c4009
Packit 6c4009
#   if __GNUC_PREREQ (3, 4)
Packit 6c4009
__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
Packit 6c4009
#   else
Packit 6c4009
#    define __exp_code \
Packit 6c4009
  register long double __value;						      \
Packit 6c4009
  register long double __exponent;					      \
Packit 6c4009
  __asm __volatile__							      \
Packit 6c4009
    ("fldl2e			# e^x = 2^(x * log2(e))\n\t"		      \
Packit 6c4009
     "fmul	%%st(1)		# x * log2(e)\n\t"			      \
Packit 6c4009
     "fst	%%st(1)\n\t"						      \
Packit 6c4009
     "frndint			# int(x * log2(e))\n\t"			      \
Packit 6c4009
     "fxch\n\t"								      \
Packit 6c4009
     "fsub	%%st(1)		# fract(x * log2(e))\n\t"		      \
Packit 6c4009
     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"	      \
Packit 6c4009
     : "=t" (__value), "=u" (__exponent) : "0" (__x));			      \
Packit 6c4009
  __value += 1.0;							      \
Packit 6c4009
  __asm __volatile__							      \
Packit 6c4009
    ("fscale"								      \
Packit 6c4009
     : "=t" (__value) : "0" (__value), "u" (__exponent));		      \
Packit 6c4009
  return __value
Packit 6c4009
__inline_mathcodeNP (exp, __x, __exp_code)
Packit 6c4009
__inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
Packit 6c4009
#   endif
Packit 6c4009
#  endif /* __FAST_MATH__ */
Packit 6c4009
Packit 6c4009
Packit 6c4009
#  ifdef __FAST_MATH__
Packit 6c4009
#   if !__GNUC_PREREQ (3,3)
Packit 6c4009
__inline_mathopNP (sqrt, "fsqrt")
Packit 6c4009
__inline_mathopNP_ (long double, __sqrtl, "fsqrt")
Packit 6c4009
#    define __libc_sqrtl(n) __sqrtl (n)
Packit 6c4009
#   else
Packit 6c4009
#    define __libc_sqrtl(n) __builtin_sqrtl (n)
Packit 6c4009
#   endif
Packit 6c4009
#  endif
Packit 6c4009
Packit 6c4009
#  if __GNUC_PREREQ (2, 8)
Packit 6c4009
__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
Packit 6c4009
#   ifdef __USE_ISOC99
Packit 6c4009
__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
Packit 6c4009
__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
Packit 6c4009
#   endif
Packit 6c4009
__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
Packit 6c4009
#  else
Packit 6c4009
__inline_mathop (fabs, "fabs")
Packit 6c4009
__inline_mathop_ (long double, __fabsl, "fabs")
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
__inline_mathcode_ (long double, __sgn1l, __x, \
Packit 6c4009
  __extension__ union { long double __xld; unsigned int __xi[3]; } __n =      \
Packit 6c4009
    { __xld: __x };							      \
Packit 6c4009
  __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff;			      \
Packit 6c4009
  __n.__xi[1] = 0x80000000;						      \
Packit 6c4009
  __n.__xi[0] = 0;							      \
Packit 6c4009
  return __n.__xld)
Packit 6c4009
Packit 6c4009
Packit 6c4009
#  ifdef __FAST_MATH__
Packit 6c4009
/* The argument range of the inline version of sinhl is slightly reduced.  */
Packit 6c4009
__inline_mathcodeNP (sinh, __x, \
Packit 6c4009
  register long double __exm1 = __expm1l (__fabsl (__x));		      \
Packit 6c4009
  return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
Packit 6c4009
Packit 6c4009
__inline_mathcodeNP (cosh, __x, \
Packit 6c4009
  register long double __ex = __expl (__x);				      \
Packit 6c4009
  return 0.5 * (__ex + 1.0 / __ex))
Packit 6c4009
Packit 6c4009
__inline_mathcodeNP (tanh, __x, \
Packit 6c4009
  register long double __exm1 = __expm1l (-__fabsl (__x + __x));	      \
Packit 6c4009
  return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
Packit 6c4009
#  endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Optimized versions for some non-standardized functions.  */
Packit 6c4009
#  ifdef __USE_ISOC99
Packit 6c4009
Packit 6c4009
#   ifdef __FAST_MATH__
Packit 6c4009
__inline_mathcodeNP (expm1, __x, __expm1_code)
Packit 6c4009
Packit 6c4009
/* The argument range of the inline version of asinhl is slightly reduced.  */
Packit 6c4009
__inline_mathcodeNP (asinh, __x, \
Packit 6c4009
  register long double  __y = __fabsl (__x);				      \
Packit 6c4009
  return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y)   \
Packit 6c4009
	  * __sgn1l (__x)))
Packit 6c4009
Packit 6c4009
__inline_mathcodeNP (acosh, __x, \
Packit 6c4009
  return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
Packit 6c4009
Packit 6c4009
__inline_mathcodeNP (atanh, __x, \
Packit 6c4009
  register long double __y = __fabsl (__x);				      \
Packit 6c4009
  return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
Packit 6c4009
Packit 6c4009
/* The argument range of the inline version of hypotl is slightly reduced.  */
Packit 6c4009
__inline_mathcodeNP2 (hypot, __x, __y,
Packit 6c4009
		      return __libc_sqrtl (__x * __x + __y * __y))
Packit 6c4009
Packit 6c4009
#   endif
Packit 6c4009
#  endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Undefine some of the large macros which are not used anymore.  */
Packit 6c4009
#  ifdef __FAST_MATH__
Packit 6c4009
#   undef __expm1_code
Packit 6c4009
#   undef __exp_code
Packit 6c4009
#  endif /* __FAST_MATH__ */
Packit 6c4009
Packit 6c4009
# endif /* __NO_MATH_INLINES  */
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* This code is used internally in the GNU libc.  */
Packit 6c4009
# ifdef __LIBC_INTERNAL_MATH_INLINES
Packit 6c4009
__inline_mathcode2_ (long double, __ieee754_atan2l, __y, __x,
Packit 6c4009
		     register long double __value;
Packit 6c4009
		     __asm __volatile__ ("fpatan\n\t"
Packit 6c4009
					 : "=t" (__value)
Packit 6c4009
					 : "0" (__x), "u" (__y) : "st(1)");
Packit 6c4009
		     return __value;)
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
#endif /* !__SSE2_MATH__ && !__x86_64__ */