2012-05-05 Joseph Myers <joseph@codesourcery.com>
+ [BZ #13787]
+ [BZ #13922]
+ [BZ #14036]
+ * sysdeps/i386/fpu/e_expl.S (csat): New constant.
+ (__ieee754_expl): Allow for and saturate large arguments.
+ * sysdeps/ieee754/dbl-64/w_exp.c (o_threshold): Remove variable.
+ (u_threshold): Likewise.
+ (__exp): Call __ieee754_exp before checking for overflow and
+ underflow.
+ * sysdeps/ieee754/flt-32/w_expf.c (o_threshold): Remove variable.
+ (u_threshold): Likewise.
+ (__expf): Call __ieee754_expf before checking for overflow and
+ underflow.
+ * sysdeps/ieee754/ldbl-96/w_expl.c (o_threshold): Remove variable.
+ (u_threshold): Likewise.
+ (__expl): Call __ieee754_expl before checking for overflow and
+ underflow.
+ * sysdeps/x86_64/fpu/e_expl.S (csat): New constant.
+ (__ieee754_expl): Allow for and saturate large arguments.
+ * math/libm-test.inc (exp_test): Add another test. Do not allow
+ missing overflow exception on overflow.
+ (expm1_test): Do not allow missing overflow exception on overflow.
+
* sysdeps/i386/fpu/e_expl.c: Move to ...
* sysdeps/i386/fpu/e_expl.S: ... here. Write directly in assembly
rather than using inline asm.
12047, 12340, 13058, 13525, 13526, 13527, 13528, 13529, 13530, 13531,
13532, 13533, 13547, 13551, 13552, 13553, 13555, 13559, 13566, 13583,
13592, 13618, 13637, 13656, 13658, 13673, 13691, 13695, 13704, 13705,
- 13706, 13726, 13738, 13739, 13758, 13760, 13761, 13775, 13786, 13792,
- 13806, 13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871,
- 13872, 13873, 13879, 13883, 13886, 13892, 13895, 13908, 13910, 13911,
- 13912, 13913, 13915, 13916, 13917, 13918, 13919, 13920, 13921, 13924,
- 13926, 13927, 13928, 13938, 13941, 13942, 13963, 13967, 13970, 13973,
- 14027, 14033, 14034, 14040, 14049, 14055
+ 13706, 13726, 13738, 13739, 13758, 13760, 13761, 13775, 13786, 13787,
+ 13792, 13806, 13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854,
+ 13871, 13872, 13873, 13879, 13883, 13886, 13892, 13895, 13908, 13910,
+ 13911, 13912, 13913, 13915, 13916, 13917, 13918, 13919, 13920, 13921,
+ 13922, 13924, 13926, 13927, 13928, 13938, 13941, 13942, 13963, 13967,
+ 13970, 13973, 14027, 14033, 14034, 14040, 14049, 14055
* ISO C11 support:
TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L);
#endif
- /* Bug 13922: OVERFLOW exception may be missing. */
- TEST_f_f (exp, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
+#if !(defined TEST_LDOUBLE && LDBL_MAX_EXP > 1024)
+ TEST_f_f (exp, 710, plus_infty, OVERFLOW_EXCEPTION);
+#endif
+ TEST_f_f (exp, 1e5, plus_infty, OVERFLOW_EXCEPTION);
+ TEST_f_f (exp, max_value, plus_infty, OVERFLOW_EXCEPTION);
TEST_f_f (exp, -max_value, 0);
END (exp);
#endif
errno = 0;
- /* Bug 13787: OVERFLOW exception may be missing. */
- TEST_f_f (expm1, 100000.0, plus_infty, OVERFLOW_EXCEPTION_OK);
+ TEST_f_f (expm1, 100000.0, plus_infty, OVERFLOW_EXCEPTION);
check_int ("errno for expm1(large) == ERANGE", errno, ERANGE, 0, 0, 0);
- /* Bug 13787: OVERFLOW exception may be missing. */
- TEST_f_f (expm1, max_value, plus_infty, OVERFLOW_EXCEPTION_OK);
+ TEST_f_f (expm1, max_value, plus_infty, OVERFLOW_EXCEPTION);
#ifndef TEST_LDOUBLE /* Bug 13923. */
TEST_f_f (expm1, -max_value, -1);
#endif
c1: .byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(c1)
+ ASM_TYPE_DIRECTIVE(csat,@object)
+csat: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(csat)
#ifdef PIC
# define MO(op) op##@GOTOFF(%ecx)
#ifdef PIC
LOAD_PIC_REG (cx)
#endif
+ movzwl 4+8(%esp), %eax
+ andl $0x7fff, %eax
+ cmpl $0x400d, %eax
+ jle 3f
+ /* Overflow, underflow or infinity or NaN as argument. */
fstsw %ax
movb $0x45, %dh
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
- fldl2e /* 1 log2(e) */
+ cmpb $0x01, %dh
+ je 2f /* Is +-NaN, jump. */
+ /* Overflow or underflow; saturate. */
+ fstp %st
+ fldt MO(csat)
+ andb $2, %ah
+ jz 3f
+ fchs
+3: fldl2e /* 1 log2(e) */
fmul %st(1), %st /* 1 x log2(e) */
frndint /* 1 i */
fld %st(1) /* 2 x */
#include <math.h>
#include <math_private.h>
-static const double
-o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
-u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */
-
-
/* wrapper exp */
double
__exp (double x)
{
- if (__builtin_expect (isgreater (x, o_threshold), 0))
- {
- if (_LIB_VERSION != _IEEE_)
- return __kernel_standard (x, x, 6);
- }
- else if (__builtin_expect (isless (x, u_threshold), 0))
- {
- if (_LIB_VERSION != _IEEE_)
- return __kernel_standard (x, x, 7);
- }
+ double z = __ieee754_exp (x);
+ if (__builtin_expect (!__finite (z) || z == 0, 0)
+ && __finite (x) && _LIB_VERSION != _IEEE_)
+ return __kernel_standard (x, x, 6 + !!__signbit (x));
- return __ieee754_exp (x);
+ return z;
}
hidden_def (__exp)
weak_alias (__exp, exp)
#include <math.h>
#include <math_private.h>
-static const float
-o_threshold= 8.8722831726e+01, /* 0x42b17217 */
-u_threshold= -1.0397208405e+02; /* 0xc2cff1b5 */
-
-
/* wrapper expf */
float
__expf (float x)
{
- if (__builtin_expect (isgreater (x, o_threshold), 0))
- {
- if (_LIB_VERSION != _IEEE_)
- return __kernel_standard_f (x, x, 106);
- }
- else if (__builtin_expect (isless (x, u_threshold), 0))
- {
- if (_LIB_VERSION != _IEEE_)
- return __kernel_standard_f (x, x, 107);
- }
+ float z = __ieee754_expf (x);
+ if (__builtin_expect (!__finitef (z) || z == 0, 0)
+ && __finitef (x) && _LIB_VERSION != _IEEE_)
+ return __kernel_standard_f (x, x, 106 + !!__signbitf (x));
- return __ieee754_expf (x);
+ return z;
}
hidden_def (__expf)
weak_alias (__expf, expf)
#include <math.h>
#include <math_private.h>
-static const long double
-o_threshold= 1.135652340629414394949193107797076489134e4,
- /* 0x400C, 0xB17217F7, 0xD1CF79AC */
-u_threshold= -1.140019167866942050398521670162263001513e4;
- /* 0x400C, 0xB220C447, 0x69C201E8 */
-
-
/* wrapper expl */
long double
__expl (long double x)
{
- if (__builtin_expect (isgreater (x, o_threshold), 0))
- {
- if (_LIB_VERSION != _IEEE_)
- return __kernel_standard_l (x, x, 206);
- }
- else if (__builtin_expect (isless (x, u_threshold), 0))
- {
- if (_LIB_VERSION != _IEEE_)
- return __kernel_standard_l (x, x, 207);
- }
+ long double z = __ieee754_expl (x);
+ if (__builtin_expect (!__finitel (z) || z == 0, 0)
+ && __finitel (x) && _LIB_VERSION != _IEEE_)
+ return __kernel_standard_l (x, x, 206 + !!__signbitl (x));
- return __ieee754_expl (x);
+ return z;
}
hidden_def (__expl)
weak_alias (__expl, expl)
c1: .byte 0x20, 0xfa, 0xee, 0xc2, 0x5f, 0x70, 0xa5, 0xec, 0xed, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(c1)
+ ASM_TYPE_DIRECTIVE(csat,@object)
+csat: .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0e, 0x40
+ .byte 0, 0, 0, 0, 0, 0
+ ASM_SIZE_DIRECTIVE(csat)
#ifdef PIC
# define MO(op) op##(%rip)
For the i686 the code can be written better.
-- drepper@cygnus.com. */
fxam /* Is NaN or +-Inf? */
+ movzwl 8+8(%rsp), %eax
+ andl $0x7fff, %eax
+ cmpl $0x400d, %eax
+ jle 3f
+ /* Overflow, underflow or infinity or NaN as argument. */
fstsw %ax
movb $0x45, %dh
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
- fldl2e /* 1 log2(e) */
+ cmpb $0x01, %dh
+ je 2f /* Is +-NaN, jump. */
+ /* Overflow or underflow; saturate. */
+ fstp %st
+ fldt MO(csat)
+ andb $2, %ah
+ jz 3f
+ fchs
+3: fldl2e /* 1 log2(e) */
fmul %st(1), %st /* 1 x log2(e) */
frndint /* 1 i */
fld %st(1) /* 2 x */