lmi
[Top][All Lists]

## Re: [lmi] Is DBL_MAX "adjacent" to infinity?

 From: Vadim Zeitlin Subject: Re: [lmi] Is DBL_MAX "adjacent" to infinity? Date: Fri, 24 Mar 2017 21:31:17 +0100

On Fri, 24 Mar 2017 19:36:44 +0000 Greg Chicares <address@hidden> wrote:

GC> On 2017-03-23 00:27, Greg Chicares wrote:
GC> [...]
GC> > Oh, and here's another question. What happens if you try
GC> >   static_cast<float>(DBL_MAX)?
GC> > C++11 [4.8/1] says "If the source value is between two adjacent
destination
GC> > values, the result of the conversion is an implementation-defined choice
of
GC> > either of those values. Otherwise, the behavior is undefined." So is this
GC> > cast UB? Or is DBL_MAX "adjacent" to infinity?

I don't think anything in (either C++ or IEEE) standard justifies an
affirmative answer to this question. So IMO this cast is clearly UB.

GC> >   static_cast<float>((double)INFINITY)
GC> > ? AIUI, the C and C++ standards supposedly defer to the floating-point
GC> > standard, and IEEE 754-1985 [6.1] defines "conversion of an infinity into
GC> > the same infinity in another format" as an operation that signals no
GC> > exceptions, so I think this is supposed to be well defined. OTOH, it's
GC> > not "between two adjacent destination values", so is it UB?
GC> >
GC> > Can it be that
GC> >   DBL_MAX is too big to convert to float, but
GC> >   INFINITY is not too big to "   "   "
GC> > even though DBL_MAX < INFINITY?

FWIW this would seem to be perfectly logical to me. Infinity is
exactly representable as float (so there is no need to speak about adjacent
values at all), but DBL_MAX is not.

GC> I happened upon this:
GC>
GC>
https://www.securecoding.cert.org/confluence/display/c/FLP34-C.+Ensure+that+floating-point+conversions+are+within+range+of+the+new+type
GC>
GC> It cites the C equivalents of C++11's [conv.double] and [conv.fpint],
GC> exhorts us to avoid the undefined behavior noted there, and then says:
GC>
GC> | This rule does not apply to demotions of floating-point types on
GC> | implementations that support signed infinity, such as IEEE 754,
GC> | as all values are within range.
GC>
GC> OTOH, their "safe" version of
GC>   float f = whatever;
GC>   int i = (int) f;
GC> signals an error if the value to be converted is
GC>  - out of range (determined by computing its logarithm), or
GC>  - subnormal
GC> but does not check for NaN...so their advice seems unreliable.

It's a bit hard to argue that NaN is "within range" (for any value of
"range"), so their rules does seem to be incomplete. But it doesn't really
invalidate the rest of it.

To summarize, IMO any "safe cast" of double to float absolutely must check
that the value is either non-finite or is between -FLT_MAX and FLT_MAX.

Regards,
VZ