]>
Commit | Line | Data |
---|---|---|
9359218f | 1 | /* Inline math functions for x86-64. |
cd205654 | 2 | Copyright (C) 2002-2004, 2007, 2009, 2011 Free Software Foundation, Inc. |
9359218f | 3 | This file is part of the GNU C Library. |
9359218f AJ |
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 | ||
24044103 JJ |
24 | #include <bits/wordsize.h> |
25 | ||
cd205654 | 26 | #ifndef __extern_always_inline |
9359218f AJ |
27 | # define __MATH_INLINE __inline |
28 | #else | |
cd205654 | 29 | # define __MATH_INLINE __extern_always_inline |
9359218f AJ |
30 | #endif |
31 | ||
32 | ||
ed22dcf6 UD |
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 | |
ad0f5cad | 36 | __BEGIN_NAMESPACE_C99 |
ea493b56 UD |
37 | |
38 | /* Test for negative number. Used in the signbit() macro. */ | |
39 | __MATH_INLINE int | |
f377d022 | 40 | __NTH (__signbitf (float __x)) |
ea493b56 | 41 | { |
ed22dcf6 | 42 | # if __WORDSIZE == 32 |
24044103 JJ |
43 | __extension__ union { float __f; int __i; } __u = { __f: __x }; |
44 | return __u.__i < 0; | |
ed22dcf6 | 45 | # else |
ef72d5f1 | 46 | int __m; |
c2735e95 | 47 | __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); |
ef72d5f1 | 48 | return __m & 0x8; |
ed22dcf6 | 49 | # endif |
ea493b56 UD |
50 | } |
51 | __MATH_INLINE int | |
f377d022 | 52 | __NTH (__signbit (double __x)) |
ea493b56 | 53 | { |
ed22dcf6 | 54 | # if __WORDSIZE == 32 |
24044103 JJ |
55 | __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; |
56 | return __u.__i[1] < 0; | |
ed22dcf6 | 57 | # else |
ef72d5f1 | 58 | int __m; |
c2735e95 | 59 | __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); |
ef72d5f1 | 60 | return __m & 0x80; |
ed22dcf6 | 61 | # endif |
ea493b56 UD |
62 | } |
63 | __MATH_INLINE int | |
f377d022 | 64 | __NTH (__signbitl (long double __x)) |
ea493b56 UD |
65 | { |
66 | __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; | |
67 | return (__u.__i[2] & 0x8000) != 0; | |
68 | } | |
cd205654 | 69 | |
ed22dcf6 UD |
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 | ||
cd205654 | 80 | /* Round to nearest integer. */ |
4c1a1f71 | 81 | # if __WORDSIZE == 64 || defined __SSE_MATH__ |
cd205654 UD |
82 | __MATH_INLINE long int |
83 | __NTH (lrintf (float __x)) | |
84 | { | |
85 | long int __res; | |
bf972c9d | 86 | __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); |
cd205654 UD |
87 | return __res; |
88 | } | |
4c1a1f71 UD |
89 | # endif |
90 | # if __WORDSIZE == 64 || defined __SSE2_MATH__ | |
cd205654 UD |
91 | __MATH_INLINE long int |
92 | __NTH (lrint (double __x)) | |
93 | { | |
94 | long int __res; | |
bf972c9d | 95 | __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); |
cd205654 UD |
96 | return __res; |
97 | } | |
4c1a1f71 UD |
98 | # endif |
99 | # if __WORDSIZE == 64 | |
cd205654 UD |
100 | __MATH_INLINE long long int |
101 | __NTH (llrintf (float __x)) | |
102 | { | |
103 | long long int __res; | |
bf972c9d | 104 | __asm ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); |
cd205654 UD |
105 | return __res; |
106 | } | |
107 | __MATH_INLINE long long int | |
108 | __NTH (llrint (double __x)) | |
109 | { | |
110 | long long int __res; | |
bf972c9d | 111 | __asm ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); |
cd205654 UD |
112 | return __res; |
113 | } | |
4c1a1f71 UD |
114 | # endif |
115 | ||
0ac5ae23 UD |
116 | # if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \ |
117 | && (__WORDSIZE == 64 || defined __SSE2_MATH__) | |
4c1a1f71 UD |
118 | /* Determine maximum of two values. */ |
119 | __MATH_INLINE float | |
120 | __NTH (fmaxf (float __x, float __y)) | |
121 | { | |
bf972c9d | 122 | __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y)); |
4c1a1f71 UD |
123 | return __x; |
124 | } | |
125 | __MATH_INLINE double | |
126 | __NTH (fmax (double __x, double __y)) | |
127 | { | |
bf972c9d | 128 | __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y)); |
4c1a1f71 UD |
129 | return __x; |
130 | } | |
131 | ||
132 | /* Determine minimum of two values. */ | |
133 | __MATH_INLINE float | |
134 | __NTH (fminf (float __x, float __y)) | |
135 | { | |
bf972c9d | 136 | __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y)); |
4c1a1f71 UD |
137 | return __x; |
138 | } | |
139 | __MATH_INLINE double | |
140 | __NTH (fmin (double __x, double __y)) | |
141 | { | |
bf972c9d | 142 | __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y)); |
4c1a1f71 UD |
143 | return __x; |
144 | } | |
145 | # endif | |
146 | ||
147 | __END_NAMESPACE_C99 | |
cd205654 UD |
148 | # endif |
149 | ||
ad0f5cad UD |
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; | |
228a984d | 159 | __asm ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x)); |
ad0f5cad UD |
160 | return __res; |
161 | } | |
162 | __MATH_INLINE float | |
163 | __NTH (rintf (float __x)) | |
164 | { | |
165 | float __res; | |
228a984d | 166 | __asm ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x)); |
ad0f5cad UD |
167 | return __res; |
168 | } | |
169 | ||
170 | __END_NAMESPACE_C99 | |
171 | # endif | |
172 | ||
173 | __BEGIN_NAMESPACE_STD | |
174 | /* Smallest integral value not less than X. */ | |
175 | __MATH_INLINE double | |
176 | __NTH (ceil (double __x)) | |
177 | { | |
178 | double __res; | |
228a984d | 179 | __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x)); |
ad0f5cad UD |
180 | return __res; |
181 | } | |
182 | __END_NAMESPACE_STD | |
183 | ||
184 | __BEGIN_NAMESPACE_C99 | |
185 | __MATH_INLINE float | |
186 | __NTH (ceilf (float __x)) | |
187 | { | |
188 | float __res; | |
228a984d | 189 | __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x)); |
ad0f5cad UD |
190 | return __res; |
191 | } | |
192 | __END_NAMESPACE_C99 | |
193 | ||
194 | __BEGIN_NAMESPACE_STD | |
195 | /* Largest integer not greater than X. */ | |
196 | __MATH_INLINE double | |
b171c137 | 197 | __NTH (floor (double __x)) |
ad0f5cad UD |
198 | { |
199 | double __res; | |
228a984d | 200 | __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x)); |
ad0f5cad UD |
201 | return __res; |
202 | } | |
203 | __END_NAMESPACE_STD | |
204 | ||
205 | __BEGIN_NAMESPACE_C99 | |
206 | __MATH_INLINE float | |
b171c137 | 207 | __NTH (floorf (float __x)) |
ad0f5cad UD |
208 | { |
209 | float __res; | |
228a984d | 210 | __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x)); |
ad0f5cad UD |
211 | return __res; |
212 | } | |
213 | __END_NAMESPACE_C99 | |
214 | # endif | |
215 | ||
9359218f | 216 | #endif |