diff options
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/i386/fpu/s_expm1.S | 22 | ||||
-rw-r--r-- | sysdeps/i386/fpu/s_expm1f.S | 22 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/s_expm1.c | 6 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/wordsize-64/e_cosh.c | 3 | ||||
-rw-r--r-- | sysdeps/ieee754/flt-32/s_expm1f.c | 6 |
5 files changed, 58 insertions, 1 deletions
diff --git a/sysdeps/i386/fpu/s_expm1.S b/sysdeps/i386/fpu/s_expm1.S index 65426c5984..05e5285d7b 100644 --- a/sysdeps/i386/fpu/s_expm1.S +++ b/sysdeps/i386/fpu/s_expm1.S @@ -37,6 +37,13 @@ one: .double 1.0 l2e: .tfloat 1.442695040888963407359924681002 ASM_SIZE_DIRECTIVE(l2e) + .section .rodata.cst8,"aM",@progbits,8 + + .p2align 3 + .type dbl_min,@object +dbl_min: .byte 0, 0, 0, 0, 0, 0, 0x10, 0 + ASM_SIZE_DIRECTIVE(dbl_min) + #ifdef PIC #define MO(op) op##@GOTOFF(%edx) #else @@ -74,6 +81,21 @@ ENTRY(__expm1) #ifdef PIC LOAD_PIC_REG (dx) #endif + fld %st + fabs + fcoml MO(dbl_min) + fstp %st + fnstsw + sahf + jae 5f + subl $8, %esp + cfi_adjust_cfa_offset (8) + fld %st(0) + fmul %st(0) + fstpl (%esp) + addl $8, %esp + cfi_adjust_cfa_offset (-8) + ret 5: fldt MO(l2e) // log2(e) : x fmulp // log2(e)*x diff --git a/sysdeps/i386/fpu/s_expm1f.S b/sysdeps/i386/fpu/s_expm1f.S index 748b7b8791..a83e435e22 100644 --- a/sysdeps/i386/fpu/s_expm1f.S +++ b/sysdeps/i386/fpu/s_expm1f.S @@ -37,6 +37,13 @@ one: .double 1.0 l2e: .tfloat 1.442695040888963407359924681002 ASM_SIZE_DIRECTIVE(l2e) + .section .rodata.cst4,"aM",@progbits,4 + + .p2align 2 + .type flt_min,@object +flt_min: .byte 0, 0, 0x80, 0 + ASM_SIZE_DIRECTIVE(flt_min) + #ifdef PIC #define MO(op) op##@GOTOFF(%edx) #else @@ -74,6 +81,21 @@ ENTRY(__expm1f) #ifdef PIC LOAD_PIC_REG (dx) #endif + fld %st + fabs + fcoms MO(flt_min) + fstp %st + fnstsw + sahf + jae 5f + subl $4, %esp + cfi_adjust_cfa_offset (4) + fld %st(0) + fmul %st(0) + fstps (%esp) + addl $4, %esp + cfi_adjust_cfa_offset (-4) + ret 5: fldt MO(l2e) // log2(e) : x fmulp // log2(e)*x diff --git a/sysdeps/ieee754/dbl-64/s_expm1.c b/sysdeps/ieee754/dbl-64/s_expm1.c index 9c9bb34559..41ef63a786 100644 --- a/sysdeps/ieee754/dbl-64/s_expm1.c +++ b/sysdeps/ieee754/dbl-64/s_expm1.c @@ -109,6 +109,7 @@ */ #include <errno.h> +#include <float.h> #include <math.h> #include <math_private.h> #define one Q[0] @@ -194,6 +195,11 @@ __expm1 (double x) } else if (hx < 0x3c900000) /* when |x|<2**-54, return x */ { + if (fabs (x) < DBL_MIN) + { + double force_underflow = x * x; + math_force_eval (force_underflow); + } t = huge + x; /* return x with inexact flags when x!=0 */ return x - (t - (huge + x)); } diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/e_cosh.c b/sysdeps/ieee754/dbl-64/wordsize-64/e_cosh.c index 84593521cc..fca80b13f9 100644 --- a/sysdeps/ieee754/dbl-64/wordsize-64/e_cosh.c +++ b/sysdeps/ieee754/dbl-64/wordsize-64/e_cosh.c @@ -50,9 +50,10 @@ __ieee754_cosh (double x) if (ix < 0x40360000) { /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if(ix<0x3fd62e43) { + if (ix<0x3c800000) /* cosh(tiny) = 1 */ + return one; t = __expm1(fabs(x)); w = one+t; - if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ return one+(t*t)/(w+w); } diff --git a/sysdeps/ieee754/flt-32/s_expm1f.c b/sysdeps/ieee754/flt-32/s_expm1f.c index ca8839fa22..c81b057f24 100644 --- a/sysdeps/ieee754/flt-32/s_expm1f.c +++ b/sysdeps/ieee754/flt-32/s_expm1f.c @@ -14,6 +14,7 @@ */ #include <errno.h> +#include <float.h> #include <math.h> #include <math_private.h> @@ -80,6 +81,11 @@ __expm1f(float x) c = (hi-x)-lo; } else if(hx < 0x33000000) { /* when |x|<2**-25, return x */ + if (fabsf (x) < FLT_MIN) + { + float force_underflow = x * x; + math_force_eval (force_underflow); + } t = huge+x; /* return x with inexact flags when x!=0 */ return x - (t-(huge+x)); } |