]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/fpu/bits/mathinline.h
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / sysdeps / i386 / fpu / bits / mathinline.h
CommitLineData
b20e47cb 1/* Inline math functions for i387.
a334319f 2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
3dbfd811 3 Free Software Foundation, Inc.
f8b87ef0 4 This file is part of the GNU C Library.
3996f34b 5 Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
b20e47cb 6
f8b87ef0 7 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
b20e47cb 11
f8b87ef0
UD
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 15 Lesser General Public License for more details.
b20e47cb 16
41bdb6e2
AJ
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
b20e47cb 21
61eb22d3
UD
22#ifndef _MATH_H
23# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
24#endif
f8b87ef0 25
f43ce637
UD
26#ifdef __cplusplus
27# define __MATH_INLINE __inline
28#else
29# define __MATH_INLINE extern __inline
30#endif
31
cd6ede75 32
ec751a23 33#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
a720a3ac 34/* GCC 2.97 and up have builtins that actually can be used. */
f4c024d1 35# if !__GNUC_PREREQ (2,97)
ec751a23 36/* ISO C99 defines some macros to perform unordered comparisons. The
cd6ede75
UD
37 ix87 FPU supports this with special opcodes and we should use them.
38 These must not be inline functions since we have to be able to handle
39 all floating-point types. */
f4c024d1
UD
40# undef isgreater
41# undef isgreaterequal
42# undef isless
43# undef islessequal
44# undef islessgreater
45# undef isunordered
a720a3ac 46# ifdef __i686__
f43ce637
UD
47/* For the PentiumPro and more recent processors we can provide
48 better code. */
a720a3ac 49# define isgreater(x, y) \
f43ce637 50 ({ register char __result; \
d111572f 51 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
f43ce637
UD
52 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
53 __result; })
a720a3ac 54# define isgreaterequal(x, y) \
f43ce637 55 ({ register char __result; \
d111572f 56 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
f43ce637
UD
57 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
58 __result; })
59
a720a3ac 60# define isless(x, y) \
f43ce637 61 ({ register char __result; \
d111572f
UD
62 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
63 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
f43ce637
UD
64 __result; })
65
a720a3ac 66# define islessequal(x, y) \
f43ce637 67 ({ register char __result; \
d111572f
UD
68 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
69 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
f43ce637
UD
70 __result; })
71
a720a3ac 72# define islessgreater(x, y) \
f43ce637 73 ({ register char __result; \
d111572f 74 __asm__ ("fucomip %%st(1), %%st; setne %%al" \
f43ce637
UD
75 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
76 __result; })
77
a720a3ac 78# define isunordered(x, y) \
f43ce637 79 ({ register char __result; \
d111572f 80 __asm__ ("fucomip %%st(1), %%st; setp %%al" \
f43ce637
UD
81 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
82 __result; })
a720a3ac 83# else
f43ce637 84/* This is the dumb, portable code for i386 and above. */
a720a3ac 85# define isgreater(x, y) \
9a0a462c 86 ({ register char __result; \
f43ce637 87 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
3996f34b
UD
88 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
89 __result; })
cd6ede75 90
a720a3ac 91# define isgreaterequal(x, y) \
9a0a462c 92 ({ register char __result; \
f43ce637 93 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
3996f34b
UD
94 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
95 __result; })
cd6ede75 96
a720a3ac 97# define isless(x, y) \
9a0a462c 98 ({ register char __result; \
d111572f
UD
99 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
100 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
3996f34b 101 __result; })
cd6ede75 102
a720a3ac 103# define islessequal(x, y) \
9a0a462c 104 ({ register char __result; \
d111572f
UD
105 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
106 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
3996f34b 107 __result; })
cd6ede75 108
a720a3ac 109# define islessgreater(x, y) \
9a0a462c 110 ({ register char __result; \
f43ce637 111 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \
3996f34b
UD
112 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
113 __result; })
cd6ede75 114
a720a3ac 115# define isunordered(x, y) \
9a0a462c
UD
116 ({ register char __result; \
117 __asm__ ("fucompp; fnstsw; sahf; setp %%al" \
3996f34b
UD
118 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
119 __result; })
a720a3ac
UD
120# endif /* __i686__ */
121# endif /* GCC 2.97 */
cd6ede75 122
090d93cd
UD
123/* The gcc, version 2.7 or below, has problems with all this inlining
124 code. So disable it for this version of the compiler. */
655c0697 125# if __GNUC_PREREQ (2, 8)
f43ce637
UD
126/* Test for negative number. Used in the signbit() macro. */
127__MATH_INLINE int
f377d022 128__NTH (__signbitf (float __x))
f43ce637 129{
e150fddc 130 __extension__ union { float __f; int __i; } __u = { __f: __x };
fc370352 131 return __u.__i < 0;
f43ce637
UD
132}
133__MATH_INLINE int
f377d022 134__NTH (__signbit (double __x))
f43ce637 135{
e150fddc 136 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
fc370352 137 return __u.__i[1] < 0;
f43ce637
UD
138}
139__MATH_INLINE int
f377d022 140__NTH (__signbitl (long double __x))
f43ce637 141{
e150fddc 142 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
f43ce637
UD
143 return (__u.__i[2] & 0x8000) != 0;
144}
090d93cd 145# endif
f43ce637 146#endif
cd6ede75 147
b20e47cb 148
f41c8091
UD
149/* The gcc, version 2.7 or below, has problems with all this inlining
150 code. So disable it for this version of the compiler. */
4360eafd 151#if __GNUC_PREREQ (2, 8)
f41c8091 152
f43ce637
UD
153#if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
154 && defined __OPTIMIZE__)
b20e47cb 155
3996f34b
UD
156/* A macro to define float, double, and long double versions of various
157 math functions for the ix87 FPU. FUNC is the function name (which will
158 be suffixed with f and l for the float and long double version,
300583a7
UD
159 respectively). OP is the name of the FPU operation.
160 We define two sets of macros. The set with the additional NP
161 doesn't add a prototype declaration. */
b20e47cb 162
ec751a23 163#if defined __USE_MISC || defined __USE_ISOC99
3996f34b
UD
164# define __inline_mathop(func, op) \
165 __inline_mathop_ (double, func, op) \
166 __inline_mathop_ (float, __CONCAT(func,f), op) \
167 __inline_mathop_ (long double, __CONCAT(func,l), op)
300583a7
UD
168# define __inline_mathopNP(func, op) \
169 __inline_mathopNP_ (double, func, op) \
170 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
171 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
3996f34b
UD
172#else
173# define __inline_mathop(func, op) \
174 __inline_mathop_ (double, func, op)
300583a7
UD
175# define __inline_mathopNP(func, op) \
176 __inline_mathopNP_ (double, func, op)
3996f34b 177#endif
b20e47cb 178
3996f34b
UD
179#define __inline_mathop_(float_type, func, op) \
180 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
300583a7
UD
181#define __inline_mathopNP_(float_type, func, op) \
182 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
b20e47cb 183
b20e47cb 184
ec751a23 185#if defined __USE_MISC || defined __USE_ISOC99
3996f34b
UD
186# define __inline_mathop_decl(func, op, params...) \
187 __inline_mathop_decl_ (double, func, op, params) \
188 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
189 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
300583a7
UD
190# define __inline_mathop_declNP(func, op, params...) \
191 __inline_mathop_declNP_ (double, func, op, params) \
192 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
193 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
3996f34b
UD
194#else
195# define __inline_mathop_decl(func, op, params...) \
196 __inline_mathop_decl_ (double, func, op, params)
300583a7
UD
197# define __inline_mathop_declNP(func, op, params...) \
198 __inline_mathop_declNP_ (double, func, op, params)
3996f34b 199#endif
b20e47cb 200
3996f34b 201#define __inline_mathop_decl_(float_type, func, op, params...) \
cc46c92d 202 __MATH_INLINE float_type func (float_type) __THROW; \
300583a7
UD
203 __inline_mathop_declNP_ (float_type, func, op, params)
204
205#define __inline_mathop_declNP_(float_type, func, op, params...) \
f377d022 206 __MATH_INLINE float_type __NTH (func (float_type __x)) \
3996f34b
UD
207 { \
208 register float_type __result; \
8f2ece69 209 __asm __volatile__ (op : "=t" (__result) : params); \
3996f34b
UD
210 return __result; \
211 }
212
213
ec751a23 214#if defined __USE_MISC || defined __USE_ISOC99
3996f34b
UD
215# define __inline_mathcode(func, arg, code) \
216 __inline_mathcode_ (double, func, arg, code) \
217 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
218 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
300583a7 219# define __inline_mathcodeNP(func, arg, code) \
3dbfd811 220 __inline_mathcodeNP_ (double, func, arg, code) \
300583a7
UD
221 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
222 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
1ea89a40
UD
223# define __inline_mathcode2(func, arg1, arg2, code) \
224 __inline_mathcode2_ (double, func, arg1, arg2, code) \
225 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
226 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
300583a7 227# define __inline_mathcodeNP2(func, arg1, arg2, code) \
3dbfd811 228 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
300583a7
UD
229 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
230 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
1ea89a40
UD
231# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
232 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
233 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
234 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
300583a7
UD
235# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
236 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
3dbfd811 237 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
300583a7 238 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
3996f34b
UD
239#else
240# define __inline_mathcode(func, arg, code) \
1ea89a40 241 __inline_mathcode_ (double, func, (arg), code)
300583a7
UD
242# define __inline_mathcodeNP(func, arg, code) \
243 __inline_mathcodeNP_ (double, func, (arg), code)
1ea89a40
UD
244# define __inline_mathcode2(func, arg1, arg2, code) \
245 __inline_mathcode2_ (double, func, arg1, arg2, code)
300583a7
UD
246# define __inline_mathcodeNP2(func, arg1, arg2, code) \
247 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
1ea89a40
UD
248# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
249 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
300583a7
UD
250# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
251 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
3996f34b 252#endif
b20e47cb 253
3996f34b 254#define __inline_mathcode_(float_type, func, arg, code) \
cc46c92d 255 __MATH_INLINE float_type func (float_type) __THROW; \
300583a7
UD
256 __inline_mathcodeNP_(float_type, func, arg, code)
257
258#define __inline_mathcodeNP_(float_type, func, arg, code) \
f377d022 259 __MATH_INLINE float_type __NTH (func (float_type arg)) \
3996f34b
UD
260 { \
261 code; \
262 }
b20e47cb 263
300583a7 264
3996f34b 265#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
cc46c92d 266 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
300583a7
UD
267 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
268
269#define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
f377d022 270 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
3996f34b
UD
271 { \
272 code; \
273 }
274
1ea89a40 275#define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
cc46c92d 276 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
300583a7
UD
277 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
278
279#define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
f377d022
UD
280 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
281 float_type arg3)) \
1ea89a40
UD
282 { \
283 code; \
284 }
f43ce637 285#endif
1ea89a40 286
3996f34b 287
f43ce637 288#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
f41c8091
UD
289/* Miscellaneous functions */
290
291__inline_mathcode (__sgn, __x, \
292 return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
293
378fbeb4
UD
294/* __FAST_MATH__ is defined by gcc -ffast-math. */
295#ifdef __FAST_MATH__
f41c8091
UD
296__inline_mathcode (__pow2, __x, \
297 register long double __value; \
298 register long double __exponent; \
7782d0bf 299 __extension__ long long int __p = (long long int) __x; \
f41c8091
UD
300 if (__x == (long double) __p) \
301 { \
302 __asm __volatile__ \
303 ("fscale" \
304 : "=t" (__value) : "0" (1.0), "u" (__x)); \
305 return __value; \
306 } \
307 __asm __volatile__ \
c0016081 308 ("fld %%st(0)\n\t" \
f41c8091
UD
309 "frndint # int(x)\n\t" \
310 "fxch\n\t" \
311 "fsub %%st(1) # fract(x)\n\t" \
312 "f2xm1 # 2^(fract(x)) - 1\n\t" \
313 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
314 __value += 1.0; \
315 __asm __volatile__ \
316 ("fscale" \
317 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
318 return __value)
319
378fbeb4
UD
320# ifdef __USE_GNU
321# define __sincos_code \
f41c8091
UD
322 register long double __cosr; \
323 register long double __sinr; \
324 __asm __volatile__ \
325 ("fsincos\n\t" \
326 "fnstsw %%ax\n\t" \
327 "testl $0x400, %%eax\n\t" \
328 "jz 1f\n\t" \
329 "fldpi\n\t" \
330 "fadd %%st(0)\n\t" \
331 "fxch %%st(1)\n\t" \
332 "2: fprem1\n\t" \
333 "fnstsw %%ax\n\t" \
334 "testl $0x400, %%eax\n\t" \
335 "jnz 2b\n\t" \
336 "fstp %%st(1)\n\t" \
337 "fsincos\n\t" \
338 "1:" \
339 : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
340 *__sinx = __sinr; \
341 *__cosx = __cosr
342
f41c8091 343__MATH_INLINE void
f377d022 344__NTH (__sincos (double __x, double *__sinx, double *__cosx))
f41c8091
UD
345{
346 __sincos_code;
347}
348
f41c8091 349__MATH_INLINE void
f377d022 350__NTH (__sincosf (float __x, float *__sinx, float *__cosx))
f41c8091
UD
351{
352 __sincos_code;
353}
354
f41c8091 355__MATH_INLINE void
f377d022 356__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
f41c8091
UD
357{
358 __sincos_code;
359}
378fbeb4 360# endif
f41c8091
UD
361
362
8f2ece69 363/* Optimized inline implementation, sometimes with reduced precision
3996f34b 364 and/or argument range. */
8f2ece69 365
3dbfd811
UD
366# if __GNUC_PREREQ (3, 5)
367# define __expm1_code \
368 register long double __temp; \
369 __temp = __builtin_expm1l (__x); \
370 return __temp ? __temp : __x
371# else
372# define __expm1_code \
3996f34b
UD
373 register long double __value; \
374 register long double __exponent; \
375 register long double __temp; \
376 __asm __volatile__ \
377 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
378 "fmul %%st(1) # x * log2(e)\n\t" \
50304ef0 379 "fst %%st(1)\n\t" \
3996f34b
UD
380 "frndint # int(x * log2(e))\n\t" \
381 "fxch\n\t" \
382 "fsub %%st(1) # fract(x * log2(e))\n\t" \
383 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
384 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
385 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
386 __asm __volatile__ \
387 ("fscale # 2^int(x * log2(e))\n\t" \
388 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
389 __temp -= 1.0; \
4e142297
RM
390 __temp += __value; \
391 return __temp ? __temp : __x
3dbfd811 392# endif
300583a7 393__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
3996f34b 394
3dbfd811
UD
395# if __GNUC_PREREQ (3, 4)
396__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
397# else
398# define __exp_code \
3996f34b
UD
399 register long double __value; \
400 register long double __exponent; \
401 __asm __volatile__ \
402 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
403 "fmul %%st(1) # x * log2(e)\n\t" \
50304ef0 404 "fst %%st(1)\n\t" \
3996f34b
UD
405 "frndint # int(x * log2(e))\n\t" \
406 "fxch\n\t" \
407 "fsub %%st(1) # fract(x * log2(e))\n\t" \
408 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
409 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
410 __value += 1.0; \
411 __asm __volatile__ \
412 ("fscale" \
413 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
414 return __value
300583a7
UD
415__inline_mathcodeNP (exp, __x, __exp_code)
416__inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
3dbfd811 417# endif
3996f34b
UD
418
419
3dbfd811 420# if !__GNUC_PREREQ (3, 5)
300583a7 421__inline_mathcodeNP (tan, __x, \
3996f34b 422 register long double __value; \
fa1f94fe 423 register long double __value2 __attribute__ ((__unused__)); \
3996f34b
UD
424 __asm __volatile__ \
425 ("fptan" \
426 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
427 return __value)
3dbfd811 428# endif
378fbeb4
UD
429#endif /* __FAST_MATH__ */
430
431
3dbfd811
UD
432#if __GNUC_PREREQ (3, 4)
433__inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
434 return __builtin_atan2l (__y, __x))
435#else
436# define __atan2_code \
378fbeb4
UD
437 register long double __value; \
438 __asm __volatile__ \
439 ("fpatan" \
440 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
441 return __value
3dbfd811 442# ifdef __FAST_MATH__
378fbeb4 443__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
3dbfd811 444# endif
378fbeb4 445__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
3dbfd811 446#endif
378fbeb4
UD
447
448
3dbfd811 449#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
378fbeb4
UD
450__inline_mathcodeNP2 (fmod, __x, __y, \
451 register long double __value; \
452 __asm __volatile__ \
453 ("1: fprem\n\t" \
454 "fnstsw %%ax\n\t" \
455 "sahf\n\t" \
456 "jp 1b" \
457 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
458 return __value)
3dbfd811 459#endif
3996f34b
UD
460
461
dfb87dc8 462#ifdef __FAST_MATH__
6d316b07 463# if !__GNUC_PREREQ (3,3)
300583a7
UD
464__inline_mathopNP (sqrt, "fsqrt")
465__inline_mathopNP_ (long double, __sqrtl, "fsqrt")
0135bde4
UD
466# define __libc_sqrtl(n) __sqrtl (n)
467# else
468# define __libc_sqrtl(n) __builtin_sqrtl (n)
6d316b07 469# endif
dfb87dc8 470#endif
3996f34b 471
4360eafd 472#if __GNUC_PREREQ (2, 8)
300583a7 473__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
3dbfd811 474# if defined __USE_MISC || defined __USE_ISOC99
300583a7
UD
475__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
476__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
3dbfd811 477# endif
300583a7 478__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
8f2ece69 479#else
3996f34b 480__inline_mathop (fabs, "fabs")
8f2ece69
UD
481__inline_mathop_ (long double, __fabsl, "fabs")
482#endif
3996f34b 483
378fbeb4 484#ifdef __FAST_MATH__
3dbfd811 485# if !__GNUC_PREREQ (3, 4)
3996f34b 486/* The argument range of this inline version is reduced. */
300583a7 487__inline_mathopNP (sin, "fsin")
3996f34b 488/* The argument range of this inline version is reduced. */
300583a7 489__inline_mathopNP (cos, "fcos")
3996f34b 490
300583a7 491__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
3dbfd811
UD
492# endif
493
494# if !__GNUC_PREREQ (3, 5)
300583a7 495__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
3996f34b 496
0135bde4
UD
497__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
498__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
3dbfd811 499# endif
378fbeb4 500
3dbfd811 501# if !__GNUC_PREREQ (3, 4)
378fbeb4 502__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
3dbfd811
UD
503# endif
504#endif /* __FAST_MATH__ */
3996f34b 505
15daa639 506__inline_mathcode_ (long double, __sgn1l, __x, \
2caacb0a 507 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
e150fddc 508 { __xld: __x }; \
15daa639
UD
509 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
510 __n.__xi[1] = 0x80000000; \
511 __n.__xi[0] = 0; \
512 return __n.__xld)
3996f34b
UD
513
514
1dd54850 515#ifdef __FAST_MATH__
3996f34b 516/* The argument range of the inline version of sinhl is slightly reduced. */
300583a7 517__inline_mathcodeNP (sinh, __x, \
8f2ece69 518 register long double __exm1 = __expm1l (__fabsl (__x)); \
3996f34b
UD
519 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
520
300583a7 521__inline_mathcodeNP (cosh, __x, \
3996f34b
UD
522 register long double __ex = __expl (__x); \
523 return 0.5 * (__ex + 1.0 / __ex))
524
300583a7 525__inline_mathcodeNP (tanh, __x, \
8f2ece69 526 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
3996f34b 527 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
1dd54850 528#endif
3996f34b 529
300583a7 530__inline_mathcodeNP (floor, __x, \
3996f34b 531 register long double __value; \
a334319f
UD
532 __volatile unsigned short int __cw; \
533 __volatile unsigned short int __cwtmp; \
534 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
535 __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
536 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
537 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
538 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
3996f34b
UD
539 return __value)
540
300583a7 541__inline_mathcodeNP (ceil, __x, \
3996f34b 542 register long double __value; \
a334319f
UD
543 __volatile unsigned short int __cw; \
544 __volatile unsigned short int __cwtmp; \
545 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
546 __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
547 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
548 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
549 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
3996f34b 550 return __value)
b20e47cb 551
dfb87dc8
UD
552#ifdef __FAST_MATH__
553# define __ldexp_code \
8f2ece69
UD
554 register long double __value; \
555 __asm __volatile__ \
556 ("fscale" \
557 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
558 return __value
559
8f2ece69 560__MATH_INLINE double
f377d022 561__NTH (ldexp (double __x, int __y))
8f2ece69
UD
562{
563 __ldexp_code;
564}
dfb87dc8 565#endif
8f2ece69 566
b20e47cb
RM
567
568/* Optimized versions for some non-standardized functions. */
ec751a23 569#if defined __USE_ISOC99 || defined __USE_MISC
b20e47cb 570
81e43fc1 571# ifdef __FAST_MATH__
300583a7 572__inline_mathcodeNP (expm1, __x, __expm1_code)
b20e47cb 573
714a562f
UD
574/* We cannot rely on M_SQRT being defined. So we do it for ourself
575 here. */
35915ec8 576# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
714a562f 577
3dbfd811 578# if !__GNUC_PREREQ (3, 5)
300583a7 579__inline_mathcodeNP (log1p, __x, \
3996f34b 580 register long double __value; \
8f2ece69 581 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
3996f34b
UD
582 __value = logl (1.0 + __x); \
583 else \
584 __asm __volatile__ \
585 ("fldln2\n\t" \
586 "fxch\n\t" \
587 "fyl2xp1" \
5892e305 588 : "=t" (__value) : "0" (__x) : "st(1)"); \
3996f34b 589 return __value)
3dbfd811 590# endif
3996f34b
UD
591
592
593/* The argument range of the inline version of asinhl is slightly reduced. */
300583a7 594__inline_mathcodeNP (asinh, __x, \
8f2ece69 595 register long double __y = __fabsl (__x); \
0135bde4 596 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
ca34d7a7 597 * __sgn1l (__x)))
3996f34b 598
300583a7 599__inline_mathcodeNP (acosh, __x, \
0135bde4 600 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
3996f34b 601
300583a7 602__inline_mathcodeNP (atanh, __x, \
8f2ece69 603 register long double __y = __fabsl (__x); \
bd355af0 604 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
3996f34b 605
3996f34b 606/* The argument range of the inline version of hypotl is slightly reduced. */
0135bde4
UD
607__inline_mathcodeNP2 (hypot, __x, __y,
608 return __libc_sqrtl (__x * __x + __y * __y))
3996f34b 609
3dbfd811 610# if !__GNUC_PREREQ (3, 5)
300583a7 611__inline_mathcodeNP(logb, __x, \
3996f34b
UD
612 register long double __value; \
613 register long double __junk; \
614 __asm __volatile__ \
615 ("fxtract\n\t" \
616 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
617 return __value)
3dbfd811 618# endif
3996f34b 619
35915ec8 620# endif
7d6a8338
UD
621#endif
622
ec751a23 623#ifdef __USE_ISOC99
3dbfd811
UD
624# ifdef __FAST_MATH__
625
626# if !__GNUC_PREREQ (3, 5)
300583a7 627__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
3dbfd811 628# endif
7d6a8338 629
8f2ece69 630__MATH_INLINE float
f377d022 631__NTH (ldexpf (float __x, int __y))
8f2ece69
UD
632{
633 __ldexp_code;
634}
635
8f2ece69 636__MATH_INLINE long double
f377d022 637__NTH (ldexpl (long double __x, int __y))
8f2ece69
UD
638{
639 __ldexp_code;
640}
3996f34b 641
300583a7 642__inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z)
7d6a8338 643
300583a7 644__inline_mathopNP (rint, "frndint")
3dbfd811 645# endif /* __FAST_MATH__ */
7d6a8338 646
3dbfd811 647# define __lrint_code \
33127459
UD
648 long int __lrintres; \
649 __asm__ __volatile__ \
650 ("fistpl %0" \
651 : "=m" (__lrintres) : "t" (__x) : "st"); \
652 return __lrintres
653__MATH_INLINE long int
f377d022 654__NTH (lrintf (float __x))
33127459
UD
655{
656 __lrint_code;
657}
658__MATH_INLINE long int
f377d022 659__NTH (lrint (double __x))
33127459
UD
660{
661 __lrint_code;
662}
663__MATH_INLINE long int
f377d022 664__NTH (lrintl (long double __x))
33127459
UD
665{
666 __lrint_code;
667}
3dbfd811 668# undef __lrint_code
33127459 669
3dbfd811 670# define __llrint_code \
33127459
UD
671 long long int __llrintres; \
672 __asm__ __volatile__ \
673 ("fistpll %0" \
674 : "=m" (__llrintres) : "t" (__x) : "st"); \
675 return __llrintres
676__MATH_INLINE long long int
f377d022 677__NTH (llrintf (float __x))
33127459
UD
678{
679 __llrint_code;
680}
681__MATH_INLINE long long int
f377d022 682__NTH (llrint (double __x))
33127459
UD
683{
684 __llrint_code;
685}
686__MATH_INLINE long long int
f377d022 687__NTH (llrintl (long double __x))
33127459
UD
688{
689 __llrint_code;
690}
3dbfd811 691# undef __llrint_code
33127459 692
cd6ede75
UD
693#endif
694
b20e47cb 695
cd6ede75 696#ifdef __USE_MISC
8f2ece69 697
3dbfd811 698# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
300583a7 699__inline_mathcodeNP2 (drem, __x, __y, \
3996f34b 700 register double __value; \
33127459 701 register int __clobbered; \
3996f34b
UD
702 __asm __volatile__ \
703 ("1: fprem1\n\t" \
704 "fstsw %%ax\n\t" \
705 "sahf\n\t" \
706 "jp 1b" \
33127459 707 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
3996f34b 708 return __value)
3dbfd811 709# endif
3996f34b 710
b20e47cb 711
7799b7b3 712/* This function is used in the `isfinite' macro. */
7799b7b3 713__MATH_INLINE int
f377d022 714__NTH (__finite (double __x))
7799b7b3 715{
db24ce47 716 return (__extension__
e150fddc 717 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
77faa354 718 | 0x800fffffu) + 1) >> 31));
7799b7b3 719}
dd33e89f 720
3996f34b 721/* Miscellaneous functions */
3dbfd811 722# ifdef __FAST_MATH__
3996f34b 723__inline_mathcode (__coshm1, __x, \
8f2ece69 724 register long double __exm1 = __expm1l (__fabsl (__x)); \
3996f34b
UD
725 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
726
727__inline_mathcode (__acosh1p, __x, \
0135bde4 728 return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0)))
3996f34b 729
3dbfd811 730# endif /* __FAST_MATH__ */
b20e47cb
RM
731#endif /* __USE_MISC */
732
3996f34b 733/* Undefine some of the large macros which are not used anymore. */
3996f34b 734#undef __atan2_code
378fbeb4
UD
735#ifdef __FAST_MATH__
736# undef __expm1_code
737# undef __exp_code
738# undef __sincos_code
739#endif /* __FAST_MATH__ */
3996f34b 740
b20e47cb 741#endif /* __NO_MATH_INLINES */
f43ce637
UD
742
743
744/* This code is used internally in the GNU libc. */
f43ce637
UD
745#ifdef __LIBC_INTERNAL_MATH_INLINES
746__inline_mathop (__ieee754_sqrt, "fsqrt")
bd355af0
UD
747__inline_mathcode2 (__ieee754_atan2, __y, __x,
748 register long double __value;
749 __asm __volatile__ ("fpatan\n\t"
750 : "=t" (__value)
751 : "0" (__x), "u" (__y) : "st(1)");
752 return __value;)
f43ce637
UD
753#endif
754
b20e47cb 755#endif /* __GNUC__ */