1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Fix pow overflow in non-default rounding modes (bug 16315).

This patch fixes bug 16315, bad pow handling of overflow/underflow in
non-default rounding modes.  Tests of pow are duly converted to
ALL_RM_TEST to run all tests in all rounding modes.

There are two main issues here.  First, various implementations
compute a negative result by negating a positive result, but this
yields inappropriate overflow / underflow values for directed
rounding, so either overflow / underflow results need recomputing in
the correct sign, or the relevant overflowing / underflowing operation
needs to be made to have a result of the correct sign.  Second, the
dbl-64 implementation sets FE_TONEAREST internally; in the overflow /
underflow case, the result needs recomputing in the original rounding
mode.

Tested x86_64 and x86 and ulps updated accordingly.

	[BZ #16315]
	* sysdeps/i386/fpu/e_pow.S (__ieee754_pow): Ensure possibly
	overflowing or underflowing operations take place with sign of
	result.
	* sysdeps/i386/fpu/e_powf.S (__ieee754_powf): Likewise.
	* sysdeps/i386/fpu/e_powl.S (__ieee754_powl): Likewise.
	* sysdeps/ieee754/dbl-64/e_pow.c: Include <math.h>.
	(__ieee754_pow): Recompute overflowing and underflowing results in
	original rounding mode.
	* sysdeps/x86/fpu/powl_helper.c: Include <stdbool.h>.
	(__powl_helper): Allow negative argument X and scale negated value
	as needed.  Avoid passing value outside [-1, 1] to f2xm1.
	* sysdeps/x86_64/fpu/e_powl.S (__ieee754_powl): Ensure possibly
	overflowing or underflowing operations take place with sign of
	result.
	* sysdeps/x86_64/fpu/multiarch/e_pow.c [HAVE_FMA4_SUPPORT]:
	Include <math.h>.
	* math/auto-libm-test-in: Add more tests of pow.
	* math/auto-libm-test-out: Regenerated.
	* math/libm-test.inc (pow_test): Use ALL_RM_TEST.
	(pow_tonearest_test_data): Remove.
	(pow_test_tonearest): Likewise.
	(pow_towardzero_test_data): Likewise.
	(pow_test_towardzero): Likewise.
	(pow_downward_test_data): Likewise.
	(pow_test_downward): Likewise.
	(pow_upward_test_data): Likewise.
	(pow_test_upward): Likewise.
	(main): Don't call removed functions.
	* sysdeps/i386/fpu/libm-test-ulps: Update.
	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
This commit is contained in:
Joseph Myers
2014-06-23 20:12:33 +00:00
parent 5686b236cc
commit 4da6db5188
14 changed files with 2955 additions and 235 deletions

View File

@ -8697,69 +8697,7 @@ static const struct test_ff_f_data pow_test_data[] =
static void
pow_test (void)
{
START (pow, 0);
RUN_TEST_LOOP_ff_f (pow, pow_test_data, );
END;
}
static const struct test_ff_f_data pow_tonearest_test_data[] =
{
AUTO_TESTS_ff_f (pow),
};
static void
pow_test_tonearest (void)
{
START (pow_tonearest, 0);
RUN_TEST_LOOP_ff_f (pow, pow_tonearest_test_data, FE_TONEAREST);
END;
}
static const struct test_ff_f_data pow_towardzero_test_data[] =
{
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L),
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L),
};
static void
pow_test_towardzero (void)
{
START (pow_towardzero, 0);
RUN_TEST_LOOP_ff_f (pow, pow_towardzero_test_data, FE_TOWARDZERO);
END;
}
static const struct test_ff_f_data pow_downward_test_data[] =
{
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L),
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L),
};
static void
pow_test_downward (void)
{
START (pow_downward, 0);
RUN_TEST_LOOP_ff_f (pow, pow_downward_test_data, FE_DOWNWARD);
END;
}
static const struct test_ff_f_data pow_upward_test_data[] =
{
TEST_ff_f (pow, 1.0625L, 1.125L, 1.070582293028761362162622578677070098674L),
TEST_ff_f (pow, 1.5L, 1.03125L, 1.519127098714743184071644334163037684948L),
};
static void
pow_test_upward (void)
{
START (pow_upward, 0);
RUN_TEST_LOOP_ff_f (pow, pow_upward_test_data, FE_UPWARD);
END;
ALL_RM_TEST (pow, 0, pow_test_data, RUN_TEST_LOOP_ff_f, END);
}
@ -9946,10 +9884,6 @@ main (int argc, char **argv)
fabs_test ();
hypot_test ();
pow_test ();
pow_test_tonearest ();
pow_test_towardzero ();
pow_test_downward ();
pow_test_upward ();
sqrt_test ();
/* Error and gamma functions: */