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 __MATH_INLINE
double log1p (double __x
);
389 register double __value
;
391 if (fabs (__x
) >= 1.0 - 0.5 * M_SQRT2
)
392 __value
= log (1.0 + __x
);
398 : "=t" (__value
) : "0" (__x
));
403 __MATH_INLINE
double asinh (double __x
);
407 register double __y
= fabs (__x
);
409 return log1p ((__y
* __y
/ (sqrt (__y
* __y
+ 1.0) + 1.0) + __y
)
413 __MATH_INLINE
double acosh (double __x
);
417 return log (__x
+ sqrt (__x
- 1.0) * sqrt (__x
+ 1.0));
420 __MATH_INLINE
double atanh (double __x
);
424 register double __y
= fabs (__x
);
426 return -0.5 * __log1p (-(__y
+ __y
) / (1.0 + __y
)) * __sgn1 (__x
);
429 __MATH_INLINE
double logb (double __x
);
433 register double __value
;
436 : "=t" (__value
) : "0" (__x
));
441 __MATH_INLINE
double drem (double __x
, double __y
);
443 drem (double __x
, double __y
)
445 register double __value
;
451 : "=t" (__value
) : "0" (__x
), "u" (__y
) : "ax", "cc");
456 /* This function is used in the `isfinite' macro. */
457 __MATH_INLINE
int __finite (double __x
);
459 __finite (double __x
)
461 register int __result
;
463 ("orl $x0x800fffff, %0\n\t"
466 : "=q" (__result
) : "0" (((int *) &__x
)[1]));
472 __MATH_INLINE
double coshm1 (double __x
);
476 register double __exm1
= __expm1 (fabs (__x
));
478 return 0.5 * (__exm1
/ (__exm1
+ 1.0)) * __exm1
;
481 __MATH_INLINE
double acosh1p (double __x
);
485 return __log1p (__x
+ sqrt (__x
) * sqrt (__x
+ 2.0));
488 __MATH_INLINE
void sincos (double __x
, double *__sinx
, double *__cosx
);
490 sincos (double __x
, double *__sinx
, double *__cosx
)
492 register double __cosr
, __sinr
;
496 "testl $0x400, %%eax\n\t"
503 "testl $0x400, %%eax\n\t"
508 : "=t" (__cosr
), "=u" (__sinr
) : "0" (__x
));
514 __MATH_INLINE
double sgn (double __x
);
518 return __x
== 0.0 ? 0.0 : (__x
> 0.0 ? 1.0 : -1.0);
521 __MATH_INLINE
double pow2 (double __x
);
525 register double __value
, __exponent
;
526 long __p
= (long) __x
;
528 if (__x
== (double) __p
)
529 return ldexp (1.0, __p
);
533 "frndint # int(x)\n\t"
535 "fsub %%st(1) # fract(x)\n\t"
536 "f2xm1 # 2^(fract(x)) - 1\n\t"
537 : "=t" (__value
), "=u" (__exponent
) : "0" (__x
));
541 : "=t" (__value
) : "0" (__value
), "u" (__exponent
));
546 #endif /* __USE_MISC */
548 #endif /* __NO_MATH_INLINES */
549 #endif /* __GNUC__ */
551 #endif /* __MATH_H */