This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Fix hypotf overflow/underflow (bug 13840)
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 13 Mar 2012 20:46:17 +0000 (UTC)
- Subject: Fix hypotf overflow/underflow (bug 13840)
This patch fixes overflow and underflow problems in
sysdeps/ieee754/flt-32/e_hypotf.c. This scales by 2**60 in an attempt
to avoid the internal x**x+y**y overflowing. But as FLT_MAX is just
under 2**128, scaling down by 2**60 isn't enough for large inputs.
And while there is a separate case for subnormal inputs, for small
normal inputs the scaling up by 2**60 still leaves x**x+y**y subnormal
(so with loss of precision).
Tested x86_64 and x86 (no ulps updates required). The TEST_INLINE
conditionals are based on failures observed with the x86 inline
implementation (it's possible that the test without such a conditional
will need one as well depending on the exact compiler version /
configuration in use, I just didn't find it to be needed in my
testing).
2012-03-13 Joseph Myers <joseph@codesourcery.com>
[BZ #13840]
* sysdeps/ieee754/flt-32/e_hypotf.c (__ieee754_hypotf): Scale by
2**70, not 2**60.
* math/libm-test.inc (hypot_test): Add more tests.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 39cda66..191f359 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -3557,6 +3557,19 @@ hypot_test (void)
TEST_ff_f (hypot, 0.75L, 1.25L, 1.45773797371132511771853821938639577L);
+#if !(defined TEST_FLOAT && defined TEST_INLINE)
+ TEST_ff_f (hypot, 0x3p125L, 0x4p125L, 0x5p125L);
+ TEST_ff_f (hypot, 0x1.234566p-126L, 0x1.234566p-126L, 1.891441686191081936598531534017449451173e-38L);
+#endif
+
+#ifndef TEST_FLOAT
+ TEST_ff_f (hypot, 0x3p1021L, 0x4p1021L, 0x5p1021L);
+#endif
+
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384 && !defined TEST_INLINE
+ TEST_ff_f (hypot, 0x3p16381L, 0x4p16381L, 0x5p16381L);
+#endif
+
END (hypot);
}
diff --git a/sysdeps/ieee754/flt-32/e_hypotf.c b/sysdeps/ieee754/flt-32/e_hypotf.c
index 97e7d34..69dae12 100644
--- a/sysdeps/ieee754/flt-32/e_hypotf.c
+++ b/sysdeps/ieee754/flt-32/e_hypotf.c
@@ -38,8 +38,8 @@ __ieee754_hypotf(float x, float y)
if(hb == 0x7f800000) w = b;
return w;
}
- /* scale a and b by 2**-60 */
- ha -= 0x1e000000; hb -= 0x1e000000; k += 60;
+ /* scale a and b by 2**-70 */
+ ha -= 0x23000000; hb -= 0x23000000; k += 70;
SET_FLOAT_WORD(a,ha);
SET_FLOAT_WORD(b,hb);
}
@@ -50,10 +50,10 @@ __ieee754_hypotf(float x, float y)
b *= t1;
a *= t1;
k -= 126;
- } else { /* scale a and b by 2^60 */
- ha += 0x1e000000; /* a *= 2^60 */
- hb += 0x1e000000; /* b *= 2^60 */
- k -= 60;
+ } else { /* scale a and b by 2^70 */
+ ha += 0x23000000; /* a *= 2^70 */
+ hb += 0x23000000; /* b *= 2^70 */
+ k -= 70;
SET_FLOAT_WORD(a,ha);
SET_FLOAT_WORD(b,hb);
}
--
Joseph S. Myers
joseph@codesourcery.com