]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/x86/fpu/bits/mathinline.h
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / x86 / fpu / bits / mathinline.h
CommitLineData
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__ */