[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: signed-nan: Don't assume that '-' works as expected on NaN values
From: |
Bruno Haible |
Subject: |
Re: signed-nan: Don't assume that '-' works as expected on NaN values |
Date: |
Fri, 19 Apr 2024 15:27:51 +0200 |
Jeffrey Walton wrote:
> > +/* Returns - x, implemented by inverting the sign bit,
> > + so that it works also on 'float' NaN values. */
> > +_GL_UNUSED static float
> > +minus_NaNf (float x)
> > +{
> > +#if defined __mips__
> > + /* The mips instruction neg.s may have no effect on NaNs.
> > + Therefore, invert the sign bit using integer operations. */
> > + union { unsigned int i; float value; } u;
> > + u.value = x;
> > + u.i ^= 1U << 31;
> > + return u.value;
> > +#else
> > + return - x;
> > +#endif
> > +}
> >
>
> Accessing the union first though 'value' and then through 'i' may be
> undefined behavior. I don't think you can legally access the union through
> the inactive member.
It is certainly undefined behaviour according to ISO C, because ISO C does
not specify the bit-by-bit representation of a 'float'.
But when we assume IEEE-754 single-precision as 'float' — which all hardware
uses nowadays —, the results are defined. All we need to worry about are
compiler optimizations.
The use of a union to extract the bits of the representation of a
'float' is safe in practice, despite of the "aliasing rules" of
C99, because the GCC docs [1] say
"Even with '-fstrict-aliasing', type-punning is allowed, provided the
memory is accessed through the union type."
and similarly for other compilers.
Bruno
[1] https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Optimize-Options.html