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