This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Fix exp2* on very small values


Hi!

The exp2* wrappers would signal underflow too early (they should do so when
real underflow happens, not when the returned value would be denormal), on
the other side __ieee754_exp* had the low threshold too small (arguments
<= 2^(*_MIN_EXP - *_MANT_DIG - 1) underflow, while the code was testing
arguments < 2^(*_MIN_EXP - *_MANT_DIG - 2)).

2001-06-04  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/generic/w_exp2.c (u_threshold): Lower threshold so that
	even arguments which result in denormalized exp2 are accepted.
	(__exp2): Arguments equal to u_threshold already result into
	underflow.
	* sysdeps/generic/w_exp2f.c (u_threshold, __exp2f): Likewise.
	* sysdeps/generic/w_exp2l.c (u_threshold, __exp2l): Likewise.
	* sysdeps/ieee754/dbl-64/e_exp2.c (__ieee754_exp2): Lomark was too
	low, with corrected lowmark use greaterequal, not greater.
	* sysdeps/ieee754/flt-32/e_exp2f.c (__ieee754_exp2f): Likewise.

--- libc/sysdeps/generic/w_exp2.c.jj	Sat Feb 17 02:42:18 2001
+++ libc/sysdeps/generic/w_exp2.c	Mon Jun  4 11:45:24 2001
@@ -7,7 +7,7 @@
 #include "math_private.h"
 
 static const double o_threshold= (double) DBL_MAX_EXP;
-static const double u_threshold= (double) DBL_MIN_EXP;
+static const double u_threshold= (double) (DBL_MIN_EXP - DBL_MANT_DIG - 1);
 
 double
 __exp2 (double x)		/* wrapper exp2 */
@@ -22,7 +22,7 @@ __exp2 (double x)		/* wrapper exp2 */
       if (x > o_threshold)
 	/* exp2 overflow */
 	return __kernel_standard (x, x, 44);
-      else if (x < u_threshold)
+      else if (x <= u_threshold)
 	/* exp2 underflow */
 	return __kernel_standard (x, x, 45);
     }
--- libc/sysdeps/generic/w_exp2f.c.jj	Sat Feb 17 02:42:22 2001
+++ libc/sysdeps/generic/w_exp2f.c	Mon Jun  4 11:48:44 2001
@@ -7,7 +7,7 @@
 #include "math_private.h"
 
 static const float o_threshold= (float) FLT_MAX_EXP;
-static const float u_threshold= (float) FLT_MIN_EXP;
+static const float u_threshold= (float) (FLT_MIN_EXP - FLT_MANT_DIG - 1);
 
 float
 __exp2f (float x)		/* wrapper exp2f */
@@ -22,7 +22,7 @@ __exp2f (float x)		/* wrapper exp2f */
       if (x > o_threshold)
 	/* exp2 overflow */
 	return (float) __kernel_standard ((double) x, (double) x, 144);
-      else if (x < u_threshold)
+      else if (x <= u_threshold)
 	/* exp2 underflow */
 	return (float) __kernel_standard ((double) x, (double) x, 145);
     }
--- libc/sysdeps/generic/w_exp2l.c.jj	Sat Feb 17 02:42:26 2001
+++ libc/sysdeps/generic/w_exp2l.c	Mon Jun  4 11:48:26 2001
@@ -7,7 +7,8 @@
 #include "math_private.h"
 
 static const long double o_threshold = (long double) LDBL_MAX_EXP;
-static const long double u_threshold = (long double) LDBL_MIN_EXP;
+static const long double u_threshold
+  = (long double) (LDBL_MIN_EXP - LDBL_MANT_DIG - 1);
 
 long double
 __exp2l (long double x)			/* wrapper exp2l */
@@ -21,7 +22,7 @@ __exp2l (long double x)			/* wrapper exp
     {
       if (x > o_threshold)
 	return __kernel_standard (x, x, 244); /* exp2l overflow */
-      else if (x < u_threshold)
+      else if (x <= u_threshold)
 	return __kernel_standard (x, x, 245); /* exp2l underflow */
     }
   return z;
--- libc/sysdeps/ieee754/dbl-64/e_exp2.c.jj	Sat Feb 17 17:48:54 2001
+++ libc/sysdeps/ieee754/dbl-64/e_exp2.c	Mon Jun  4 11:34:32 2001
@@ -1,5 +1,5 @@
 /* Double-precision floating point 2^x.
-   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Geoffrey Keating <geoffk@ozemail.com.au>
 
@@ -44,10 +44,10 @@ double
 __ieee754_exp2 (double x)
 {
   static const double himark = (double) DBL_MAX_EXP;
-  static const double lomark = (double) (DBL_MIN_EXP - DBL_MANT_DIG - 1) - 1.0;
+  static const double lomark = (double) (DBL_MIN_EXP - DBL_MANT_DIG - 1);
 
   /* Check for usual case.  */
-  if (isless (x, himark) && isgreater (x, lomark))
+  if (isless (x, himark) && isgreaterequal (x, lomark))
     {
       static const double THREEp42 = 13194139533312.0;
       int tval, unsafe;
--- libc/sysdeps/ieee754/flt-32/e_exp2f.c.jj	Sat Feb 17 17:48:20 2001
+++ libc/sysdeps/ieee754/flt-32/e_exp2f.c	Mon Jun  4 11:44:12 2001
@@ -1,5 +1,5 @@
 /* Single-precision floating point 2^x.
-   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Geoffrey Keating <geoffk@ozemail.com.au>
 
@@ -45,10 +45,10 @@ float
 __ieee754_exp2f (float x)
 {
   static const float himark = (float) FLT_MAX_EXP;
-  static const float lomark = (float) (FLT_MIN_EXP - FLT_MANT_DIG - 1) - 1.0;
+  static const float lomark = (float) (FLT_MIN_EXP - FLT_MANT_DIG - 1);
 
   /* Check for usual case.  */
-  if (isless (x, himark) && isgreater (x, lomark))
+  if (isless (x, himark) && isgreaterequal (x, lomark))
     {
       static const float THREEp14 = 49152.0;
       int tval, unsafe;

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]