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. */
24 #if defined __GNUG__ && \
25 (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ <= 7))
26 /* gcc 2.7.2 and 2.7.2.1 have problems with inlining `long double'
27 functions so we disable this now. */
28 #undef __NO_MATH_INLINES
29 #define __NO_MATH_INLINES
33 #ifndef __NO_MATH_INLINES
36 #define __MATH_INLINE __inline
38 #define __MATH_INLINE extern __inline
41 __MATH_INLINE
double cos (double);
42 __MATH_INLINE
double sin (double);
45 __MATH_INLINE
double __expm1 (double __x
);
49 register double __value
, __exponent
, __temp
;
51 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t"
52 "fmul %%st(1) # x * log2(e)\n\t"
54 "frndint # int(x * log2(e))\n\t"
56 "fsub %%st(1) # fract(x * log2(e))\n\t"
57 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
58 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
59 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
61 ("fscale # 2^int(x * log2(e))\n\t"
62 : "=t" (__temp
) : "0" (1.0), "u" (__exponent
));
65 return __temp
+ __value
;
68 __MATH_INLINE
double __sgn1 (double __x
);
72 return __x
>= 0.0 ? 1.0 : -1.0;
75 __MATH_INLINE
double sqrt (double __x
);
79 register double __value
;
82 : "=t" (__value
) : "0" (__x
));
87 __MATH_INLINE
double fabs (double __x
);
91 register double __value
;
94 : "=t" (__value
) : "0" (__x
));
99 /* The argument range of this inline version is limited. */
100 __MATH_INLINE
double sin (double __x
);
104 register double __value
;
107 : "=t" (__value
) : "0" (__x
));
112 /* The argument range of this inline version is limited. */
113 __MATH_INLINE
double cos (double __x
);
117 register double __value
;
120 : "=t" (__value
): "0" (__x
));
125 __MATH_INLINE
double tan (double __x
);
129 register double __value
;
130 register double __value2
__attribute__ ((unused
));
133 : "=t" (__value2
), "=u" (__value
) : "0" (__x
));
138 __MATH_INLINE
double atan2 (double __y
, double __x
);
140 atan2 (double __y
, double __x
)
142 register double __value
;
146 : "=t" (__value
) : "0" (__x
), "u" (__y
));
151 __MATH_INLINE
double asin (double __x
);
155 return atan2 (__x
, sqrt (1.0 - __x
* __x
));
158 __MATH_INLINE
double acos (double __x
);
162 return atan2 (sqrt (1.0 - __x
* __x
), __x
);
165 __MATH_INLINE
double atan (double __x
);
169 register double __value
;
173 : "=t" (__value
) : "0" (__x
));
178 __MATH_INLINE
double exp (double __x
);
182 register double __value
, __exponent
;
184 ("fldl2e # e^x = 2^(x * log2(e))\n\t"
185 "fmul %%st(1) # x * log2(e)\n\t"
187 "frndint # int(x * log2(e))\n\t"
189 "fsub %%st(1) # fract(x * log2(e))\n\t"
190 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
191 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
195 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
200 __MATH_INLINE
double sinh (double __x
);
204 register double __exm1
= __expm1 (fabs (__x
));
206 return 0.5 * (__exm1
/ (__exm1
+ 1.0) + __exm1
) * __sgn1 (__x
);
209 __MATH_INLINE
double cosh (double __x
);
213 register double __ex
= exp (__x
);
215 return 0.5 * (__ex
+ 1.0 / __ex
);
218 __MATH_INLINE
double tanh (double __x
);
222 register double __exm1
= __expm1 (-fabs (__x
+ __x
));
224 return __exm1
/ (__exm1
+ 2.0) * __sgn1 (-__x
);
227 __MATH_INLINE
double log (double __x
);
231 register double __value
;
236 : "=t" (__value
) : "0" (__x
));
241 __MATH_INLINE
double log10 (double __x
);
245 register double __value
;
250 : "=t" (__value
) : "0" (__x
));
255 __MATH_INLINE
double __log2 (double __x
);
259 register double __value
;
264 : "=t" (__value
) : "0" (__x
));
269 __MATH_INLINE
double fmod (double __x
, double __y
);
271 fmod (double __x
, double __y
)
273 register double __value
;
279 : "=t" (__value
) : "0" (__x
), "u" (__y
) : "ax", "cc");
284 __MATH_INLINE
double ldexp (double __x
, int __y
);
286 ldexp (double __x
, int __y
)
288 register double __value
;
291 : "=t" (__value
) : "0" (__x
), "u" ((double) __y
));
296 __MATH_INLINE
double pow (double __x
, double __y
);
298 pow (double __x
, double __y
)
300 register double __value
, __exponent
;
301 long __p
= (long) __y
;
303 if (__x
== 0.0 && __y
> 0.0)
305 if (__y
== (double) __p
)
327 ("fmul %%st(1) # y * log2(x)\n\t"
329 "frndint # int(y * log2(x))\n\t"
331 "fsub %%st(1) # fract(y * log2(x))\n\t"
332 "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
333 : "=t" (__value
), "=u" (__exponent
) : "0" (__log2 (__x
)), "1" (__y
));
337 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
342 __MATH_INLINE
double floor (double __x
);
346 register double __value
;
347 __volatile
unsigned short int __cw
, __cwtmp
;
349 __asm
__volatile ("fnstcw %0" : "=m" (__cw
));
350 __cwtmp
= (__cw
& 0xf3ff) | 0x0400; /* rounding down */
351 __asm
__volatile ("fldcw %0" : : "m" (__cwtmp
));
352 __asm
__volatile ("frndint" : "=t" (__value
) : "0" (__x
));
353 __asm
__volatile ("fldcw %0" : : "m" (__cw
));
358 __MATH_INLINE
double ceil (double __x
);
362 register double __value
;
363 __volatile
unsigned short int __cw
, __cwtmp
;
365 __asm
__volatile ("fnstcw %0" : "=m" (__cw
));
366 __cwtmp
= (__cw
& 0xf3ff) | 0x0800; /* rounding up */
367 __asm
__volatile ("fldcw %0" : : "m" (__cwtmp
));
368 __asm
__volatile ("frndint" : "=t" (__value
) : "0" (__x
));
369 __asm
__volatile ("fldcw %0" : : "m" (__cw
));
375 /* Optimized versions for some non-standardized functions. */
376 #if defined __USE_ISOC9X || defined __USE_MISC
378 __MATH_INLINE
double hypot (double __x
, double __y
);
380 hypot (double __x
, double __y
)
382 return sqrt (__x
* __x
+ __y
* __y
);
385 /* We cannot rely on M_SQRT being defined. So we do it for ourself
387 #define __M_SQRT2 _Mldbl(1.41421356237309504880) /* sqrt(2) */
389 __MATH_INLINE
double log1p (double __x
);
393 register double __value
;
395 if (fabs (__x
) >= 1.0 - 0.5 * __M_SQRT2
)
396 __value
= log (1.0 + __x
);
402 : "=t" (__value
) : "0" (__x
));
407 __MATH_INLINE
double asinh (double __x
);
411 register double __y
= fabs (__x
);
413 return log1p ((__y
* __y
/ (sqrt (__y
* __y
+ 1.0) + 1.0) + __y
)
417 __MATH_INLINE
double acosh (double __x
);
421 return log (__x
+ sqrt (__x
- 1.0) * sqrt (__x
+ 1.0));
424 __MATH_INLINE
double atanh (double __x
);
428 register double __y
= fabs (__x
);
430 return -0.5 * __log1p (-(__y
+ __y
) / (1.0 + __y
)) * __sgn1 (__x
);
433 __MATH_INLINE
double logb (double __x
);
437 register double __value
, __junk
;
440 : "=t" (__junk
), "=u" (__value
) : "0" (__x
));
445 __MATH_INLINE
double drem (double __x
, double __y
);
447 drem (double __x
, double __y
)
449 register double __value
;
455 : "=t" (__value
) : "0" (__x
), "u" (__y
) : "ax", "cc");
460 /* This function is used in the `isfinite' macro. */
461 __MATH_INLINE
int __finite (double __x
);
463 __finite (double __x
)
465 register int __result
;
467 ("orl $0x800fffff, %0\n\t"
470 : "=q" (__result
) : "0" (((int *) &__x
)[1]));
475 /* ISO C 9X defines some macros to perform unordered comparisons. The
476 ix87 FPU supports this with special opcodes and we should use them.
477 These must not be inline functions since we have to be able to handle
478 all floating-point types. */
480 #define isgreater(x, y) \
482 __asm__ ("fucompp; fnstsw; andb $0x45, %%ah; setz %%al;" \
484 : "=a" (result) : "t" (x), "u" (y) : "cc"); \
487 #undef isgreaterequal
488 #define isgreaterequal(x, y) \
490 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al;" \
492 : "=a" (result) : "t" (x), "u" (y) : "cc"); \
496 #define isless(x, y) \
498 __asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x45, %%ah;" \
499 "setz %%al; andl $0xff, %0" \
500 : "=a" (result) : "t" (x), "u" (y) : "cc"); \
504 #define islessequal(x, y) \
506 __asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x05, %%ah;" \
507 "setz %%al; andl $0xff, %0" \
508 : "=a" (result) : "t" (x), "u" (y) : "cc"); \
512 #define islessgreater(x, y) \
514 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al;" \
516 : "=a" (result) : "t" (x), "u" (y) : "cc"); \
520 #define isunordered(x, y) \
522 __asm__ ("fucompp; fnstsw; sahf; setp %%al; andl $0xff, %0" \
523 : "=a" (result) : "t" (x), "u" (y) : "cc"); \
529 __MATH_INLINE
double coshm1 (double __x
);
533 register double __exm1
= __expm1 (fabs (__x
));
535 return 0.5 * (__exm1
/ (__exm1
+ 1.0)) * __exm1
;
538 __MATH_INLINE
double acosh1p (double __x
);
542 return __log1p (__x
+ sqrt (__x
) * sqrt (__x
+ 2.0));
545 __MATH_INLINE
void sincos (double __x
, double *__sinx
, double *__cosx
);
547 sincos (double __x
, double *__sinx
, double *__cosx
)
549 register double __cosr
, __sinr
;
553 "testl $0x400, %%eax\n\t"
560 "testl $0x400, %%eax\n\t"
565 : "=t" (__cosr
), "=u" (__sinr
) : "0" (__x
));
571 __MATH_INLINE
double sgn (double __x
);
575 return __x
== 0.0 ? 0.0 : (__x
> 0.0 ? 1.0 : -1.0);
578 __MATH_INLINE
double pow2 (double __x
);
582 register double __value
, __exponent
;
583 long __p
= (long) __x
;
585 if (__x
== (double) __p
)
586 return ldexp (1.0, __p
);
590 "frndint # int(x)\n\t"
592 "fsub %%st(1) # fract(x)\n\t"
593 "f2xm1 # 2^(fract(x)) - 1\n\t"
594 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
598 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
603 #endif /* __USE_MISC */
605 #endif /* __NO_MATH_INLINES */
606 #endif /* __GNUC__ */
608 #endif /* __MATH_H */