1/* Inline math functions for x86-64. 2 Copyright (C) 2002-2004, 2007, 2009, 2011 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, write to the Free 17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA. */ 19 20#ifndef _MATH_H 21# error "Never use <bits/mathinline.h> directly; include <math.h> instead." 22#endif 23 24#include <bits/wordsize.h> 25 26#ifndef __extern_always_inline 27# define __MATH_INLINE __inline 28#else 29# define __MATH_INLINE __extern_always_inline 30#endif 31 32 33/* The gcc, version 2.7 or below, has problems with all this inlining 34 code. So disable it for this version of the compiler. */ 35#if __GNUC_PREREQ (2, 8) && defined __USE_ISOC99 36__BEGIN_NAMESPACE_C99 37 38/* Test for negative number. Used in the signbit() macro. */ 39__MATH_INLINE int 40__NTH (__signbitf (float __x)) 41{ 42# if __WORDSIZE == 32 43 __extension__ union { float __f; int __i; } __u = { __f: __x }; 44 return __u.__i < 0; 45# else 46 int __m; 47 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); 48 return __m & 0x8; 49# endif 50} 51__MATH_INLINE int 52__NTH (__signbit (double __x)) 53{ 54# if __WORDSIZE == 32 55 __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; 56 return __u.__i[1] < 0; 57# else 58 int __m; 59 __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); 60 return __m & 0x80; 61# endif 62} 63__MATH_INLINE int 64__NTH (__signbitl (long double __x)) 65{ 66 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; 67 return (__u.__i[2] & 0x8000) != 0; 68} 69 70__END_NAMESPACE_C99 71#endif 72 73 74#if (__GNUC_PREREQ (2, 8) && !defined __NO_MATH_INLINES \ 75 && defined __OPTIMIZE__) 76 77# ifdef __USE_ISOC99 78__BEGIN_NAMESPACE_C99 79 80/* Round to nearest integer. */ 81# if __WORDSIZE == 64 || defined __SSE_MATH__ 82__MATH_INLINE long int 83__NTH (lrintf (float __x)) 84{ 85 long int __res; 86 __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); 87 return __res; 88} 89# endif 90# if __WORDSIZE == 64 || defined __SSE2_MATH__ 91__MATH_INLINE long int 92__NTH (lrint (double __x)) 93{ 94 long int __res; 95 __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); 96 return __res; 97} 98# endif 99# if __WORDSIZE == 64 100__MATH_INLINE long long int 101__NTH (llrintf (float __x)) 102{ 103 long long int __res; 104 __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); 105 return __res; 106} 107__MATH_INLINE long long int 108__NTH (llrint (double __x)) 109{ 110 long long int __res; 111 __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); 112 return __res; 113} 114# endif 115 116# if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \ 117 && (__WORDSIZE == 64 || defined __SSE2_MATH__) 118/* Determine maximum of two values. */ 119__MATH_INLINE float 120__NTH (fmaxf (float __x, float __y)) 121{ 122 __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y)); 123 return __x; 124} 125__MATH_INLINE double 126__NTH (fmax (double __x, double __y)) 127{ 128 __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y)); 129 return __x; 130} 131 132/* Determine minimum of two values. */ 133__MATH_INLINE float 134__NTH (fminf (float __x, float __y)) 135{ 136 __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y)); 137 return __x; 138} 139__MATH_INLINE double 140__NTH (fmin (double __x, double __y)) 141{ 142 __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y)); 143 return __x; 144} 145# endif 146 147__END_NAMESPACE_C99 148# endif 149 150# if defined __SSE4_1__ && (__WORDSIZE == 64 || defined __SSE2_MATH__) 151# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 152__BEGIN_NAMESPACE_C99 153 154/* Round to nearest integer. */ 155__MATH_INLINE double 156__NTH (rint (double __x)) 157{ 158 double __res; 159 __asm ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x)); 160 return __res; 161} 162__MATH_INLINE float 163__NTH (rintf (float __x)) 164{ 165 float __res; 166 __asm ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x)); 167 return __res; 168} 169 170# ifdef __USE_ISOC99 171/* Round to nearest integer without raising inexact exception. */ 172__MATH_INLINE double 173__NTH (nearbyint (double __x)) 174{ 175 double __res; 176 __asm ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); 177 return __res; 178} 179__MATH_INLINE float 180__NTH (nearbyintf (float __x)) 181{ 182 float __res; 183 __asm ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); 184 return __res; 185} 186# endif 187 188__END_NAMESPACE_C99 189# endif 190 191__BEGIN_NAMESPACE_STD 192/* Smallest integral value not less than X. */ 193__MATH_INLINE double 194__NTH (ceil (double __x)) 195{ 196 double __res; 197 __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x)); 198 return __res; 199} 200__END_NAMESPACE_STD 201 202__BEGIN_NAMESPACE_C99 203__MATH_INLINE float 204__NTH (ceilf (float __x)) 205{ 206 float __res; 207 __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x)); 208 return __res; 209} 210__END_NAMESPACE_C99 211 212__BEGIN_NAMESPACE_STD 213/* Largest integer not greater than X. */ 214__MATH_INLINE double 215__NTH (floor (double __x)) 216{ 217 double __res; 218 __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x)); 219 return __res; 220} 221__END_NAMESPACE_STD 222 223__BEGIN_NAMESPACE_C99 224__MATH_INLINE float 225__NTH (floorf (float __x)) 226{ 227 float __res; 228 __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x)); 229 return __res; 230} 231__END_NAMESPACE_C99 232# endif 233 234#endif 235