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