about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--NEWS4
-rw-r--r--math/e_exp10.c13
-rw-r--r--math/e_exp10f.c10
-rw-r--r--math/e_exp10l.c13
-rw-r--r--math/libm-test.inc6
6 files changed, 43 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index a13bcec7cc..7a65e6c5b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2012-04-30  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #13884]
+	[BZ #13924]
+	* math/e_exp10.c: Include <float.h>.
+	(__ieee754_exp10): Handle underflow here rather than multiplying
+	large negative argument by M_LN10.
+	* math/e_exp10f.c (__ieee754_exp10f): Call __ieee754_exp instead
+	of __ieee754_expf.
+	* math/e_exp10l.c: Include <float.h>.
+	(__ieee754_exp10l): Handle underflow here rather than multiplying
+	large negative argument by M_LN10l.
+	* math/libm-test.inc (exp10_test): Add another test.  Do not allow
+	spurious overflow exception on underflow.
+
 2012-04-29  Marek Polacek  <polacek@redhat.com>
 
 	* misc/sys/cdefs.h (__attribute_artificial__): New macro.
diff --git a/NEWS b/NEWS
index c1d051de85..da9174eff8 100644
--- a/NEWS
+++ b/NEWS
@@ -21,8 +21,8 @@ Version 2.16
   13739, 13758, 13760, 13761, 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, 13926, 13927, 13928, 13938, 13941,
-  13963, 13967, 13970, 13973, 14027, 14033
+  13917, 13918, 13919, 13920, 13921, 13924, 13926, 13927, 13928, 13938,
+  13941, 13963, 13967, 13970, 13973, 14027, 14033
 
 * ISO C11 support:
 
diff --git a/math/e_exp10.c b/math/e_exp10.c
index 75185836b8..ce319fdcd2 100644
--- a/math/e_exp10.c
+++ b/math/e_exp10.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -18,13 +18,16 @@
 
 #include <math.h>
 #include <math_private.h>
-
+#include <float.h>
 
 double
 __ieee754_exp10 (double arg)
 {
-  /* This is a very stupid and inprecise implementation.  It'll get
-     replaced sometime (soon?).  */
-  return __ieee754_exp (M_LN10 * arg);
+  if (__finite (arg) && arg < DBL_MIN_10_EXP - DBL_DIG - 10)
+    return DBL_MIN * DBL_MIN;
+  else
+    /* This is a very stupid and inprecise implementation.  It'll get
+       replaced sometime (soon?).  */
+    return __ieee754_exp (M_LN10 * arg);
 }
 strong_alias (__ieee754_exp10, __exp10_finite)
diff --git a/math/e_exp10f.c b/math/e_exp10f.c
index 7b940053fb..582824fcf5 100644
--- a/math/e_exp10f.c
+++ b/math/e_exp10f.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -23,8 +23,10 @@
 float
 __ieee754_exp10f (float arg)
 {
-  /* This is a very stupid and inprecise implementation.  It'll get
-     replaced sometime (soon?).  */
-  return __ieee754_expf (M_LN10 * arg);
+  /* The argument to exp needs to be calculated in enough precision
+     that the fractional part has as much precision as float, in
+     addition to the bits in the integer part; using double ensures
+     this.  */
+  return __ieee754_exp (M_LN10 * arg);
 }
 strong_alias (__ieee754_exp10f, __exp10f_finite)
diff --git a/math/e_exp10l.c b/math/e_exp10l.c
index e3dad0a183..d57c8cfa4f 100644
--- a/math/e_exp10l.c
+++ b/math/e_exp10l.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -18,13 +18,16 @@
 
 #include <math.h>
 #include <math_private.h>
-
+#include <float.h>
 
 long double
 __ieee754_exp10l (long double arg)
 {
-  /* This is a very stupid and inprecise implementation.  It'll get
-     replaced sometime (soon?).  */
-  return __ieee754_expl (M_LN10l * arg);
+  if (__finitel (arg) && arg < LDBL_MIN_10_EXP - LDBL_DIG - 10)
+    return LDBL_MIN * LDBL_MIN;
+  else
+    /* This is a very stupid and inprecise implementation.  It'll get
+       replaced sometime (soon?).  */
+    return __ieee754_expl (M_LN10l * arg);
 }
 strong_alias (__ieee754_exp10l, __exp10l_finite)
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 1b5d1c7e42..cd627cd829 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -3196,12 +3196,14 @@ exp10_test (void)
   TEST_f_f (exp10, nan_value, nan_value);
   TEST_f_f (exp10, 3, 1000);
   TEST_f_f (exp10, -1, 0.1L);
+#ifdef TEST_FLOAT /* Bug 13884: inaccurate results except for float.  */
+  TEST_f_f (exp10, 36, 1.0e36L);
+#endif
   TEST_f_f (exp10, 1e6, plus_infty, OVERFLOW_EXCEPTION);
   TEST_f_f (exp10, -1e6, 0);
 #ifndef TEST_LDOUBLE /* Bug 13914: spurious exceptions.  */
   TEST_f_f (exp10, max_value, plus_infty, OVERFLOW_EXCEPTION);
-  /* Bug 13924: spurious OVERFLOW exception may be present.  */
-  TEST_f_f (exp10, -max_value, 0, OVERFLOW_EXCEPTION_OK);
+  TEST_f_f (exp10, -max_value, 0);
 #endif
   TEST_f_f (exp10, 0.75L, 5.62341325190349080394951039776481231L);