]> 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.
1228ed5c 2 Copyright (C) 1995, 1996, 1997 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; \
42 __asm__ ("fucomip; seta %%al" \
43 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
44 __result; })
45# define isgreaterequal(x, y) \
46 ({ register char __result; \
47 __asm__ ("fucomip; setae %%al" \
48 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
49 __result; })
50
51# define isless(x, y) \
52 ({ register char __result; \
53 __asm__ ("fucomip; setb %%al" \
54 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
55 __result; })
56
57# define islessequal(x, y) \
58 ({ register char __result; \
59 __asm__ ("fucomip; setbe %%al" \
60 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
61 __result; })
62
63# define islessgreater(x, y) \
64 ({ register char __result; \
65 __asm__ ("fucomip; setne %%al" \
66 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
67 __result; })
68
69# define isunordered(x, y) \
70 ({ register char __result; \
71 __asm__ ("fucomip; setp %%al" \
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; \
f43ce637 90 __asm__ ("fucompp; fnstsw; sahf; setb %%al" \
3996f34b
UD
91 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
92 __result; })
cd6ede75 93
f43ce637 94# define islessequal(x, y) \
9a0a462c 95 ({ register char __result; \
f43ce637 96 __asm__ ("fucompp; fnstsw; sahf; setbe %%al" \
3996f34b
UD
97 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
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
f43ce637
UD
113/* XXX Argh!!! More compiler errors. */
114#if 0
115/* Test for negative number. Used in the signbit() macro. */
116__MATH_INLINE int
117__signbitf (float __x)
118{
119 union { float __f; int __i; } __u = { __f: __x }; return __u.__i < 0;
120}
121__MATH_INLINE int
122__signbit (double __x)
123{
124 union { double __d; int __i[2]; } __u = { __d: __x }; return __u.__i[1] < 0;
125}
126__MATH_INLINE int
127__signbitl (long double __x)
128{
129 union { long double __l; int __i[3]; } __u = { __l: __x };
130 return (__u.__i[2] & 0x8000) != 0;
131}
132#endif
133#endif
cd6ede75 134
b20e47cb 135
f41c8091
UD
136/* The gcc, version 2.7 or below, has problems with all this inlining
137 code. So disable it for this version of the compiler. */
f43ce637 138#if defined __GNUC__ && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7))
f41c8091 139
f43ce637
UD
140#if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
141 && defined __OPTIMIZE__)
b20e47cb 142
3996f34b
UD
143/* A macro to define float, double, and long double versions of various
144 math functions for the ix87 FPU. FUNC is the function name (which will
145 be suffixed with f and l for the float and long double version,
146 respectively). OP is the name of the FPU operation. */
b20e47cb 147
3996f34b
UD
148#if defined __USE_MISC || defined __USE_ISOC9X
149# define __inline_mathop(func, op) \
150 __inline_mathop_ (double, func, op) \
151 __inline_mathop_ (float, __CONCAT(func,f), op) \
152 __inline_mathop_ (long double, __CONCAT(func,l), op)
153#else
154# define __inline_mathop(func, op) \
155 __inline_mathop_ (double, func, op)
156#endif
b20e47cb 157
3996f34b
UD
158#define __inline_mathop_(float_type, func, op) \
159 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
b20e47cb 160
b20e47cb 161
3996f34b
UD
162#if defined __USE_MISC || defined __USE_ISOC9X
163# define __inline_mathop_decl(func, op, params...) \
164 __inline_mathop_decl_ (double, func, op, params) \
165 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
166 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
167#else
168# define __inline_mathop_decl(func, op, params...) \
169 __inline_mathop_decl_ (double, func, op, params)
170#endif
b20e47cb 171
3996f34b 172#define __inline_mathop_decl_(float_type, func, op, params...) \
8f2ece69
UD
173 __MATH_INLINE float_type func (float_type); \
174 __MATH_INLINE float_type func (float_type __x) \
3996f34b
UD
175 { \
176 register float_type __result; \
8f2ece69 177 __asm __volatile__ (op : "=t" (__result) : params); \
3996f34b
UD
178 return __result; \
179 }
180
181
182#if defined __USE_MISC || defined __USE_ISOC9X
183# define __inline_mathcode(func, arg, code) \
184 __inline_mathcode_ (double, func, arg, code) \
185 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
186 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
1ea89a40
UD
187# define __inline_mathcode2(func, arg1, arg2, code) \
188 __inline_mathcode2_ (double, func, arg1, arg2, code) \
189 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
190 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
191# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
192 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
193 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
194 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
3996f34b
UD
195#else
196# define __inline_mathcode(func, arg, code) \
1ea89a40
UD
197 __inline_mathcode_ (double, func, (arg), code)
198# define __inline_mathcode2(func, arg1, arg2, code) \
199 __inline_mathcode2_ (double, func, arg1, arg2, code)
200# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
201 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
3996f34b 202#endif
b20e47cb 203
3996f34b
UD
204#define __inline_mathcode_(float_type, func, arg, code) \
205 __MATH_INLINE float_type func (float_type); \
206 __MATH_INLINE float_type func (float_type arg) \
207 { \
208 code; \
209 }
b20e47cb 210
3996f34b
UD
211#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
212 __MATH_INLINE float_type func (float_type, float_type); \
213 __MATH_INLINE float_type func (float_type arg1, float_type arg2) \
214 { \
215 code; \
216 }
217
1ea89a40
UD
218#define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
219 __MATH_INLINE float_type func (float_type, float_type, float_type); \
220 __MATH_INLINE float_type func (float_type arg1, float_type arg2, \
221 float_type arg3) \
222 { \
223 code; \
224 }
f43ce637 225#endif
1ea89a40 226
3996f34b 227
f43ce637 228#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
f41c8091
UD
229/* Miscellaneous functions */
230
231__inline_mathcode (__sgn, __x, \
232 return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
233
234__inline_mathcode (__pow2, __x, \
235 register long double __value; \
236 register long double __exponent; \
237 long int __p = (long int) __x; \
238 if (__x == (long double) __p) \
239 { \
240 __asm __volatile__ \
241 ("fscale" \
242 : "=t" (__value) : "0" (1.0), "u" (__x)); \
243 return __value; \
244 } \
245 __asm __volatile__ \
246 ("fldl %%st(0)\n\t" \
247 "frndint # int(x)\n\t" \
248 "fxch\n\t" \
249 "fsub %%st(1) # fract(x)\n\t" \
250 "f2xm1 # 2^(fract(x)) - 1\n\t" \
251 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
252 __value += 1.0; \
253 __asm __volatile__ \
254 ("fscale" \
255 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
256 return __value)
257
258#define __sincos_code \
259 register long double __cosr; \
260 register long double __sinr; \
261 __asm __volatile__ \
262 ("fsincos\n\t" \
263 "fnstsw %%ax\n\t" \
264 "testl $0x400, %%eax\n\t" \
265 "jz 1f\n\t" \
266 "fldpi\n\t" \
267 "fadd %%st(0)\n\t" \
268 "fxch %%st(1)\n\t" \
269 "2: fprem1\n\t" \
270 "fnstsw %%ax\n\t" \
271 "testl $0x400, %%eax\n\t" \
272 "jnz 2b\n\t" \
273 "fstp %%st(1)\n\t" \
274 "fsincos\n\t" \
275 "1:" \
276 : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
277 *__sinx = __sinr; \
278 *__cosx = __cosr
279
280__MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx);
281__MATH_INLINE void
282__sincos (double __x, double *__sinx, double *__cosx)
283{
284 __sincos_code;
285}
286
287__MATH_INLINE void __sincosf (float __x, float *__sinx, float *__cosx);
288__MATH_INLINE void
289__sincosf (float __x, float *__sinx, float *__cosx)
290{
291 __sincos_code;
292}
293
294__MATH_INLINE void __sincosl (long double __x, long double *__sinx,
295 long double *__cosx);
296__MATH_INLINE void
297__sincosl (long double __x, long double *__sinx, long double *__cosx)
298{
299 __sincos_code;
300}
301
302
8f2ece69 303/* Optimized inline implementation, sometimes with reduced precision
3996f34b 304 and/or argument range. */
8f2ece69 305
3996f34b
UD
306#define __expm1_code \
307 register long double __value; \
308 register long double __exponent; \
309 register long double __temp; \
310 __asm __volatile__ \
311 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
312 "fmul %%st(1) # x * log2(e)\n\t" \
313 "fstl %%st(1)\n\t" \
314 "frndint # int(x * log2(e))\n\t" \
315 "fxch\n\t" \
316 "fsub %%st(1) # fract(x * log2(e))\n\t" \
317 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
318 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
319 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
320 __asm __volatile__ \
321 ("fscale # 2^int(x * log2(e))\n\t" \
322 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
323 __temp -= 1.0; \
324 return __temp + __value
325__inline_mathcode_ (long double, __expm1l, __x, __expm1_code)
326
327
328#define __exp_code \
329 register long double __value; \
330 register long double __exponent; \
331 __asm __volatile__ \
332 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
333 "fmul %%st(1) # x * log2(e)\n\t" \
334 "fstl %%st(1)\n\t" \
335 "frndint # int(x * log2(e))\n\t" \
336 "fxch\n\t" \
337 "fsub %%st(1) # fract(x * log2(e))\n\t" \
338 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
339 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
340 __value += 1.0; \
341 __asm __volatile__ \
342 ("fscale" \
343 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
344 return __value
345__inline_mathcode (exp, __x, __exp_code)
346__inline_mathcode_ (long double, __expl, __x, __exp_code)
347
348
349__inline_mathcode (tan, __x, \
350 register long double __value; \
351 register long double __value2 __attribute__ ((unused)); \
352 __asm __volatile__ \
353 ("fptan" \
354 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
355 return __value)
356
357
358#define __atan2_code \
359 register long double __value; \
360 __asm __volatile__ \
361 ("fpatan\n\t" \
362 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
363 return __value
364__inline_mathcode2 (atan2, __y, __x, __atan2_code)
365__inline_mathcode2_ (long double, __atan2l, __y, __x, __atan2_code)
366
367
368__inline_mathcode2 (fmod, __x, __y, \
369 register long double __value; \
370 __asm __volatile__ \
371 ("1: fprem\n\t" \
372 "fnstsw %%ax\n\t" \
373 "sahf\n\t" \
374 "jp 1b" \
375 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
376 return __value)
377
378
379__inline_mathcode2 (pow, __x, __y, \
380 register long double __value; \
381 register long double __exponent; \
382 long int __p = (long int) __y; \
383 if (__x == 0.0 && __y > 0.0) \
384 return 0.0; \
385 if (__y == (double) __p) \
386 { \
387 long double __r = 1.0; \
388 if (__p == 0) \
389 return 1.0; \
390 if (__p < 0) \
391 { \
392 __p = -__p; \
393 __x = 1.0 / __x; \
394 } \
395 while (1) \
396 { \
397 if (__p & 1) \
398 __r *= __x; \
399 __p >>= 1; \
400 if (__p == 0) \
401 return __r; \
402 __x *= __x; \
403 } \
404 /* NOTREACHED */ \
405 } \
406 __asm __volatile__ \
8f2ece69 407 ("fyl2x" : "=t" (__value) : "0" (__x), "u" (1.0) : "st(1)"); \
3996f34b
UD
408 __asm __volatile__ \
409 ("fmul %%st(1) # y * log2(x)\n\t" \
410 "fst %%st(1)\n\t" \
411 "frndint # int(y * log2(x))\n\t" \
412 "fxch\n\t" \
413 "fsub %%st(1) # fract(y * log2(x))\n\t" \
414 "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" \
415 : "=t" (__value), "=u" (__exponent) : "0" (__y), "1" (__value)); \
416 __value += 1.0; \
417 __asm __volatile__ \
418 ("fscale" \
419 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
420 return __value)
421
422
423__inline_mathop (sqrt, "fsqrt")
424__inline_mathop_ (long double, __sqrtl, "fsqrt")
425
8f2ece69 426#if defined __GNUC__ && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 8)
f41c8091
UD
427__inline_mathcode_ (double, fabs, __x, return __builtin_fabs (__x))
428__inline_mathcode_ (float, fabsf, __x, return __builtin_fabsf (__x))
429__inline_mathcode_ (long double, fabsl, __x, return __builtin_fabsl (__x))
430__inline_mathcode_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
8f2ece69 431#else
3996f34b 432__inline_mathop (fabs, "fabs")
8f2ece69
UD
433__inline_mathop_ (long double, __fabsl, "fabs")
434#endif
3996f34b
UD
435
436/* The argument range of this inline version is reduced. */
437__inline_mathop (sin, "fsin")
438/* The argument range of this inline version is reduced. */
439__inline_mathop (cos, "fcos")
440
ca34d7a7 441__inline_mathop (atan, "fld1; fpatan")
3996f34b
UD
442__inline_mathop (log, "fldln2; fxch; fyl2x")
443__inline_mathop (log10, "fldlg2; fxch; fyl2x")
444
445__inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
446__inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
447
8f2ece69 448__inline_mathcode_ (long double, __sgn1l, __x, return __x >= 0.0 ? 1.0 : -1.0)
3996f34b
UD
449
450
451/* The argument range of the inline version of sinhl is slightly reduced. */
452__inline_mathcode (sinh, __x, \
8f2ece69 453 register long double __exm1 = __expm1l (__fabsl (__x)); \
3996f34b
UD
454 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
455
456__inline_mathcode (cosh, __x, \
457 register long double __ex = __expl (__x); \
458 return 0.5 * (__ex + 1.0 / __ex))
459
460__inline_mathcode (tanh, __x, \
8f2ece69 461 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
3996f34b
UD
462 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
463
464
465__inline_mathcode (floor, __x, \
466 register long double __value; \
467 __volatile unsigned short int __cw; \
468 __volatile unsigned short int __cwtmp; \
469 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
470 __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
471 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
472 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
473 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
474 return __value)
475
476__inline_mathcode (ceil, __x, \
477 register long double __value; \
478 __volatile unsigned short int __cw; \
479 __volatile unsigned short int __cwtmp; \
480 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
481 __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
482 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
483 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
484 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
485 return __value)
b20e47cb 486
8f2ece69
UD
487#define __ldexp_code \
488 register long double __value; \
489 __asm __volatile__ \
490 ("fscale" \
491 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
492 return __value
493
494__MATH_INLINE double ldexp (double __x, int __y);
495__MATH_INLINE double
496ldexp (double __x, int __y)
497{
498 __ldexp_code;
499}
500
b20e47cb
RM
501
502/* Optimized versions for some non-standardized functions. */
7799b7b3 503#if defined __USE_ISOC9X || defined __USE_MISC
b20e47cb 504
f41c8091 505__inline_mathop(log2, "fld1; fxch; fyl2x")
3996f34b
UD
506
507__inline_mathcode (expm1, __x, __expm1_code)
b20e47cb 508
714a562f
UD
509/* We cannot rely on M_SQRT being defined. So we do it for ourself
510 here. */
ae1025be 511# define __M_SQRT2 _Mldbl(1.41421356237309504880) /* sqrt(2) */
714a562f 512
3996f34b
UD
513__inline_mathcode (log1p, __x, \
514 register long double __value; \
8f2ece69 515 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
3996f34b
UD
516 __value = logl (1.0 + __x); \
517 else \
518 __asm __volatile__ \
519 ("fldln2\n\t" \
520 "fxch\n\t" \
521 "fyl2xp1" \
522 : "=t" (__value) : "0" (__x)); \
523 return __value)
524
525
526/* The argument range of the inline version of asinhl is slightly reduced. */
527__inline_mathcode (asinh, __x, \
8f2ece69 528 register long double __y = __fabsl (__x); \
3996f34b 529 return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y) \
ca34d7a7 530 * __sgn1l (__x)))
3996f34b
UD
531
532__inline_mathcode (acosh, __x, \
533 return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
534
535__inline_mathcode (atanh, __x, \
8f2ece69 536 register long double __y = __fabsl (__x); \
3996f34b
UD
537 return (-0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * \
538 __sgn1l (__x)))
539
540
541/* The argument range of the inline version of hypotl is slightly reduced. */
542__inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
543
544__inline_mathcode(logb, __x, \
545 register long double __value; \
546 register long double __junk; \
547 __asm __volatile__ \
548 ("fxtract\n\t" \
549 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
550 return __value)
551
8f2ece69
UD
552__MATH_INLINE float ldexpf (float __x, int __y);
553__MATH_INLINE float
554ldexpf (float __x, int __y)
555{
556 __ldexp_code;
557}
558
559__MATH_INLINE long double ldexpl (long double __x, int __y);
560__MATH_INLINE long double
561ldexpl (long double __x, int __y)
562{
563 __ldexp_code;
564}
3996f34b 565
1ea89a40 566__inline_mathcode3 (fma, __x, __y, __z, return (__x * __y) + __z)
cd6ede75
UD
567#endif
568
b20e47cb 569
cd6ede75 570#ifdef __USE_MISC
8f2ece69 571
3996f34b
UD
572__inline_mathcode2 (drem, __x, __y, \
573 register double __value; \
574 __asm __volatile__ \
575 ("1: fprem1\n\t" \
576 "fstsw %%ax\n\t" \
577 "sahf\n\t" \
578 "jp 1b" \
579 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
580 return __value)
581
b20e47cb 582
7799b7b3
UD
583/* This function is used in the `isfinite' macro. */
584__MATH_INLINE int __finite (double __x);
585__MATH_INLINE int
586__finite (double __x)
587{
588 register int __result;
589 __asm__ __volatile__
1f205a47 590 ("orl $0x800fffff, %0\n\t"
7799b7b3
UD
591 "incl %0\n\t"
592 "shrl $31, %0"
61eb22d3 593 : "=r" (__result) : "0" (((int *) &__x)[1]) : "cc");
7799b7b3
UD
594 return __result;
595}
dd33e89f 596
3996f34b
UD
597/* Miscellaneous functions */
598
3996f34b 599__inline_mathcode (__coshm1, __x, \
8f2ece69 600 register long double __exm1 = __expm1l (__fabsl (__x)); \
3996f34b
UD
601 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
602
603__inline_mathcode (__acosh1p, __x, \
604 return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
605
b20e47cb
RM
606#endif /* __USE_MISC */
607
3996f34b
UD
608/* Undefine some of the large macros which are not used anymore. */
609#undef __expm1_code
610#undef __exp_code
611#undef __atan2_code
612#undef __sincos_code
613
b20e47cb 614#endif /* __NO_MATH_INLINES */
f43ce637
UD
615
616
617/* This code is used internally in the GNU libc. */
618#if 0
619/* XXX I hate compiler bugs. The current version produces wrong code
620 if this optimization is used. */
621#ifdef __LIBC_INTERNAL_MATH_INLINES
622__inline_mathop (__ieee754_sqrt, "fsqrt")
623#endif
624#endif
625
b20e47cb 626#endif /* __GNUC__ */