Simplify HUGE_VAL definitions [committed]

Message ID 68de3d6e-7900-96a4-bc13-c5eff05fda7f@panix.com
State Committed
Headers

Commit Message

Zack Weinberg Sept. 1, 2017, 1:56 p.m. UTC
  On 09/01/2017 09:24 AM, Joseph Myers wrote:
> On Fri, 1 Sep 2017, Zack Weinberg wrote:
> 
>>> Annex F requires conversions of constants (with at most DECIMAL_DIG
>>> digits) to be to-nearest.  (TS 18661-1 adds the FENV_ROUND pragma to
>>> choose a different rounding mode for them and for certain operations.)
>>
>> Yes, but for any constant greater than <type>_MAX, <type>_MAX is
>> arguably nearer to that constant than +Infinity is.
> 
> The IEEE rounding modes (all of them) define overflow on the basis of 
> whether the result with normal precision but infinite exponent range would 
> have an exponent that's too big (and in the case of overflow, the rounded 
> result is determined by the rounding mode, so +Inf for to-nearest).

OK, I think I get it.

One more problem, which I should have thought to check earlier: 1e10000L
isn't big enough if long double is 128 bits wide (which it actually
appears to be on this computer):

$ gcc -E -dM -xc - < /dev/null | grep -E '(DBL|LDBL|FLT[0-9]*)_MAX_EXP'
#define __LDBL_MAX_EXP__ 16384
#define __DBL_MAX_EXP__ 1024
#define __FLT32_MAX_EXP__ 128
#define __FLT128_MAX_EXP__ 16384
#define __FLT_MAX_EXP__ 128
#define __FLT64_MAX_EXP__ 1024

So I propose this patch (not yet tested):
  

Comments

Joseph Myers Sept. 1, 2017, 2:59 p.m. UTC | #1
On Fri, 1 Sep 2017, Zack Weinberg wrote:

> One more problem, which I should have thought to check earlier: 1e10000L
> isn't big enough if long double is 128 bits wide (which it actually
> appears to be on this computer):

1e10000L is big enough.  For both x86 extended and binary128, the largest 
finite value is just below 2^16384 (about 1.2e4932).

It's true that it wouldn't be enough for _Float128x (which must have a 
precision of at least 128 bits and maximum exponent at least 65535; e.g. 
binary192 would meet those requirements, binary160 wouldn't; GCC does not 
support _Float128x, or any such format, on any target).  But if we 
supported such types I don't expect we'd have a HUGE_VAL fallback for them 
any more than we do for HUGE_VAL_F128.
  

Patch

--- a/math/math.h
+++ b/math/math.h
@@ -37,20 +37,25 @@  __BEGIN_DECLS
 /* Gather machine dependent type support.  */
 #include <bits/floatn.h>

-/* Value returned on overflow.  On all IEEE754 machines, this is
-   +Infinity.  */
+/* Value returned on overflow.  With IEEE 754 floating point, this is
+   +Infinity, otherwise the largest representable positive value.  */
 #if __GNUC_PREREQ (3, 3)
 # define HUGE_VAL (__builtin_huge_val ())
 #else
-# define HUGE_VAL 1e10000
+/* This may provoke compiler warnings, and may not be rounded to
+   +Infinity in all IEEE 754 rounding modes, but is the best that
+   can be done in ISO C while remaining a constant expression.
+   100,000 is greater than the maximum exponent for all supported
+   floating-point formats and widths.  */
+# define HUGE_VAL 1e100000
 #endif
 #ifdef __USE_ISOC99
 # if __GNUC_PREREQ (3, 3)
 #  define HUGE_VALF (__builtin_huge_valf ())
 #  define HUGE_VALL (__builtin_huge_vall ())
 # else
-#  define HUGE_VALF 1e10000f
-#  define HUGE_VALL 1e10000L
+#  define HUGE_VALF 1e100000f
+#  define HUGE_VALL 1e100000L
 # endif
 #endif
 #if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)