V3 PATCH: numeric_limits<> support, fix PR/3865
Richard Henderson
rth@redhat.com
Fri Aug 30 18:07:00 GMT 2002
On Tue, Aug 27, 2002 at 10:35:59PM +0200, Gabriel Dos Reis wrote:
> + #if __GCC_FLOAT_FORMAT__ == __IEEE_FORMAT__
> + # define __glibcpp_f32_infinity_bytes { 0x7f800000 }
> + # define __glibcpp_f32_has_infinity true
> + # define __glibcpp_f32_QNaN_bytes { 0x7fc00000 }
> + # define __glibcpp_f32_has_QNaN true
> + # define __glibcpp_f32_SNaN_bytes { 0x7f800001 }
> + # define __glibcpp_f32_has_SNaN true
> + # define __glibcpp_f32_denorm_min_bytes { 0x00000001 }
> + # define __glibcpp_f32_has_denorm denorm_present
> + # define __glibcpp_f32_is_iec559 true
> + #endif
This is incomplete.
First, MIPS swaps the usual meaning of QNaN and SNaN encoding
interpretations. Don't ask me why.
Second, there are is an IEEE subset that omits extra-normal
operands. I.e. no Inf, no NaN, no denormal. Call this "IEEE--".
Third, there are configurations for which "float" uses IEEE--
while "double" uses regular IEEE. This happens, for instance
with the MIPS r5900, in which "float" is implemented in hardware
(in IEEE--) and "double" is implemented in software (plain IEEE).
Issue 3 is modeled inside the compiler with the MODE_HAS_NANS
(et al) target hooks.
I think all of this would be better handled *without* macros that
say "IEEE" or "float is 32-bits" or "float words are big-endian".
If you know that infinities exist, it's much easier to produce
them with (1.0f / 0.0f) than futz about with bitwise definitions.
We ought to implement the C99 nan/nanf/nanl functions as builtins,
and allow them to be constant-folded in initializers (at least
when used with the explicit __builtin_ prefix).
Thus, IMO we should have
const float __glibcpp_float_infinity = 1.0f / 0.0f;
const float __glibcpp_float_QNaN = __builtin_nanf("");
// Well, still need to handle MIPS queerness here, but can be
// done just fine with libstdc++/config/cpu headers.
const float __glibcpp_float_SNaN = __builtin_nanf("0");
Getting the minimum denormal is harder, but it can still be done.
#define _twoemx(exp, type) 0x1p ## - ## exp ## type
#define twoemx(exp, type) _twoemx(exp, type)
const float __glibcpp_float_denorm_min
= FLT_MIN * (twoemx(FLT_MANT_DIG, f) * 2.0f);
This is particularly convenient if denorm_min is supposed to return
zero in the case that denormals don't exist. In that case the value
will just underflow to zero during folding.
Of course, you don't want to pollute the namespace by including
<float.h> to get at FLT_MIN etc, but this is handled by having the
preprocessor emit all the bits for float.h as __FLT_MIN__ etc. This
is particularly useful since now we can avoid the 9 variants of
float.h in gcc's config directory. And, incidentally, the 9
variants don't actually handle all the cases properly, so that
would fix this outstanding bug as well.
The only part I can see right off that isn't handed like this is
the is_iec559 predicate. I'd guess that that should be handled
with a type-specific macro (i.e. __FLT_IS_IEC559__=1) rather than
by some __GCC_FLOAT_FORMAT__. That should handle the odd case of
the r5900.
r~
More information about the Libstdc++
mailing list