This is the mail archive of the mailing list for the libstdc++ project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: V3 PATCH: numeric_limits<> support, fix PR/3865

On Tue, Aug 27, 2002 at 10:35:59PM +0200, Gabriel Dos Reis wrote:
> + #  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.


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