]>
sourceware.org Git - glibc.git/blob - sysdeps/i386/fpu/bits/mathinline.h
4228959d23886fb38a7f560adb0ce3c4e7deb75a
1 /* Inline math functions for i387.
2 Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by John C. Bowman <bowman@ipp-garching.mpg.de>, 1995.
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.
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.
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. */
21 #ifndef _BITS_MATHINLINE_H
22 #define _BITS_MATHINLINE_H 1
25 #if defined __USE_ISOC9X && defined __GNUC__ && __GNUC__ >= 2
26 /* ISO C 9X defines some macros to perform unordered comparisons. The
27 ix87 FPU supports this with special opcodes and we should use them.
28 These must not be inline functions since we have to be able to handle
29 all floating-point types. */
30 # define isgreater(x, y) \
32 __asm__ ("fucompp; fnstsw; andb $0x45, %%ah; setz %%al;" \
34 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
37 # define isgreaterequal(x, y) \
39 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al;" \
41 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
44 # define isless(x, y) \
46 __asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x45, %%ah;" \
47 "setz %%al; andl $0x01, %0" \
48 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
51 # define islessequal(x, y) \
53 __asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x05, %%ah;" \
54 "setz %%al; andl $0x01, %0" \
55 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
58 # define islessgreater(x, y) \
60 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al;" \
62 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
65 # define isunordered(x, y) \
67 __asm__ ("fucompp; fnstsw; sahf; setp %%al; andl $0x01, %0" \
68 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
73 #if defined __GNUC__ && \
74 (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ <= 7))
75 /* gcc 2.7.2 and 2.7.2.1 have problems with inlining `long double'
76 functions so we disable this now. */
77 # undef __NO_MATH_INLINES
78 # define __NO_MATH_INLINES
83 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
86 # define __MATH_INLINE __inline
88 # define __MATH_INLINE extern __inline
91 __MATH_INLINE
double cos (double);
92 __MATH_INLINE
double sin (double);
95 __MATH_INLINE
double __expm1 (double __x
);
99 register double __value
, __exponent
, __temp
;
101 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t"
102 "fmul %%st(1) # x * log2(e)\n\t"
104 "frndint # int(x * log2(e))\n\t"
106 "fsub %%st(1) # fract(x * log2(e))\n\t"
107 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
108 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
109 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
111 ("fscale # 2^int(x * log2(e))\n\t"
112 : "=t" (__temp
) : "0" (1.0), "u" (__exponent
));
115 return __temp
+ __value
;
118 __MATH_INLINE
double __sgn1 (double __x
);
122 return __x
>= 0.0 ? 1.0 : -1.0;
125 __MATH_INLINE
double sqrt (double __x
);
129 register double __value
;
132 : "=t" (__value
) : "0" (__x
));
137 __MATH_INLINE
double fabs (double __x
);
141 register double __value
;
144 : "=t" (__value
) : "0" (__x
));
149 /* The argument range of this inline version is limited. */
150 __MATH_INLINE
double sin (double __x
);
154 register double __value
;
157 : "=t" (__value
) : "0" (__x
));
162 /* The argument range of this inline version is limited. */
163 __MATH_INLINE
double cos (double __x
);
167 register double __value
;
170 : "=t" (__value
): "0" (__x
));
175 __MATH_INLINE
double tan (double __x
);
179 register double __value
;
180 register double __value2
__attribute__ ((unused
));
183 : "=t" (__value2
), "=u" (__value
) : "0" (__x
));
188 __MATH_INLINE
double atan2 (double __y
, double __x
);
190 atan2 (double __y
, double __x
)
192 register double __value
;
196 : "=t" (__value
) : "0" (__x
), "u" (__y
));
201 __MATH_INLINE
double asin (double __x
);
205 return atan2 (__x
, sqrt (1.0 - __x
* __x
));
208 __MATH_INLINE
double acos (double __x
);
212 return atan2 (sqrt (1.0 - __x
* __x
), __x
);
215 __MATH_INLINE
double atan (double __x
);
219 register double __value
;
223 : "=t" (__value
) : "0" (__x
));
228 __MATH_INLINE
double exp (double __x
);
232 register double __value
, __exponent
;
234 ("fldl2e # e^x = 2^(x * log2(e))\n\t"
235 "fmul %%st(1) # x * log2(e)\n\t"
237 "frndint # int(x * log2(e))\n\t"
239 "fsub %%st(1) # fract(x * log2(e))\n\t"
240 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
241 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
245 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
250 __MATH_INLINE
double sinh (double __x
);
254 register double __exm1
= __expm1 (fabs (__x
));
256 return 0.5 * (__exm1
/ (__exm1
+ 1.0) + __exm1
) * __sgn1 (__x
);
259 __MATH_INLINE
double cosh (double __x
);
263 register double __ex
= exp (__x
);
265 return 0.5 * (__ex
+ 1.0 / __ex
);
268 __MATH_INLINE
double tanh (double __x
);
272 register double __exm1
= __expm1 (-fabs (__x
+ __x
));
274 return __exm1
/ (__exm1
+ 2.0) * __sgn1 (-__x
);
277 __MATH_INLINE
double log (double __x
);
281 register double __value
;
286 : "=t" (__value
) : "0" (__x
));
291 __MATH_INLINE
double log10 (double __x
);
295 register double __value
;
300 : "=t" (__value
) : "0" (__x
));
305 __MATH_INLINE
double __log2 (double __x
);
309 register double __value
;
312 : "=t" (__value
) : "0" (__x
), "u" (1.0));
317 __MATH_INLINE
double fmod (double __x
, double __y
);
319 fmod (double __x
, double __y
)
321 register double __value
;
327 : "=t" (__value
) : "0" (__x
), "u" (__y
) : "ax", "cc");
332 __MATH_INLINE
double ldexp (double __x
, int __y
);
334 ldexp (double __x
, int __y
)
336 register double __value
;
339 : "=t" (__value
) : "0" (__x
), "u" ((double) __y
));
344 __MATH_INLINE
double pow (double __x
, double __y
);
346 pow (double __x
, double __y
)
348 register double __value
, __exponent
;
349 long __p
= (long) __y
;
351 if (__x
== 0.0 && __y
> 0.0)
353 if (__y
== (double) __p
)
375 ("fmul %%st(1) # y * log2(x)\n\t"
377 "frndint # int(y * log2(x))\n\t"
379 "fsub %%st(1) # fract(y * log2(x))\n\t"
380 "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
381 : "=t" (__value
), "=u" (__exponent
) : "0" (__log2 (__x
)), "1" (__y
));
385 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
390 __MATH_INLINE
double floor (double __x
);
394 register double __value
;
395 __volatile
unsigned short int __cw
, __cwtmp
;
397 __asm
__volatile ("fnstcw %0" : "=m" (__cw
));
398 __cwtmp
= (__cw
& 0xf3ff) | 0x0400; /* rounding down */
399 __asm
__volatile ("fldcw %0" : : "m" (__cwtmp
));
400 __asm
__volatile ("frndint" : "=t" (__value
) : "0" (__x
));
401 __asm
__volatile ("fldcw %0" : : "m" (__cw
));
406 __MATH_INLINE
double ceil (double __x
);
410 register double __value
;
411 __volatile
unsigned short int __cw
, __cwtmp
;
413 __asm
__volatile ("fnstcw %0" : "=m" (__cw
));
414 __cwtmp
= (__cw
& 0xf3ff) | 0x0800; /* rounding up */
415 __asm
__volatile ("fldcw %0" : : "m" (__cwtmp
));
416 __asm
__volatile ("frndint" : "=t" (__value
) : "0" (__x
));
417 __asm
__volatile ("fldcw %0" : : "m" (__cw
));
423 /* Optimized versions for some non-standardized functions. */
424 #if defined __USE_ISOC9X || defined __USE_MISC
426 __MATH_INLINE
double hypot (double __x
, double __y
);
428 hypot (double __x
, double __y
)
430 return sqrt (__x
* __x
+ __y
* __y
);
433 /* We cannot rely on M_SQRT being defined. So we do it for ourself
435 # define __M_SQRT2 _Mldbl(1.41421356237309504880) /* sqrt(2) */
437 __MATH_INLINE
double log1p (double __x
);
441 register double __value
;
443 if (fabs (__x
) >= 1.0 - 0.5 * __M_SQRT2
)
444 __value
= log (1.0 + __x
);
450 : "=t" (__value
) : "0" (__x
));
455 __MATH_INLINE
double asinh (double __x
);
459 register double __y
= fabs (__x
);
461 return log1p ((__y
* __y
/ (sqrt (__y
* __y
+ 1.0) + 1.0) + __y
)
465 __MATH_INLINE
double acosh (double __x
);
469 return log (__x
+ sqrt (__x
- 1.0) * sqrt (__x
+ 1.0));
472 __MATH_INLINE
double atanh (double __x
);
476 register double __y
= fabs (__x
);
478 return -0.5 * __log1p (-(__y
+ __y
) / (1.0 + __y
)) * __sgn1 (__x
);
481 __MATH_INLINE
double logb (double __x
);
485 register double __value
, __junk
;
488 : "=t" (__junk
), "=u" (__value
) : "0" (__x
));
496 __MATH_INLINE
double drem (double __x
, double __y
);
498 drem (double __x
, double __y
)
500 register double __value
;
506 : "=t" (__value
) : "0" (__x
), "u" (__y
) : "ax", "cc");
511 /* This function is used in the `isfinite' macro. */
512 __MATH_INLINE
int __finite (double __x
);
514 __finite (double __x
)
516 register int __result
;
518 ("orl $0x800fffff, %0\n\t"
521 : "=q" (__result
) : "0" (((int *) &__x
)[1]));
525 __MATH_INLINE
double coshm1 (double __x
);
529 register double __exm1
= __expm1 (fabs (__x
));
531 return 0.5 * (__exm1
/ (__exm1
+ 1.0)) * __exm1
;
534 __MATH_INLINE
double acosh1p (double __x
);
538 return __log1p (__x
+ sqrt (__x
) * sqrt (__x
+ 2.0));
541 __MATH_INLINE
void sincos (double __x
, double *__sinx
, double *__cosx
);
543 sincos (double __x
, double *__sinx
, double *__cosx
)
545 register double __cosr
, __sinr
;
549 "testl $0x400, %%eax\n\t"
556 "testl $0x400, %%eax\n\t"
561 : "=t" (__cosr
), "=u" (__sinr
) : "0" (__x
));
567 __MATH_INLINE
double sgn (double __x
);
571 return __x
== 0.0 ? 0.0 : (__x
> 0.0 ? 1.0 : -1.0);
574 __MATH_INLINE
double pow2 (double __x
);
578 register double __value
, __exponent
;
579 long __p
= (long) __x
;
581 if (__x
== (double) __p
)
582 return ldexp (1.0, __p
);
586 "frndint # int(x)\n\t"
588 "fsub %%st(1) # fract(x)\n\t"
589 "f2xm1 # 2^(fract(x)) - 1\n\t"
590 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
594 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
599 #endif /* __USE_MISC */
601 #endif /* __NO_MATH_INLINES */
602 #endif /* __GNUC__ */
604 #endif /* _BITS_MATHINLINE_H */
This page took 0.064303 seconds and 4 git commands to generate.