]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/x86_64/fpu/bits/mathinline.h
1 /* Inline math functions for x86-64.
2 Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #ifndef __extern_always_inline
24 # define __MATH_INLINE __inline
26 # define __MATH_INLINE __extern_always_inline
30 /* The gcc, version 2.7 or below, has problems with all this inlining
31 code. So disable it for this version of the compiler. */
32 #if __GNUC_PREREQ (2, 8) && defined __USE_ISOC99
35 /* Test for negative number. Used in the signbit() macro. */
37 __NTH (__signbitf (float __x
))
40 __extension__
union { float __f
; int __i
; } __u
= { __f
: __x
};
44 __asm ("pmovmskb %1, %0" : "=r" (__m
) : "x" (__x
));
49 __NTH (__signbit (double __x
))
52 __extension__
union { double __d
; int __i
[2]; } __u
= { __d
: __x
};
53 return __u
.__i
[1] < 0;
56 __asm ("pmovmskb %1, %0" : "=r" (__m
) : "x" (__x
));
61 __NTH (__signbitl (long double __x
))
63 __extension__
union { long double __l
; int __i
[3]; } __u
= { __l
: __x
};
64 return __u
.__i
[2] & 0x8000;
71 #if __GNUC_PREREQ (2, 8) && !__GNUC_PREREQ (3, 4) \
72 && !defined __NO_MATH_INLINES && defined __OPTIMIZE__
73 /* GCC 3.4 introduced builtins for all functions below, so
74 there's no need to define any of these inline functions. */
79 /* Round to nearest integer. */
81 __MATH_INLINE
long int
82 __NTH (lrintf (float __x
))
85 /* Mark as volatile since the result is dependend on the state of
86 the SSE control register (the rounding mode). Otherwise GCC might
87 remove these assembler instructions since it does not know about
88 the rounding mode change and cannot currently be told. */
89 __asm
__volatile__ ("cvtss2si %1, %0" : "=r" (__res
) : "xm" (__x
));
94 __MATH_INLINE
long int
95 __NTH (lrint (double __x
))
98 /* Mark as volatile since the result is dependend on the state of
99 the SSE control register (the rounding mode). Otherwise GCC might
100 remove these assembler instructions since it does not know about
101 the rounding mode change and cannot currently be told. */
102 __asm
__volatile__ ("cvtsd2si %1, %0" : "=r" (__res
) : "xm" (__x
));
107 __MATH_INLINE
long long int
108 __NTH (llrintf (float __x
))
111 /* Mark as volatile since the result is dependend on the state of
112 the SSE control register (the rounding mode). Otherwise GCC might
113 remove these assembler instructions since it does not know about
114 the rounding mode change and cannot currently be told. */
115 __asm
__volatile__ ("cvtss2si %1, %0" : "=r" (__res
) : "xm" (__x
));
118 __MATH_INLINE
long long int
119 __NTH (llrint (double __x
))
122 /* Mark as volatile since the result is dependend on the state of
123 the SSE control register (the rounding mode). Otherwise GCC might
124 remove these assembler instructions since it does not know about
125 the rounding mode change and cannot currently be told. */
126 __asm
__volatile__ ("cvtsd2si %1, %0" : "=r" (__res
) : "xm" (__x
));
131 # if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
132 && defined __SSE2_MATH__
133 /* Determine maximum of two values. */
135 __NTH (fmaxf (float __x
, float __y
))
139 __asm ("vmaxss %2, %1, %0" : "=x" (__res
) : "x" (x
), "xm" (__y
));
142 __asm ("maxss %1, %0" : "+x" (__x
) : "xm" (__y
));
147 __NTH (fmax (double __x
, double __y
))
151 __asm ("vmaxsd %2, %1, %0" : "=x" (__res
) : "x" (x
), "xm" (__y
));
154 __asm ("maxsd %1, %0" : "+x" (__x
) : "xm" (__y
));
159 /* Determine minimum of two values. */
161 __NTH (fminf (float __x
, float __y
))
165 __asm ("vminss %2, %1, %0" : "=x" (__res
) : "x" (x
), "xm" (__y
));
168 __asm ("minss %1, %0" : "+x" (__x
) : "xm" (__y
));
173 __NTH (fmin (double __x
, double __y
))
177 __asm ("vminsd %2, %1, %0" : "=x" (__res
) : "x" (x
), "xm" (__y
));
180 __asm ("minsd %1, %0" : "+x" (__x
) : "xm" (__y
));
189 # if defined __SSE4_1__ && defined __SSE2_MATH__
190 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
191 __BEGIN_NAMESPACE_C99
193 /* Round to nearest integer. */
195 __NTH (rint (double __x
))
198 /* Mark as volatile since the result is dependend on the state of
199 the SSE control register (the rounding mode). Otherwise GCC might
200 remove these assembler instructions since it does not know about
201 the rounding mode change and cannot currently be told. */
202 __asm
__volatile__ ("roundsd $4, %1, %0" : "=x" (__res
) : "xm" (__x
));
206 __NTH (rintf (float __x
))
209 /* Mark as volatile since the result is dependend on the state of
210 the SSE control register (the rounding mode). Otherwise GCC might
211 remove these assembler instructions since it does not know about
212 the rounding mode change and cannot currently be told. */
213 __asm
__volatile__ ("roundss $4, %1, %0" : "=x" (__res
) : "xm" (__x
));
218 /* Round to nearest integer without raising inexact exception. */
220 __NTH (nearbyint (double __x
))
223 /* Mark as volatile since the result is dependend on the state of
224 the SSE control register (the rounding mode). Otherwise GCC might
225 remove these assembler instructions since it does not know about
226 the rounding mode change and cannot currently be told. */
227 __asm
__volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res
) : "xm" (__x
));
231 __NTH (nearbyintf (float __x
))
234 /* Mark as volatile since the result is dependend on the state of
235 the SSE control register (the rounding mode). Otherwise GCC might
236 remove these assembler instructions since it does not know about
237 the rounding mode change and cannot currently be told. */
238 __asm
__volatile__ ("roundss $0xc, %1, %0" : "=x" (__res
) : "xm" (__x
));
246 __BEGIN_NAMESPACE_STD
247 /* Smallest integral value not less than X. */
249 __NTH (ceil (double __x
))
252 __asm ("roundsd $2, %1, %0" : "=x" (__res
) : "xm" (__x
));
257 __BEGIN_NAMESPACE_C99
259 __NTH (ceilf (float __x
))
262 __asm ("roundss $2, %1, %0" : "=x" (__res
) : "xm" (__x
));
267 __BEGIN_NAMESPACE_STD
268 /* Largest integer not greater than X. */
270 __NTH (floor (double __x
))
273 __asm ("roundsd $1, %1, %0" : "=x" (__res
) : "xm" (__x
));
278 __BEGIN_NAMESPACE_C99
280 __NTH (floorf (float __x
))
283 __asm ("roundss $1, %1, %0" : "=x" (__res
) : "xm" (__x
));