Branch data Line data Source code
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 : 2 : __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
|