]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/fpu/bits/mathinline.h
* tst-oddstacklimit.c: New file.
[thirdparty/glibc.git] / sysdeps / i386 / fpu / bits / mathinline.h
CommitLineData
b20e47cb 1/* Inline math functions for i387.
dfb87dc8 2 Copyright (C) 1995,96,97,98,99,2000,2001,2003 Free Software Foundation, Inc.
f8b87ef0 3 This file is part of the GNU C Library.
3996f34b 4 Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
b20e47cb 5
f8b87ef0 6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
b20e47cb 10
f8b87ef0
UD
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
b20e47cb 15
41bdb6e2
AJ
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
b20e47cb 20
61eb22d3
UD
21#ifndef _MATH_H
22# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23#endif
f8b87ef0 24
f43ce637
UD
25#ifdef __cplusplus
26# define __MATH_INLINE __inline
27#else
28# define __MATH_INLINE extern __inline
29#endif
30
cd6ede75 31
ec751a23 32#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
a720a3ac
UD
33# if __GNUC_PREREQ (2,97)
34/* GCC 2.97 and up have builtins that actually can be used. */
35# define isgreater(x, y) __builtin_isgreater (x, y)
36# define isgreaterequal(x, y) __builtin_isgreaterequal (x, y)
37# define isless(x, y) __builtin_isless (x, y)
38# define islessequal(x, y) __builtin_islessequal (x, y)
39# define islessgreater(x, y) __builtin_islessgreater (x, y)
40# define isunordered(x, y) __builtin_isunordered (x, y)
41# else
ec751a23 42/* ISO C99 defines some macros to perform unordered comparisons. The
cd6ede75
UD
43 ix87 FPU supports this with special opcodes and we should use them.
44 These must not be inline functions since we have to be able to handle
45 all floating-point types. */
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
cc46c92d 128__signbitf (float __x) __THROW
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
cc46c92d 134__signbit (double __x) __THROW
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
cc46c92d 140__signbitl (long double __x) __THROW
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...) \
cc46c92d 206 __MATH_INLINE float_type func (float_type __x) __THROW \
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
UD
219# define __inline_mathcodeNP(func, arg, code) \
220 __inline_mathcodeNP_ (double, func, arg, code) \
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
UD
227# define __inline_mathcodeNP2(func, arg1, arg2, code) \
228 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
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) \
237 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
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) \
cc46c92d 259 __MATH_INLINE float_type func (float_type arg) __THROW \
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) \
cc46c92d 270 __MATH_INLINE float_type func (float_type arg1, float_type arg2) __THROW \
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) \
1ea89a40 280 __MATH_INLINE float_type func (float_type arg1, float_type arg2, \
cc46c92d 281 float_type arg3) __THROW \
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
cc46c92d 344__sincos (double __x, double *__sinx, double *__cosx) __THROW
f41c8091
UD
345{
346 __sincos_code;
347}
348
f41c8091 349__MATH_INLINE void
cc46c92d 350__sincosf (float __x, float *__sinx, float *__cosx) __THROW
f41c8091
UD
351{
352 __sincos_code;
353}
354
f41c8091 355__MATH_INLINE void
cc46c92d 356__sincosl (long double __x, long double *__sinx, long double *__cosx) __THROW
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
378fbeb4 366# define __expm1_code \
3996f34b
UD
367 register long double __value; \
368 register long double __exponent; \
369 register long double __temp; \
370 __asm __volatile__ \
371 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
372 "fmul %%st(1) # x * log2(e)\n\t" \
50304ef0 373 "fst %%st(1)\n\t" \
3996f34b
UD
374 "frndint # int(x * log2(e))\n\t" \
375 "fxch\n\t" \
376 "fsub %%st(1) # fract(x * log2(e))\n\t" \
377 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
378 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
379 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
380 __asm __volatile__ \
381 ("fscale # 2^int(x * log2(e))\n\t" \
382 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
383 __temp -= 1.0; \
15daa639 384 return __temp + __value ?: __x
300583a7 385__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
3996f34b
UD
386
387
378fbeb4 388# define __exp_code \
3996f34b
UD
389 register long double __value; \
390 register long double __exponent; \
391 __asm __volatile__ \
392 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
393 "fmul %%st(1) # x * log2(e)\n\t" \
50304ef0 394 "fst %%st(1)\n\t" \
3996f34b
UD
395 "frndint # int(x * log2(e))\n\t" \
396 "fxch\n\t" \
397 "fsub %%st(1) # fract(x * log2(e))\n\t" \
398 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
399 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
400 __value += 1.0; \
401 __asm __volatile__ \
402 ("fscale" \
403 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
404 return __value
300583a7
UD
405__inline_mathcodeNP (exp, __x, __exp_code)
406__inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
3996f34b
UD
407
408
300583a7 409__inline_mathcodeNP (tan, __x, \
3996f34b 410 register long double __value; \
fa1f94fe 411 register long double __value2 __attribute__ ((__unused__)); \
3996f34b
UD
412 __asm __volatile__ \
413 ("fptan" \
414 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
415 return __value)
378fbeb4
UD
416#endif /* __FAST_MATH__ */
417
418
419#define __atan2_code \
420 register long double __value; \
421 __asm __volatile__ \
422 ("fpatan" \
423 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
424 return __value
425__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
426__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
427
428
429__inline_mathcodeNP2 (fmod, __x, __y, \
430 register long double __value; \
431 __asm __volatile__ \
432 ("1: fprem\n\t" \
433 "fnstsw %%ax\n\t" \
434 "sahf\n\t" \
435 "jp 1b" \
436 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
437 return __value)
3996f34b
UD
438
439
dfb87dc8 440#ifdef __FAST_MATH__
6d316b07 441# if !__GNUC_PREREQ (3,3)
300583a7
UD
442__inline_mathopNP (sqrt, "fsqrt")
443__inline_mathopNP_ (long double, __sqrtl, "fsqrt")
0135bde4
UD
444# define __libc_sqrtl(n) __sqrtl (n)
445# else
446# define __libc_sqrtl(n) __builtin_sqrtl (n)
6d316b07 447# endif
dfb87dc8 448#endif
3996f34b 449
4360eafd 450#if __GNUC_PREREQ (2, 8)
300583a7
UD
451__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
452__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
453__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
454__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
8f2ece69 455#else
3996f34b 456__inline_mathop (fabs, "fabs")
8f2ece69
UD
457__inline_mathop_ (long double, __fabsl, "fabs")
458#endif
3996f34b 459
378fbeb4 460#ifdef __FAST_MATH__
3996f34b 461/* The argument range of this inline version is reduced. */
300583a7 462__inline_mathopNP (sin, "fsin")
3996f34b 463/* The argument range of this inline version is reduced. */
300583a7 464__inline_mathopNP (cos, "fcos")
3996f34b 465
300583a7
UD
466__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
467__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
3996f34b 468
0135bde4
UD
469__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
470__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
378fbeb4
UD
471#endif /* __FAST_MATH__ */
472
473__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
3996f34b 474
15daa639 475__inline_mathcode_ (long double, __sgn1l, __x, \
2caacb0a 476 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
e150fddc 477 { __xld: __x }; \
15daa639
UD
478 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
479 __n.__xi[1] = 0x80000000; \
480 __n.__xi[0] = 0; \
481 return __n.__xld)
3996f34b
UD
482
483
1dd54850 484#ifdef __FAST_MATH__
3996f34b 485/* The argument range of the inline version of sinhl is slightly reduced. */
300583a7 486__inline_mathcodeNP (sinh, __x, \
8f2ece69 487 register long double __exm1 = __expm1l (__fabsl (__x)); \
3996f34b
UD
488 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
489
300583a7 490__inline_mathcodeNP (cosh, __x, \
3996f34b
UD
491 register long double __ex = __expl (__x); \
492 return 0.5 * (__ex + 1.0 / __ex))
493
300583a7 494__inline_mathcodeNP (tanh, __x, \
8f2ece69 495 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
3996f34b 496 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
1dd54850 497#endif
3996f34b 498
300583a7 499__inline_mathcodeNP (floor, __x, \
3996f34b
UD
500 register long double __value; \
501 __volatile unsigned short int __cw; \
502 __volatile unsigned short int __cwtmp; \
503 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
504 __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
505 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
506 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
507 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
508 return __value)
509
300583a7 510__inline_mathcodeNP (ceil, __x, \
3996f34b
UD
511 register long double __value; \
512 __volatile unsigned short int __cw; \
513 __volatile unsigned short int __cwtmp; \
514 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
515 __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
516 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
517 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
518 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
519 return __value)
b20e47cb 520
dfb87dc8
UD
521#ifdef __FAST_MATH__
522# define __ldexp_code \
8f2ece69
UD
523 register long double __value; \
524 __asm __volatile__ \
525 ("fscale" \
526 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
527 return __value
528
8f2ece69 529__MATH_INLINE double
cc46c92d 530ldexp (double __x, int __y) __THROW
8f2ece69
UD
531{
532 __ldexp_code;
533}
dfb87dc8 534#endif
8f2ece69 535
b20e47cb
RM
536
537/* Optimized versions for some non-standardized functions. */
ec751a23 538#if defined __USE_ISOC99 || defined __USE_MISC
b20e47cb 539
81e43fc1 540# ifdef __FAST_MATH__
300583a7 541__inline_mathcodeNP (expm1, __x, __expm1_code)
b20e47cb 542
714a562f
UD
543/* We cannot rely on M_SQRT being defined. So we do it for ourself
544 here. */
35915ec8 545# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
714a562f 546
300583a7 547__inline_mathcodeNP (log1p, __x, \
3996f34b 548 register long double __value; \
8f2ece69 549 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
3996f34b
UD
550 __value = logl (1.0 + __x); \
551 else \
552 __asm __volatile__ \
553 ("fldln2\n\t" \
554 "fxch\n\t" \
555 "fyl2xp1" \
5892e305 556 : "=t" (__value) : "0" (__x) : "st(1)"); \
3996f34b
UD
557 return __value)
558
559
560/* The argument range of the inline version of asinhl is slightly reduced. */
300583a7 561__inline_mathcodeNP (asinh, __x, \
8f2ece69 562 register long double __y = __fabsl (__x); \
0135bde4 563 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
ca34d7a7 564 * __sgn1l (__x)))
3996f34b 565
300583a7 566__inline_mathcodeNP (acosh, __x, \
0135bde4 567 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
3996f34b 568
300583a7 569__inline_mathcodeNP (atanh, __x, \
8f2ece69 570 register long double __y = __fabsl (__x); \
bd355af0 571 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
3996f34b 572
3996f34b 573/* The argument range of the inline version of hypotl is slightly reduced. */
0135bde4
UD
574__inline_mathcodeNP2 (hypot, __x, __y,
575 return __libc_sqrtl (__x * __x + __y * __y))
3996f34b 576
300583a7 577__inline_mathcodeNP(logb, __x, \
3996f34b
UD
578 register long double __value; \
579 register long double __junk; \
580 __asm __volatile__ \
581 ("fxtract\n\t" \
582 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
583 return __value)
584
35915ec8 585# endif
7d6a8338
UD
586#endif
587
ec751a23 588#ifdef __USE_ISOC99
f9c9dc78 589#ifdef __FAST_MATH__
300583a7 590__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
7d6a8338 591
8f2ece69 592__MATH_INLINE float
cc46c92d 593ldexpf (float __x, int __y) __THROW
8f2ece69
UD
594{
595 __ldexp_code;
596}
597
8f2ece69 598__MATH_INLINE long double
cc46c92d 599ldexpl (long double __x, int __y) __THROW
8f2ece69
UD
600{
601 __ldexp_code;
602}
3996f34b 603
300583a7 604__inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z)
7d6a8338 605
300583a7 606__inline_mathopNP (rint, "frndint")
f9c9dc78 607#endif /* __FAST_MATH__ */
7d6a8338 608
33127459
UD
609#define __lrint_code \
610 long int __lrintres; \
611 __asm__ __volatile__ \
612 ("fistpl %0" \
613 : "=m" (__lrintres) : "t" (__x) : "st"); \
614 return __lrintres
615__MATH_INLINE long int
cc46c92d 616lrintf (float __x) __THROW
33127459
UD
617{
618 __lrint_code;
619}
620__MATH_INLINE long int
cc46c92d 621lrint (double __x) __THROW
33127459
UD
622{
623 __lrint_code;
624}
625__MATH_INLINE long int
cc46c92d 626lrintl (long double __x) __THROW
33127459
UD
627{
628 __lrint_code;
629}
630#undef __lrint_code
631
632#define __llrint_code \
633 long long int __llrintres; \
634 __asm__ __volatile__ \
635 ("fistpll %0" \
636 : "=m" (__llrintres) : "t" (__x) : "st"); \
637 return __llrintres
638__MATH_INLINE long long int
cc46c92d 639llrintf (float __x) __THROW
33127459
UD
640{
641 __llrint_code;
642}
643__MATH_INLINE long long int
cc46c92d 644llrint (double __x) __THROW
33127459
UD
645{
646 __llrint_code;
647}
648__MATH_INLINE long long int
cc46c92d 649llrintl (long double __x) __THROW
33127459
UD
650{
651 __llrint_code;
652}
653#undef __llrint_code
654
cd6ede75
UD
655#endif
656
b20e47cb 657
cd6ede75 658#ifdef __USE_MISC
8f2ece69 659
300583a7 660__inline_mathcodeNP2 (drem, __x, __y, \
3996f34b 661 register double __value; \
33127459 662 register int __clobbered; \
3996f34b
UD
663 __asm __volatile__ \
664 ("1: fprem1\n\t" \
665 "fstsw %%ax\n\t" \
666 "sahf\n\t" \
667 "jp 1b" \
33127459 668 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
3996f34b
UD
669 return __value)
670
b20e47cb 671
7799b7b3 672/* This function is used in the `isfinite' macro. */
7799b7b3 673__MATH_INLINE int
cc46c92d 674__finite (double __x) __THROW
7799b7b3 675{
db24ce47 676 return (__extension__
e150fddc 677 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
77faa354 678 | 0x800fffffu) + 1) >> 31));
7799b7b3 679}
dd33e89f 680
3996f34b 681/* Miscellaneous functions */
f9c9dc78 682#ifdef __FAST_MATH__
3996f34b 683__inline_mathcode (__coshm1, __x, \
8f2ece69 684 register long double __exm1 = __expm1l (__fabsl (__x)); \
3996f34b
UD
685 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
686
687__inline_mathcode (__acosh1p, __x, \
0135bde4 688 return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0)))
3996f34b 689
f9c9dc78 690#endif /* __FAST_MATH__ */
b20e47cb
RM
691#endif /* __USE_MISC */
692
3996f34b 693/* Undefine some of the large macros which are not used anymore. */
3996f34b 694#undef __atan2_code
378fbeb4
UD
695#ifdef __FAST_MATH__
696# undef __expm1_code
697# undef __exp_code
698# undef __sincos_code
699#endif /* __FAST_MATH__ */
3996f34b 700
b20e47cb 701#endif /* __NO_MATH_INLINES */
f43ce637
UD
702
703
704/* This code is used internally in the GNU libc. */
f43ce637
UD
705#ifdef __LIBC_INTERNAL_MATH_INLINES
706__inline_mathop (__ieee754_sqrt, "fsqrt")
bd355af0
UD
707__inline_mathcode2 (__ieee754_atan2, __y, __x,
708 register long double __value;
709 __asm __volatile__ ("fpatan\n\t"
710 : "=t" (__value)
711 : "0" (__x), "u" (__y) : "st(1)");
712 return __value;)
f43ce637
UD
713#endif
714
b20e47cb 715#endif /* __GNUC__ */