]>
Commit | Line | Data |
---|---|---|
ddb28975 | 1 | /* Inline math functions for i387 and SSE. |
d4697bc9 | 2 | Copyright (C) 1995-2014 Free Software Foundation, Inc. |
f8b87ef0 | 3 | This file is part of the GNU C Library. |
b20e47cb | 4 | |
f8b87ef0 | 5 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
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. | |
b20e47cb | 9 | |
f8b87ef0 UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
b20e47cb | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
b20e47cb | 18 | |
61eb22d3 UD |
19 | #ifndef _MATH_H |
20 | # error "Never use <bits/mathinline.h> directly; include <math.h> instead." | |
21 | #endif | |
f8b87ef0 | 22 | |
ddb28975 | 23 | #ifndef __extern_always_inline |
f43ce637 UD |
24 | # define __MATH_INLINE __inline |
25 | #else | |
ddb28975 | 26 | # define __MATH_INLINE __extern_always_inline |
f43ce637 UD |
27 | #endif |
28 | ||
cd6ede75 | 29 | |
ec751a23 | 30 | #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 |
a720a3ac | 31 | /* GCC 2.97 and up have builtins that actually can be used. */ |
f4c024d1 | 32 | # if !__GNUC_PREREQ (2,97) |
ec751a23 | 33 | /* ISO C99 defines some macros to perform unordered comparisons. The |
cd6ede75 UD |
34 | ix87 FPU supports this with special opcodes and we should use them. |
35 | These must not be inline functions since we have to be able to handle | |
36 | all floating-point types. */ | |
f4c024d1 UD |
37 | # undef isgreater |
38 | # undef isgreaterequal | |
39 | # undef isless | |
40 | # undef islessequal | |
41 | # undef islessgreater | |
42 | # undef isunordered | |
a720a3ac | 43 | # ifdef __i686__ |
f43ce637 UD |
44 | /* For the PentiumPro and more recent processors we can provide |
45 | better code. */ | |
a720a3ac | 46 | # define isgreater(x, y) \ |
f43ce637 | 47 | ({ register char __result; \ |
d111572f | 48 | __asm__ ("fucomip %%st(1), %%st; seta %%al" \ |
f43ce637 UD |
49 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ |
50 | __result; }) | |
a720a3ac | 51 | # define isgreaterequal(x, y) \ |
f43ce637 | 52 | ({ register char __result; \ |
d111572f | 53 | __asm__ ("fucomip %%st(1), %%st; setae %%al" \ |
f43ce637 UD |
54 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ |
55 | __result; }) | |
56 | ||
a720a3ac | 57 | # define isless(x, y) \ |
f43ce637 | 58 | ({ register char __result; \ |
d111572f UD |
59 | __asm__ ("fucomip %%st(1), %%st; seta %%al" \ |
60 | : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ | |
f43ce637 UD |
61 | __result; }) |
62 | ||
a720a3ac | 63 | # define islessequal(x, y) \ |
f43ce637 | 64 | ({ register char __result; \ |
d111572f UD |
65 | __asm__ ("fucomip %%st(1), %%st; setae %%al" \ |
66 | : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ | |
f43ce637 UD |
67 | __result; }) |
68 | ||
a720a3ac | 69 | # define islessgreater(x, y) \ |
f43ce637 | 70 | ({ register char __result; \ |
d111572f | 71 | __asm__ ("fucomip %%st(1), %%st; setne %%al" \ |
f43ce637 UD |
72 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ |
73 | __result; }) | |
74 | ||
a720a3ac | 75 | # define isunordered(x, y) \ |
f43ce637 | 76 | ({ register char __result; \ |
d111572f | 77 | __asm__ ("fucomip %%st(1), %%st; setp %%al" \ |
f43ce637 UD |
78 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ |
79 | __result; }) | |
a720a3ac | 80 | # else |
f43ce637 | 81 | /* This is the dumb, portable code for i386 and above. */ |
a720a3ac | 82 | # define isgreater(x, y) \ |
9a0a462c | 83 | ({ register char __result; \ |
f43ce637 | 84 | __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ |
3996f34b UD |
85 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ |
86 | __result; }) | |
cd6ede75 | 87 | |
a720a3ac | 88 | # define isgreaterequal(x, y) \ |
9a0a462c | 89 | ({ register char __result; \ |
f43ce637 | 90 | __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ |
3996f34b UD |
91 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ |
92 | __result; }) | |
cd6ede75 | 93 | |
a720a3ac | 94 | # define isless(x, y) \ |
9a0a462c | 95 | ({ register char __result; \ |
d111572f UD |
96 | __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ |
97 | : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ | |
3996f34b | 98 | __result; }) |
cd6ede75 | 99 | |
a720a3ac | 100 | # define islessequal(x, y) \ |
9a0a462c | 101 | ({ register char __result; \ |
d111572f UD |
102 | __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ |
103 | : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ | |
3996f34b | 104 | __result; }) |
cd6ede75 | 105 | |
a720a3ac | 106 | # define islessgreater(x, y) \ |
9a0a462c | 107 | ({ register char __result; \ |
f43ce637 | 108 | __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \ |
3996f34b UD |
109 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ |
110 | __result; }) | |
cd6ede75 | 111 | |
a720a3ac | 112 | # define isunordered(x, y) \ |
9a0a462c UD |
113 | ({ register char __result; \ |
114 | __asm__ ("fucompp; fnstsw; sahf; setp %%al" \ | |
3996f34b UD |
115 | : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ |
116 | __result; }) | |
a720a3ac UD |
117 | # endif /* __i686__ */ |
118 | # endif /* GCC 2.97 */ | |
cd6ede75 | 119 | |
090d93cd UD |
120 | /* The gcc, version 2.7 or below, has problems with all this inlining |
121 | code. So disable it for this version of the compiler. */ | |
655c0697 | 122 | # if __GNUC_PREREQ (2, 8) |
ddb28975 L |
123 | __BEGIN_NAMESPACE_C99 |
124 | ||
f43ce637 UD |
125 | /* Test for negative number. Used in the signbit() macro. */ |
126 | __MATH_INLINE int | |
f377d022 | 127 | __NTH (__signbitf (float __x)) |
f43ce637 | 128 | { |
ddb28975 L |
129 | # ifdef __SSE2_MATH__ |
130 | int __m; | |
131 | __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); | |
132 | return (__m & 0x8) != 0; | |
133 | # else | |
e150fddc | 134 | __extension__ union { float __f; int __i; } __u = { __f: __x }; |
fc370352 | 135 | return __u.__i < 0; |
ddb28975 | 136 | # endif |
f43ce637 UD |
137 | } |
138 | __MATH_INLINE int | |
f377d022 | 139 | __NTH (__signbit (double __x)) |
f43ce637 | 140 | { |
ddb28975 L |
141 | # ifdef __SSE2_MATH__ |
142 | int __m; | |
143 | __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); | |
144 | return (__m & 0x80) != 0; | |
145 | # else | |
e150fddc | 146 | __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; |
fc370352 | 147 | return __u.__i[1] < 0; |
ddb28975 | 148 | # endif |
f43ce637 UD |
149 | } |
150 | __MATH_INLINE int | |
f377d022 | 151 | __NTH (__signbitl (long double __x)) |
f43ce637 | 152 | { |
e150fddc | 153 | __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; |
f43ce637 UD |
154 | return (__u.__i[2] & 0x8000) != 0; |
155 | } | |
ddb28975 L |
156 | |
157 | __END_NAMESPACE_C99 | |
090d93cd | 158 | # endif |
f43ce637 | 159 | #endif |
cd6ede75 | 160 | |
b20e47cb | 161 | |
f41c8091 UD |
162 | /* The gcc, version 2.7 or below, has problems with all this inlining |
163 | code. So disable it for this version of the compiler. */ | |
4360eafd | 164 | #if __GNUC_PREREQ (2, 8) |
ddb28975 L |
165 | # if !__GNUC_PREREQ (3, 4) && !defined __NO_MATH_INLINES \ |
166 | && defined __OPTIMIZE__ | |
167 | /* GCC 3.4 introduced builtins for all functions below, so | |
168 | there's no need to define any of these inline functions. */ | |
169 | ||
170 | # ifdef __USE_ISOC99 | |
171 | __BEGIN_NAMESPACE_C99 | |
172 | ||
173 | /* Round to nearest integer. */ | |
174 | # ifdef __SSE_MATH__ | |
175 | __MATH_INLINE long int | |
176 | __NTH (lrintf (float __x)) | |
177 | { | |
178 | long int __res; | |
179 | /* Mark as volatile since the result is dependent on the state of | |
180 | the SSE control register (the rounding mode). Otherwise GCC might | |
181 | remove these assembler instructions since it does not know about | |
182 | the rounding mode change and cannot currently be told. */ | |
183 | __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); | |
184 | return __res; | |
185 | } | |
186 | # endif | |
187 | # ifdef __SSE2_MATH__ | |
188 | __MATH_INLINE long int | |
189 | __NTH (lrint (double __x)) | |
190 | { | |
191 | long int __res; | |
192 | /* Mark as volatile since the result is dependent on the state of | |
193 | the SSE control register (the rounding mode). Otherwise GCC might | |
194 | remove these assembler instructions since it does not know about | |
195 | the rounding mode change and cannot currently be told. */ | |
196 | __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); | |
197 | return __res; | |
198 | } | |
199 | # endif | |
200 | # ifdef __x86_64__ | |
828beb13 | 201 | __extension__ |
ddb28975 L |
202 | __MATH_INLINE long long int |
203 | __NTH (llrintf (float __x)) | |
204 | { | |
205 | long long int __res; | |
206 | /* Mark as volatile since the result is dependent on the state of | |
207 | the SSE control register (the rounding mode). Otherwise GCC might | |
208 | remove these assembler instructions since it does not know about | |
209 | the rounding mode change and cannot currently be told. */ | |
210 | __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); | |
211 | return __res; | |
212 | } | |
828beb13 | 213 | __extension__ |
ddb28975 L |
214 | __MATH_INLINE long long int |
215 | __NTH (llrint (double __x)) | |
216 | { | |
217 | long long int __res; | |
218 | /* Mark as volatile since the result is dependent on the state of | |
219 | the SSE control register (the rounding mode). Otherwise GCC might | |
220 | remove these assembler instructions since it does not know about | |
221 | the rounding mode change and cannot currently be told. */ | |
222 | __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); | |
223 | return __res; | |
224 | } | |
225 | # endif | |
226 | ||
227 | # if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \ | |
228 | && defined __SSE2_MATH__ | |
229 | /* Determine maximum of two values. */ | |
230 | __MATH_INLINE float | |
231 | __NTH (fmaxf (float __x, float __y)) | |
232 | { | |
233 | # ifdef __AVX__ | |
234 | float __res; | |
235 | __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); | |
236 | return __res; | |
237 | # else | |
238 | __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y)); | |
239 | return __x; | |
240 | # endif | |
241 | } | |
242 | __MATH_INLINE double | |
243 | __NTH (fmax (double __x, double __y)) | |
244 | { | |
245 | # ifdef __AVX__ | |
246 | float __res; | |
247 | __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); | |
248 | return __res; | |
249 | # else | |
250 | __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y)); | |
251 | return __x; | |
252 | # endif | |
253 | } | |
254 | ||
255 | /* Determine minimum of two values. */ | |
256 | __MATH_INLINE float | |
257 | __NTH (fminf (float __x, float __y)) | |
258 | { | |
259 | # ifdef __AVX__ | |
260 | float __res; | |
261 | __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); | |
262 | return __res; | |
263 | # else | |
264 | __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y)); | |
265 | return __x; | |
266 | # endif | |
267 | } | |
268 | __MATH_INLINE double | |
269 | __NTH (fmin (double __x, double __y)) | |
270 | { | |
271 | # ifdef __AVX__ | |
272 | float __res; | |
273 | __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); | |
274 | return __res; | |
275 | # else | |
276 | __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y)); | |
277 | return __x; | |
278 | # endif | |
279 | } | |
280 | # endif | |
281 | ||
282 | __END_NAMESPACE_C99 | |
283 | # endif | |
284 | ||
285 | # if defined __SSE4_1__ && defined __SSE2_MATH__ | |
286 | # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 | |
287 | __BEGIN_NAMESPACE_C99 | |
288 | ||
289 | /* Round to nearest integer. */ | |
290 | __MATH_INLINE double | |
291 | __NTH (rint (double __x)) | |
292 | { | |
293 | double __res; | |
294 | /* Mark as volatile since the result is dependent on the state of | |
295 | the SSE control register (the rounding mode). Otherwise GCC might | |
296 | remove these assembler instructions since it does not know about | |
297 | the rounding mode change and cannot currently be told. */ | |
298 | __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x)); | |
299 | return __res; | |
300 | } | |
301 | __MATH_INLINE float | |
302 | __NTH (rintf (float __x)) | |
303 | { | |
304 | float __res; | |
305 | /* Mark as volatile since the result is dependent on the state of | |
306 | the SSE control register (the rounding mode). Otherwise GCC might | |
307 | remove these assembler instructions since it does not know about | |
308 | the rounding mode change and cannot currently be told. */ | |
309 | __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x)); | |
310 | return __res; | |
311 | } | |
312 | ||
313 | # ifdef __USE_ISOC99 | |
314 | /* Round to nearest integer without raising inexact exception. */ | |
315 | __MATH_INLINE double | |
316 | __NTH (nearbyint (double __x)) | |
317 | { | |
318 | double __res; | |
319 | /* Mark as volatile since the result is dependent on the state of | |
320 | the SSE control register (the rounding mode). Otherwise GCC might | |
321 | remove these assembler instructions since it does not know about | |
322 | the rounding mode change and cannot currently be told. */ | |
323 | __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); | |
324 | return __res; | |
325 | } | |
326 | __MATH_INLINE float | |
327 | __NTH (nearbyintf (float __x)) | |
328 | { | |
329 | float __res; | |
330 | /* Mark as volatile since the result is dependent on the state of | |
331 | the SSE control register (the rounding mode). Otherwise GCC might | |
332 | remove these assembler instructions since it does not know about | |
333 | the rounding mode change and cannot currently be told. */ | |
334 | __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); | |
335 | return __res; | |
336 | } | |
337 | # endif | |
338 | ||
339 | __END_NAMESPACE_C99 | |
340 | # endif | |
341 | ||
342 | __BEGIN_NAMESPACE_STD | |
343 | /* Smallest integral value not less than X. */ | |
344 | __MATH_INLINE double | |
345 | __NTH (ceil (double __x)) | |
346 | { | |
347 | double __res; | |
348 | __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x)); | |
349 | return __res; | |
350 | } | |
351 | __END_NAMESPACE_STD | |
352 | ||
353 | __BEGIN_NAMESPACE_C99 | |
354 | __MATH_INLINE float | |
355 | __NTH (ceilf (float __x)) | |
356 | { | |
357 | float __res; | |
358 | __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x)); | |
359 | return __res; | |
360 | } | |
361 | __END_NAMESPACE_C99 | |
362 | ||
363 | __BEGIN_NAMESPACE_STD | |
364 | /* Largest integer not greater than X. */ | |
365 | __MATH_INLINE double | |
366 | __NTH (floor (double __x)) | |
367 | { | |
368 | double __res; | |
369 | __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x)); | |
370 | return __res; | |
371 | } | |
372 | __END_NAMESPACE_STD | |
373 | ||
374 | __BEGIN_NAMESPACE_C99 | |
375 | __MATH_INLINE float | |
376 | __NTH (floorf (float __x)) | |
377 | { | |
378 | float __res; | |
379 | __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x)); | |
380 | return __res; | |
381 | } | |
382 | __END_NAMESPACE_C99 | |
383 | # endif | |
384 | # endif | |
ed1825f8 | 385 | #endif |
f41c8091 | 386 | |
ed1825f8 L |
387 | #ifndef __x86_64__ |
388 | # if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ | |
f43ce637 | 389 | && defined __OPTIMIZE__) |
b20e47cb | 390 | |
7b943af6 UD |
391 | /* The inline functions do not set errno or raise necessarily the |
392 | correct exceptions. */ | |
ed1825f8 | 393 | # undef math_errhandling |
7b943af6 | 394 | |
3996f34b UD |
395 | /* A macro to define float, double, and long double versions of various |
396 | math functions for the ix87 FPU. FUNC is the function name (which will | |
397 | be suffixed with f and l for the float and long double version, | |
300583a7 UD |
398 | respectively). OP is the name of the FPU operation. |
399 | We define two sets of macros. The set with the additional NP | |
400 | doesn't add a prototype declaration. */ | |
b20e47cb | 401 | |
ed1825f8 L |
402 | # if defined __USE_MISC || defined __USE_ISOC99 |
403 | # define __inline_mathop(func, op) \ | |
3996f34b UD |
404 | __inline_mathop_ (double, func, op) \ |
405 | __inline_mathop_ (float, __CONCAT(func,f), op) \ | |
406 | __inline_mathop_ (long double, __CONCAT(func,l), op) | |
ed1825f8 | 407 | # define __inline_mathopNP(func, op) \ |
300583a7 UD |
408 | __inline_mathopNP_ (double, func, op) \ |
409 | __inline_mathopNP_ (float, __CONCAT(func,f), op) \ | |
410 | __inline_mathopNP_ (long double, __CONCAT(func,l), op) | |
ed1825f8 L |
411 | # else |
412 | # define __inline_mathop(func, op) \ | |
3996f34b | 413 | __inline_mathop_ (double, func, op) |
ed1825f8 | 414 | # define __inline_mathopNP(func, op) \ |
300583a7 | 415 | __inline_mathopNP_ (double, func, op) |
ed1825f8 | 416 | # endif |
b20e47cb | 417 | |
ed1825f8 | 418 | # define __inline_mathop_(float_type, func, op) \ |
3996f34b | 419 | __inline_mathop_decl_ (float_type, func, op, "0" (__x)) |
ed1825f8 | 420 | # define __inline_mathopNP_(float_type, func, op) \ |
300583a7 | 421 | __inline_mathop_declNP_ (float_type, func, op, "0" (__x)) |
b20e47cb | 422 | |
b20e47cb | 423 | |
ed1825f8 L |
424 | # if defined __USE_MISC || defined __USE_ISOC99 |
425 | # define __inline_mathop_decl(func, op, params...) \ | |
3996f34b UD |
426 | __inline_mathop_decl_ (double, func, op, params) \ |
427 | __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \ | |
428 | __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params) | |
ed1825f8 | 429 | # define __inline_mathop_declNP(func, op, params...) \ |
300583a7 UD |
430 | __inline_mathop_declNP_ (double, func, op, params) \ |
431 | __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \ | |
432 | __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params) | |
ed1825f8 L |
433 | # else |
434 | # define __inline_mathop_decl(func, op, params...) \ | |
3996f34b | 435 | __inline_mathop_decl_ (double, func, op, params) |
ed1825f8 | 436 | # define __inline_mathop_declNP(func, op, params...) \ |
300583a7 | 437 | __inline_mathop_declNP_ (double, func, op, params) |
ed1825f8 | 438 | # endif |
b20e47cb | 439 | |
ed1825f8 | 440 | # define __inline_mathop_decl_(float_type, func, op, params...) \ |
cc46c92d | 441 | __MATH_INLINE float_type func (float_type) __THROW; \ |
300583a7 UD |
442 | __inline_mathop_declNP_ (float_type, func, op, params) |
443 | ||
ed1825f8 | 444 | # define __inline_mathop_declNP_(float_type, func, op, params...) \ |
f377d022 | 445 | __MATH_INLINE float_type __NTH (func (float_type __x)) \ |
3996f34b UD |
446 | { \ |
447 | register float_type __result; \ | |
8f2ece69 | 448 | __asm __volatile__ (op : "=t" (__result) : params); \ |
3996f34b UD |
449 | return __result; \ |
450 | } | |
451 | ||
452 | ||
ed1825f8 L |
453 | # if defined __USE_MISC || defined __USE_ISOC99 |
454 | # define __inline_mathcode(func, arg, code) \ | |
3996f34b UD |
455 | __inline_mathcode_ (double, func, arg, code) \ |
456 | __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \ | |
457 | __inline_mathcode_ (long double, __CONCAT(func,l), arg, code) | |
ed1825f8 | 458 | # define __inline_mathcodeNP(func, arg, code) \ |
3dbfd811 | 459 | __inline_mathcodeNP_ (double, func, arg, code) \ |
300583a7 UD |
460 | __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \ |
461 | __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code) | |
ed1825f8 | 462 | # define __inline_mathcode2(func, arg1, arg2, code) \ |
1ea89a40 UD |
463 | __inline_mathcode2_ (double, func, arg1, arg2, code) \ |
464 | __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \ | |
465 | __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code) | |
ed1825f8 | 466 | # define __inline_mathcodeNP2(func, arg1, arg2, code) \ |
3dbfd811 | 467 | __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \ |
300583a7 UD |
468 | __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \ |
469 | __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code) | |
ed1825f8 | 470 | # define __inline_mathcode3(func, arg1, arg2, arg3, code) \ |
1ea89a40 UD |
471 | __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \ |
472 | __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ | |
473 | __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) | |
ed1825f8 | 474 | # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ |
300583a7 | 475 | __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \ |
3dbfd811 | 476 | __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ |
300583a7 | 477 | __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) |
ed1825f8 L |
478 | # else |
479 | # define __inline_mathcode(func, arg, code) \ | |
1ea89a40 | 480 | __inline_mathcode_ (double, func, (arg), code) |
ed1825f8 | 481 | # define __inline_mathcodeNP(func, arg, code) \ |
300583a7 | 482 | __inline_mathcodeNP_ (double, func, (arg), code) |
ed1825f8 | 483 | # define __inline_mathcode2(func, arg1, arg2, code) \ |
1ea89a40 | 484 | __inline_mathcode2_ (double, func, arg1, arg2, code) |
ed1825f8 | 485 | # define __inline_mathcodeNP2(func, arg1, arg2, code) \ |
300583a7 | 486 | __inline_mathcodeNP2_ (double, func, arg1, arg2, code) |
ed1825f8 | 487 | # define __inline_mathcode3(func, arg1, arg2, arg3, code) \ |
1ea89a40 | 488 | __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) |
ed1825f8 | 489 | # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ |
300583a7 | 490 | __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) |
ed1825f8 | 491 | # endif |
b20e47cb | 492 | |
ed1825f8 | 493 | # define __inline_mathcode_(float_type, func, arg, code) \ |
cc46c92d | 494 | __MATH_INLINE float_type func (float_type) __THROW; \ |
300583a7 UD |
495 | __inline_mathcodeNP_(float_type, func, arg, code) |
496 | ||
ed1825f8 | 497 | # define __inline_mathcodeNP_(float_type, func, arg, code) \ |
f377d022 | 498 | __MATH_INLINE float_type __NTH (func (float_type arg)) \ |
3996f34b UD |
499 | { \ |
500 | code; \ | |
501 | } | |
b20e47cb | 502 | |
300583a7 | 503 | |
ed1825f8 | 504 | # define __inline_mathcode2_(float_type, func, arg1, arg2, code) \ |
cc46c92d | 505 | __MATH_INLINE float_type func (float_type, float_type) __THROW; \ |
300583a7 UD |
506 | __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code) |
507 | ||
ed1825f8 | 508 | # define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \ |
f377d022 | 509 | __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \ |
3996f34b UD |
510 | { \ |
511 | code; \ | |
512 | } | |
513 | ||
ed1825f8 | 514 | # define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \ |
cc46c92d | 515 | __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \ |
300583a7 UD |
516 | __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) |
517 | ||
ed1825f8 | 518 | # define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \ |
f377d022 UD |
519 | __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \ |
520 | float_type arg3)) \ | |
1ea89a40 UD |
521 | { \ |
522 | code; \ | |
523 | } | |
ed1825f8 | 524 | # endif |
1ea89a40 | 525 | |
3996f34b | 526 | |
ed1825f8 L |
527 | # if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ |
528 | /* Miscellaneous functions */ | |
f41c8091 | 529 | |
378fbeb4 | 530 | /* __FAST_MATH__ is defined by gcc -ffast-math. */ |
ed1825f8 L |
531 | # ifdef __FAST_MATH__ |
532 | # ifdef __USE_GNU | |
533 | # define __sincos_code \ | |
f41c8091 UD |
534 | register long double __cosr; \ |
535 | register long double __sinr; \ | |
8de131cb | 536 | register unsigned int __swtmp; \ |
f41c8091 UD |
537 | __asm __volatile__ \ |
538 | ("fsincos\n\t" \ | |
8de131cb RM |
539 | "fnstsw %w2\n\t" \ |
540 | "testl $0x400, %2\n\t" \ | |
f41c8091 UD |
541 | "jz 1f\n\t" \ |
542 | "fldpi\n\t" \ | |
543 | "fadd %%st(0)\n\t" \ | |
544 | "fxch %%st(1)\n\t" \ | |
545 | "2: fprem1\n\t" \ | |
8de131cb RM |
546 | "fnstsw %w2\n\t" \ |
547 | "testl $0x400, %2\n\t" \ | |
f41c8091 UD |
548 | "jnz 2b\n\t" \ |
549 | "fstp %%st(1)\n\t" \ | |
550 | "fsincos\n\t" \ | |
551 | "1:" \ | |
8de131cb | 552 | : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \ |
f41c8091 UD |
553 | *__sinx = __sinr; \ |
554 | *__cosx = __cosr | |
555 | ||
f41c8091 | 556 | __MATH_INLINE void |
f377d022 | 557 | __NTH (__sincos (double __x, double *__sinx, double *__cosx)) |
f41c8091 UD |
558 | { |
559 | __sincos_code; | |
560 | } | |
561 | ||
f41c8091 | 562 | __MATH_INLINE void |
f377d022 | 563 | __NTH (__sincosf (float __x, float *__sinx, float *__cosx)) |
f41c8091 UD |
564 | { |
565 | __sincos_code; | |
566 | } | |
567 | ||
f41c8091 | 568 | __MATH_INLINE void |
f377d022 | 569 | __NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx)) |
f41c8091 UD |
570 | { |
571 | __sincos_code; | |
572 | } | |
ed1825f8 | 573 | # endif |
f41c8091 UD |
574 | |
575 | ||
8f2ece69 | 576 | /* Optimized inline implementation, sometimes with reduced precision |
3996f34b | 577 | and/or argument range. */ |
8f2ece69 | 578 | |
ed1825f8 L |
579 | # if __GNUC_PREREQ (3, 5) |
580 | # define __expm1_code \ | |
3dbfd811 UD |
581 | register long double __temp; \ |
582 | __temp = __builtin_expm1l (__x); \ | |
583 | return __temp ? __temp : __x | |
ed1825f8 L |
584 | # else |
585 | # define __expm1_code \ | |
3996f34b UD |
586 | register long double __value; \ |
587 | register long double __exponent; \ | |
588 | register long double __temp; \ | |
589 | __asm __volatile__ \ | |
590 | ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \ | |
591 | "fmul %%st(1) # x * log2(e)\n\t" \ | |
50304ef0 | 592 | "fst %%st(1)\n\t" \ |
3996f34b UD |
593 | "frndint # int(x * log2(e))\n\t" \ |
594 | "fxch\n\t" \ | |
595 | "fsub %%st(1) # fract(x * log2(e))\n\t" \ | |
596 | "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ | |
597 | "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \ | |
598 | : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ | |
599 | __asm __volatile__ \ | |
600 | ("fscale # 2^int(x * log2(e))\n\t" \ | |
601 | : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \ | |
602 | __temp -= 1.0; \ | |
4e142297 RM |
603 | __temp += __value; \ |
604 | return __temp ? __temp : __x | |
ed1825f8 | 605 | # endif |
300583a7 | 606 | __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code) |
3996f34b | 607 | |
ed1825f8 | 608 | # if __GNUC_PREREQ (3, 4) |
3dbfd811 | 609 | __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x)) |
ed1825f8 L |
610 | # else |
611 | # define __exp_code \ | |
3996f34b UD |
612 | register long double __value; \ |
613 | register long double __exponent; \ | |
614 | __asm __volatile__ \ | |
615 | ("fldl2e # e^x = 2^(x * log2(e))\n\t" \ | |
616 | "fmul %%st(1) # x * log2(e)\n\t" \ | |
50304ef0 | 617 | "fst %%st(1)\n\t" \ |
3996f34b UD |
618 | "frndint # int(x * log2(e))\n\t" \ |
619 | "fxch\n\t" \ | |
620 | "fsub %%st(1) # fract(x * log2(e))\n\t" \ | |
621 | "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ | |
622 | : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ | |
623 | __value += 1.0; \ | |
624 | __asm __volatile__ \ | |
625 | ("fscale" \ | |
626 | : "=t" (__value) : "0" (__value), "u" (__exponent)); \ | |
627 | return __value | |
300583a7 UD |
628 | __inline_mathcodeNP (exp, __x, __exp_code) |
629 | __inline_mathcodeNP_ (long double, __expl, __x, __exp_code) | |
ed1825f8 | 630 | # endif |
3996f34b UD |
631 | |
632 | ||
ed1825f8 | 633 | # if !__GNUC_PREREQ (3, 5) |
300583a7 | 634 | __inline_mathcodeNP (tan, __x, \ |
3996f34b | 635 | register long double __value; \ |
fa1f94fe | 636 | register long double __value2 __attribute__ ((__unused__)); \ |
3996f34b UD |
637 | __asm __volatile__ \ |
638 | ("fptan" \ | |
639 | : "=t" (__value2), "=u" (__value) : "0" (__x)); \ | |
640 | return __value) | |
ed1825f8 L |
641 | # endif |
642 | # endif /* __FAST_MATH__ */ | |
378fbeb4 UD |
643 | |
644 | ||
ed1825f8 | 645 | # if __GNUC_PREREQ (3, 4) |
3dbfd811 UD |
646 | __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, |
647 | return __builtin_atan2l (__y, __x)) | |
ed1825f8 L |
648 | # else |
649 | # define __atan2_code \ | |
378fbeb4 UD |
650 | register long double __value; \ |
651 | __asm __volatile__ \ | |
652 | ("fpatan" \ | |
653 | : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \ | |
654 | return __value | |
ed1825f8 | 655 | # ifdef __FAST_MATH__ |
378fbeb4 | 656 | __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code) |
ed1825f8 | 657 | # endif |
378fbeb4 | 658 | __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code) |
ed1825f8 | 659 | # endif |
378fbeb4 UD |
660 | |
661 | ||
ed1825f8 | 662 | # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) |
378fbeb4 UD |
663 | __inline_mathcodeNP2 (fmod, __x, __y, \ |
664 | register long double __value; \ | |
665 | __asm __volatile__ \ | |
666 | ("1: fprem\n\t" \ | |
667 | "fnstsw %%ax\n\t" \ | |
668 | "sahf\n\t" \ | |
669 | "jp 1b" \ | |
670 | : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \ | |
671 | return __value) | |
ed1825f8 | 672 | # endif |
3996f34b UD |
673 | |
674 | ||
ed1825f8 L |
675 | # ifdef __FAST_MATH__ |
676 | # if !__GNUC_PREREQ (3,3) | |
300583a7 UD |
677 | __inline_mathopNP (sqrt, "fsqrt") |
678 | __inline_mathopNP_ (long double, __sqrtl, "fsqrt") | |
ed1825f8 L |
679 | # define __libc_sqrtl(n) __sqrtl (n) |
680 | # else | |
681 | # define __libc_sqrtl(n) __builtin_sqrtl (n) | |
682 | # endif | |
683 | # endif | |
3996f34b | 684 | |
ed1825f8 | 685 | # if __GNUC_PREREQ (2, 8) |
300583a7 | 686 | __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x)) |
ed1825f8 | 687 | # if defined __USE_MISC || defined __USE_ISOC99 |
300583a7 UD |
688 | __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x)) |
689 | __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x)) | |
ed1825f8 | 690 | # endif |
300583a7 | 691 | __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x)) |
ed1825f8 | 692 | # else |
3996f34b | 693 | __inline_mathop (fabs, "fabs") |
8f2ece69 | 694 | __inline_mathop_ (long double, __fabsl, "fabs") |
ed1825f8 | 695 | # endif |
3996f34b | 696 | |
ed1825f8 L |
697 | # ifdef __FAST_MATH__ |
698 | # if !__GNUC_PREREQ (3, 4) | |
3996f34b | 699 | /* The argument range of this inline version is reduced. */ |
300583a7 | 700 | __inline_mathopNP (sin, "fsin") |
3996f34b | 701 | /* The argument range of this inline version is reduced. */ |
300583a7 | 702 | __inline_mathopNP (cos, "fcos") |
3996f34b | 703 | |
300583a7 | 704 | __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)") |
ed1825f8 | 705 | # endif |
3dbfd811 | 706 | |
ed1825f8 | 707 | # if !__GNUC_PREREQ (3, 5) |
300583a7 | 708 | __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)") |
3996f34b | 709 | |
0135bde4 UD |
710 | __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x))) |
711 | __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x)) | |
ed1825f8 | 712 | # endif |
378fbeb4 | 713 | |
ed1825f8 | 714 | # if !__GNUC_PREREQ (3, 4) |
378fbeb4 | 715 | __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)") |
ed1825f8 L |
716 | # endif |
717 | # endif /* __FAST_MATH__ */ | |
3996f34b | 718 | |
15daa639 | 719 | __inline_mathcode_ (long double, __sgn1l, __x, \ |
2caacb0a | 720 | __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \ |
e150fddc | 721 | { __xld: __x }; \ |
15daa639 UD |
722 | __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \ |
723 | __n.__xi[1] = 0x80000000; \ | |
724 | __n.__xi[0] = 0; \ | |
725 | return __n.__xld) | |
3996f34b UD |
726 | |
727 | ||
ed1825f8 | 728 | # ifdef __FAST_MATH__ |
3996f34b | 729 | /* The argument range of the inline version of sinhl is slightly reduced. */ |
300583a7 | 730 | __inline_mathcodeNP (sinh, __x, \ |
8f2ece69 | 731 | register long double __exm1 = __expm1l (__fabsl (__x)); \ |
3996f34b UD |
732 | return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x)) |
733 | ||
300583a7 | 734 | __inline_mathcodeNP (cosh, __x, \ |
3996f34b UD |
735 | register long double __ex = __expl (__x); \ |
736 | return 0.5 * (__ex + 1.0 / __ex)) | |
737 | ||
300583a7 | 738 | __inline_mathcodeNP (tanh, __x, \ |
8f2ece69 | 739 | register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \ |
3996f34b | 740 | return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x)) |
ed1825f8 | 741 | # endif |
3996f34b | 742 | |
300583a7 | 743 | __inline_mathcodeNP (floor, __x, \ |
3996f34b | 744 | register long double __value; \ |
5c2af134 UD |
745 | register int __ignore; \ |
746 | unsigned short int __cw; \ | |
747 | unsigned short int __cwtmp; \ | |
e1b37083 UD |
748 | __asm __volatile ("fnstcw %3\n\t" \ |
749 | "movzwl %3, %1\n\t" \ | |
5c2af134 UD |
750 | "andl $0xf3ff, %1\n\t" \ |
751 | "orl $0x0400, %1\n\t" /* rounding down */ \ | |
e1b37083 UD |
752 | "movw %w1, %2\n\t" \ |
753 | "fldcw %2\n\t" \ | |
5c2af134 | 754 | "frndint\n\t" \ |
e1b37083 UD |
755 | "fldcw %3" \ |
756 | : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ | |
757 | "=m" (__cw) \ | |
758 | : "0" (__x)); \ | |
3996f34b UD |
759 | return __value) |
760 | ||
300583a7 | 761 | __inline_mathcodeNP (ceil, __x, \ |
3996f34b | 762 | register long double __value; \ |
5c2af134 UD |
763 | register int __ignore; \ |
764 | unsigned short int __cw; \ | |
765 | unsigned short int __cwtmp; \ | |
e1b37083 UD |
766 | __asm __volatile ("fnstcw %3\n\t" \ |
767 | "movzwl %3, %1\n\t" \ | |
5c2af134 UD |
768 | "andl $0xf3ff, %1\n\t" \ |
769 | "orl $0x0800, %1\n\t" /* rounding up */ \ | |
e1b37083 UD |
770 | "movw %w1, %2\n\t" \ |
771 | "fldcw %2\n\t" \ | |
5c2af134 | 772 | "frndint\n\t" \ |
e1b37083 UD |
773 | "fldcw %3" \ |
774 | : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ | |
775 | "=m" (__cw) \ | |
776 | : "0" (__x)); \ | |
3996f34b | 777 | return __value) |
b20e47cb | 778 | |
ed1825f8 L |
779 | # ifdef __FAST_MATH__ |
780 | # define __ldexp_code \ | |
8f2ece69 UD |
781 | register long double __value; \ |
782 | __asm __volatile__ \ | |
783 | ("fscale" \ | |
784 | : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \ | |
785 | return __value | |
786 | ||
8f2ece69 | 787 | __MATH_INLINE double |
f377d022 | 788 | __NTH (ldexp (double __x, int __y)) |
8f2ece69 UD |
789 | { |
790 | __ldexp_code; | |
791 | } | |
ed1825f8 | 792 | # endif |
8f2ece69 | 793 | |
b20e47cb RM |
794 | |
795 | /* Optimized versions for some non-standardized functions. */ | |
ed1825f8 | 796 | # if defined __USE_ISOC99 || defined __USE_MISC |
b20e47cb | 797 | |
ed1825f8 | 798 | # ifdef __FAST_MATH__ |
300583a7 | 799 | __inline_mathcodeNP (expm1, __x, __expm1_code) |
b20e47cb | 800 | |
714a562f UD |
801 | /* We cannot rely on M_SQRT being defined. So we do it for ourself |
802 | here. */ | |
ed1825f8 | 803 | # define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */ |
714a562f | 804 | |
ed1825f8 | 805 | # if !__GNUC_PREREQ (3, 5) |
300583a7 | 806 | __inline_mathcodeNP (log1p, __x, \ |
3996f34b | 807 | register long double __value; \ |
8f2ece69 | 808 | if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \ |
3996f34b UD |
809 | __value = logl (1.0 + __x); \ |
810 | else \ | |
811 | __asm __volatile__ \ | |
812 | ("fldln2\n\t" \ | |
813 | "fxch\n\t" \ | |
814 | "fyl2xp1" \ | |
5892e305 | 815 | : "=t" (__value) : "0" (__x) : "st(1)"); \ |
3996f34b | 816 | return __value) |
ed1825f8 | 817 | # endif |
3996f34b UD |
818 | |
819 | ||
820 | /* The argument range of the inline version of asinhl is slightly reduced. */ | |
300583a7 | 821 | __inline_mathcodeNP (asinh, __x, \ |
8f2ece69 | 822 | register long double __y = __fabsl (__x); \ |
0135bde4 | 823 | return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \ |
ca34d7a7 | 824 | * __sgn1l (__x))) |
3996f34b | 825 | |
300583a7 | 826 | __inline_mathcodeNP (acosh, __x, \ |
0135bde4 | 827 | return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0))) |
3996f34b | 828 | |
300583a7 | 829 | __inline_mathcodeNP (atanh, __x, \ |
8f2ece69 | 830 | register long double __y = __fabsl (__x); \ |
bd355af0 | 831 | return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x)) |
3996f34b | 832 | |
3996f34b | 833 | /* The argument range of the inline version of hypotl is slightly reduced. */ |
0135bde4 UD |
834 | __inline_mathcodeNP2 (hypot, __x, __y, |
835 | return __libc_sqrtl (__x * __x + __y * __y)) | |
3996f34b | 836 | |
ed1825f8 | 837 | # if !__GNUC_PREREQ (3, 5) |
300583a7 | 838 | __inline_mathcodeNP(logb, __x, \ |
3996f34b UD |
839 | register long double __value; \ |
840 | register long double __junk; \ | |
841 | __asm __volatile__ \ | |
842 | ("fxtract\n\t" \ | |
843 | : "=t" (__junk), "=u" (__value) : "0" (__x)); \ | |
844 | return __value) | |
ed1825f8 | 845 | # endif |
3996f34b | 846 | |
ed1825f8 L |
847 | # endif |
848 | # endif | |
7d6a8338 | 849 | |
ed1825f8 L |
850 | # ifdef __USE_ISOC99 |
851 | # ifdef __FAST_MATH__ | |
3dbfd811 | 852 | |
ed1825f8 | 853 | # if !__GNUC_PREREQ (3, 5) |
300583a7 | 854 | __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)") |
ed1825f8 | 855 | # endif |
7d6a8338 | 856 | |
8f2ece69 | 857 | __MATH_INLINE float |
f377d022 | 858 | __NTH (ldexpf (float __x, int __y)) |
8f2ece69 UD |
859 | { |
860 | __ldexp_code; | |
861 | } | |
862 | ||
8f2ece69 | 863 | __MATH_INLINE long double |
f377d022 | 864 | __NTH (ldexpl (long double __x, int __y)) |
8f2ece69 UD |
865 | { |
866 | __ldexp_code; | |
867 | } | |
3996f34b | 868 | |
300583a7 | 869 | __inline_mathopNP (rint, "frndint") |
ed1825f8 | 870 | # endif /* __FAST_MATH__ */ |
7d6a8338 | 871 | |
ed1825f8 | 872 | # define __lrint_code \ |
33127459 UD |
873 | long int __lrintres; \ |
874 | __asm__ __volatile__ \ | |
875 | ("fistpl %0" \ | |
876 | : "=m" (__lrintres) : "t" (__x) : "st"); \ | |
877 | return __lrintres | |
878 | __MATH_INLINE long int | |
f377d022 | 879 | __NTH (lrintf (float __x)) |
33127459 UD |
880 | { |
881 | __lrint_code; | |
882 | } | |
883 | __MATH_INLINE long int | |
f377d022 | 884 | __NTH (lrint (double __x)) |
33127459 UD |
885 | { |
886 | __lrint_code; | |
887 | } | |
888 | __MATH_INLINE long int | |
f377d022 | 889 | __NTH (lrintl (long double __x)) |
33127459 UD |
890 | { |
891 | __lrint_code; | |
892 | } | |
ed1825f8 | 893 | # undef __lrint_code |
33127459 | 894 | |
ed1825f8 | 895 | # define __llrint_code \ |
33127459 UD |
896 | long long int __llrintres; \ |
897 | __asm__ __volatile__ \ | |
898 | ("fistpll %0" \ | |
899 | : "=m" (__llrintres) : "t" (__x) : "st"); \ | |
900 | return __llrintres | |
828beb13 | 901 | __extension__ |
33127459 | 902 | __MATH_INLINE long long int |
f377d022 | 903 | __NTH (llrintf (float __x)) |
33127459 UD |
904 | { |
905 | __llrint_code; | |
906 | } | |
828beb13 | 907 | __extension__ |
33127459 | 908 | __MATH_INLINE long long int |
f377d022 | 909 | __NTH (llrint (double __x)) |
33127459 UD |
910 | { |
911 | __llrint_code; | |
912 | } | |
828beb13 | 913 | __extension__ |
33127459 | 914 | __MATH_INLINE long long int |
f377d022 | 915 | __NTH (llrintl (long double __x)) |
33127459 UD |
916 | { |
917 | __llrint_code; | |
918 | } | |
ed1825f8 | 919 | # undef __llrint_code |
33127459 | 920 | |
ed1825f8 | 921 | # endif |
cd6ede75 | 922 | |
b20e47cb | 923 | |
ed1825f8 | 924 | # ifdef __USE_MISC |
8f2ece69 | 925 | |
ed1825f8 | 926 | # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) |
300583a7 | 927 | __inline_mathcodeNP2 (drem, __x, __y, \ |
3996f34b | 928 | register double __value; \ |
33127459 | 929 | register int __clobbered; \ |
3996f34b UD |
930 | __asm __volatile__ \ |
931 | ("1: fprem1\n\t" \ | |
932 | "fstsw %%ax\n\t" \ | |
933 | "sahf\n\t" \ | |
934 | "jp 1b" \ | |
33127459 | 935 | : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \ |
3996f34b | 936 | return __value) |
ed1825f8 | 937 | # endif |
3996f34b | 938 | |
b20e47cb | 939 | |
7799b7b3 | 940 | /* This function is used in the `isfinite' macro. */ |
7799b7b3 | 941 | __MATH_INLINE int |
f377d022 | 942 | __NTH (__finite (double __x)) |
7799b7b3 | 943 | { |
db24ce47 | 944 | return (__extension__ |
e150fddc | 945 | (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] |
77faa354 | 946 | | 0x800fffffu) + 1) >> 31)); |
7799b7b3 | 947 | } |
dd33e89f | 948 | |
ed1825f8 | 949 | # endif /* __USE_MISC */ |
b20e47cb | 950 | |
3996f34b | 951 | /* Undefine some of the large macros which are not used anymore. */ |
ed1825f8 L |
952 | # undef __atan2_code |
953 | # ifdef __FAST_MATH__ | |
954 | # undef __expm1_code | |
955 | # undef __exp_code | |
956 | # undef __sincos_code | |
957 | # endif /* __FAST_MATH__ */ | |
3996f34b | 958 | |
ed1825f8 | 959 | # endif /* __NO_MATH_INLINES */ |
f43ce637 UD |
960 | |
961 | ||
962 | /* This code is used internally in the GNU libc. */ | |
ed1825f8 | 963 | # ifdef __LIBC_INTERNAL_MATH_INLINES |
f43ce637 | 964 | __inline_mathop (__ieee754_sqrt, "fsqrt") |
bd355af0 UD |
965 | __inline_mathcode2 (__ieee754_atan2, __y, __x, |
966 | register long double __value; | |
967 | __asm __volatile__ ("fpatan\n\t" | |
968 | : "=t" (__value) | |
969 | : "0" (__x), "u" (__y) : "st(1)"); | |
970 | return __value;) | |
ed1825f8 | 971 | # endif |
f43ce637 | 972 | |
ed1825f8 | 973 | #endif /* !__x86_64__ */ |