From 7620dc05bccf4c73e9710c501bd899e8474b01f7 Mon Sep 17 00:00:00 2001 Message-Id: <7620dc05bccf4c73e9710c501bd899e8474b01f7.1746186297.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sun, 27 Apr 2025 04:06:06 +0100 Subject: [PATCH] @@@ fltfmt fettling Organization: Straylight/Edgeware From: Mark Wooding --- utils/fltfmt-convert.c | 2 +- utils/fltfmt.c | 38 ++++++++++++++---- utils/fltfmt.h | 90 +++--------------------------------------- 3 files changed, 38 insertions(+), 92 deletions(-) diff --git a/utils/fltfmt-convert.c b/utils/fltfmt-convert.c index cc24dba..0b6971f 100644 --- a/utils/fltfmt-convert.c +++ b/utils/fltfmt-convert.c @@ -199,7 +199,7 @@ CONVERSIONS(DEF_CONV) * Use: Decodes a floating point value in an external format into a * native value. * - * The naming conventions are the same as for @fltfmt_dbltof64b@ + * The naming conventions are the same as for @fltfmt_CTYtoFTYE@ * above. * * On platforms where the external format is used natively, diff --git a/utils/fltfmt.c b/utils/fltfmt.c index cb39eca..177004e 100644 --- a/utils/fltfmt.c +++ b/utils/fltfmt.c @@ -301,7 +301,7 @@ static unsigned ms_set_bit(const uint32 *x, unsigned from, unsigned to) */ /* If the region is empty then it's technically true that all of the bits - * are zero. It's important to be able to do answer the case where + * are zero. It's important to be able to answer the case where * %$\id{from} = \id{to} = 0$% without accessing memory. */ assert(to >= from); if (to == from) return (ALLCLEAR); @@ -757,7 +757,9 @@ unsigned fltfmt_encieee(const struct fltfmt_ieeefmt *fmt, /* Set the biased exponent. */ z0 |= (exp + maxexp) << esh; - /* Clear the unit bit if we're suppose to use a hidden-bit convention. */ + /* Clear the unit bit if we're suppose to use a hidden-bit + * convention. + */ if (fmt->f&FLTIF_HIDDEN) { mb = fmt->prec - 1; mw = (mb + 31)/32; mb = mb%32; z[nw - mw] &= ~B32(mb); @@ -1203,8 +1205,10 @@ unsigned fltfmt_decidblext80(struct floatbits *z_out, uint16 se, kludge64 m) * requisite compile-time configuration machinery is worth the effort.) */ -# define SETINF(TY, rc, z) \ - do { (z) = TY##_MAX; (rc) = FLTERR_OFLOW | FLTERR_INEXACT; } while (0) +# define SETINF(TY, rc, z) do { \ + (z) = TY##_MAX; \ + (rc) = FLTERR_OFLOW | FLTERR_INEXACT; \ + } while (0) #endif #ifdef DIGIT_BITS @@ -1231,6 +1235,11 @@ unsigned fltfmt_decidblext80(struct floatbits *z_out, uint16 se, kludge64 m) #endif #ifdef FROB_NANS + /* The native floating point format uses the opposite quiet-vs-signalling + * NaN convention from the recommended `quiet bit' convention, so the bit + * needs hacking on input. + */ + # define FROBNAN_ENCDECLS struct floatbits _y # define FROBNAN_ENC do { \ if (_x->f&FLTF_NANMASK) { \ @@ -1239,6 +1248,11 @@ unsigned fltfmt_decidblext80(struct floatbits *z_out, uint16 se, kludge64 m) } \ } while (0) #else + /* The native floating point format either uses the conventional + * `quiet-bit' convention, or isn't IEEE at all. Either way, there's + * nothing to do here. + */ + # define FROBNAN_ENCDECLS # define FROBNAN_ENC do ; while (0) #endif @@ -1412,7 +1426,7 @@ unsigned fltfmt_decidblext80(struct floatbits *z_out, uint16 se, kludge64 m) * zero. * * * If the implementation's floating-point radix is not a - * power of two, and @x@ is a nonzero finite value, then + * power of two, and @x@ is a nonzero finite value, then the * @FLTERR_INEXACT@ error bit is set (unconditionally), and * the value is rounded by the implementation using its * prevailing rounding policy. If the radix is a power of @@ -1508,10 +1522,20 @@ unsigned fltfmt_encldbl(long double *z_out, #endif #ifdef FROB_NANS + /* The native floating point format uses the opposite quiet-vs-signalling + * NaN convention from the recommended `quiet bit' convention, so the bit + * needs hacking on output. + */ + # define FROBNAN_DEC do { \ if (_z->f&FLTF_NANMASK) _z->f ^= FLTF_NANMASK; \ } while (0) #else + /* The native floating point format either uses the conventional + * `quiet-bit' convention, or isn't IEEE at all. Either way, there's + * nothing to do here. + */ + # define FROBNAN_DEC do ; while (0) #endif @@ -1638,7 +1662,7 @@ unsigned fltfmt_encldbl(long double *z_out, * * Returns: Error flags (@FLTERR_...@). * - * Use: Decode the native C floatingpoint value @x@ and store the + * Use: Decode the native C floating-point value @x@ and store the * result in @z_out@. * * The @TY@ may be @flt@ to encode a @float@, @dbl@ to encode a @@ -1655,7 +1679,7 @@ unsigned fltfmt_encldbl(long double *z_out, * error bit is set and the decoded payload is left empty. * * * If the implementation's floating-point radix is not a - * power of two, and @x@ is a nonzero finite value, then + * power of two, and @x@ is a nonzero finite value, then the * @FLTERR_INEXACT@ error bit is set (unconditionally), and * the rounded value (according to the rounding mode @r@) is * stored in as many fraction words as necessary to identify diff --git a/utils/fltfmt.h b/utils/fltfmt.h index efa678c..cfdbbe7 100644 --- a/utils/fltfmt.h +++ b/utils/fltfmt.h @@ -55,7 +55,7 @@ /* Predicates considered for rounding. */ #define FRPF_LOW 0x0001u /* lost bits not exactly zero or half */ -#define FRPF_HALF 0x0002u /* lost a half or more */ +#define FRPF_HALF 0x0002u /* lost a half or more */ #define FRPF_ODD 0x0004u /* final place is currently odd */ #define FRPF_NEG 0x0008u /* number is negative */ @@ -483,84 +483,6 @@ extern unsigned fltfmt_decidblext80(struct floatbits */*z_out*/, /*----- Native formats ----------------------------------------------------*/ -/* Hacking for platforms which ill-advisedly have the opposite sense for the - * quiet NaN bit. - * - * Obviously we toggle the quiet bit, but there's a problem: if the quiet bit - * is the only one set, then if we toggle it, the fraction will become zero - * and we'll be left with an infinity. Follow MIPS and set all of the bits. - * - * This is all internal machinery and shouldn't be relied on by applications. - */ -#if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008)) -# define FLTFMT__MUST_FROB_NANS - -# define FLTFMT__FROB_NAN_F32(x_inout, rc) do { \ - uint32 *_x_inout_ = (x_inout), _x0_ = _x_inout_[0]; \ - \ - if ((_x0_&0x7f800000) != 0x7f800000 || !(_x0_&0x007fffff)) \ - ; \ - else if (_x0_&0x003fffff) \ - _x_inout_[0] = _x0_ ^ 0x00400000; \ - else { \ - _x_inout_[0] = (_x0_&0x80000000) | 0x7fffffff; \ - (rc) |= FLTERR_INEXACT; \ - } \ - } while (0) - -# define FLTFMT__FROB_NAN_F64(x_inout, rc) do { \ - uint32 *_x_inout_ = (x_inout), \ - _x0_ = _x_inout_[0], _x1_ = _x_inout_[1]; \ - \ - if ((_x0_&0x7ff00000) != 0x7ff00000 || (!(_x0_&0x000fffff) && !_x1_)) \ - ; \ - else if ((_x0_&0x0007ffff) || _x1_) \ - _x_inout_[0] = _x0_ ^ 0x00080000; \ - else { \ - _x_inout_[0] = (_x0_&0x80000000) | 0x7fffffff; \ - _x_inout_[1] = 0xffffffff; \ - (rc) |= FLTERR_INEXACT; \ - } \ - } while (0) - -# define FLTFMT__FROB_NAN_F128(x_inout, rc) do { \ - uint32 *_x_inout_ = (x_inout), \ - _x0_ = _x_inout_[0], _x1_ = _x_inout_[1], \ - _x2_ = _x_inout_[2], _x3_ = _x_inout_[3]; \ - \ - if ((_x0_&0x7fff0000) != 0x7fff0000 || \ - (!(_x0_&0x000fffff) && !_x1_ && !_x2_ && !_x3_)) \ - ; \ - else if ((_x0_&0x00007fff) || _x1_ || _x2_ || _x3_) \ - _x_inout_[0] = _x0_ ^ 0x00008000; \ - else { \ - _x_inout_[0] = (_x0_&0x80000000) | 0x7fffffff; \ - _x_inout_[1] = _x_inout_[2] = _x_inout_[3] = 0xffffffff; \ - (rc) |= FLTERR_INEXACT; \ - } \ - } while (0) - -# define FLTFMT__FROB_NAN_IDBLEXT80(x_inout, rc) do { \ - uint32 *_x_inout_ = (x_inout), \ - _x0_ = _x_inout_[0], _x1_ = _x_inout_[1], _x2_ = _x_inout_[2]; \ - \ - if ((_x0_&0x00007fff) != 0x00007fff || (!(_x1_&0x7fffffff) && !_x2_)) \ - ; \ - else if ((_x1_&0x3fffffff) || _x1_ || _x2_) \ - _x_inout_[1] = _x1_ ^ 0x40000000; \ - else { \ - _x_inout_[1] = (_x1_&0x80000000) | 0x3fffffff; /* preserve unit */ \ - _x_inout_[2] = 0xffffffff; \ - } \ - } while (0) - -#else -# define FLTFMT__FROB_NAN_F32(x_inout, rc) do ; while (0) -# define FLTFMT__FROB_NAN_F64(x_inout, rc) do ; while (0) -# define FLTFMT__FROB_NAN_F128(x_inout, rc) do ; while (0) -# define FLTFMT__FROB_NAN_IDBLEXT80(x_inout, rc) do ; while (0) -#endif - /* --- @fltfmt_encTY@ --- * * * Arguments: @ty *z_out@ = storage for the result @@ -594,7 +516,7 @@ extern unsigned fltfmt_decidblext80(struct floatbits */*z_out*/, * zero. * * * If the implementation's floating-point radix is not a - * power of two, and @x@ is a nonzero finite value, then + * power of two, and @x@ is a nonzero finite value, then the * @FLTERR_INEXACT@ error bit is set (unconditionally), and * the value is rounded by the implementation using its * prevailing rounding policy. If the radix is a power of @@ -625,7 +547,7 @@ extern unsigned fltfmt_encldbl(long double */*z_out*/, * * Returns: Error flags (@FLTERR_...@). * - * Use: Decode the native C floatingpoint value @x@ and store the + * Use: Decode the native C floating-point value @x@ and store the * result in @z_out@. * * The @TY@ may be @flt@ to encode a @float@, @dbl@ to encode a @@ -642,7 +564,7 @@ extern unsigned fltfmt_encldbl(long double */*z_out*/, * error bit is set and the decoded payload is left empty. * * * If the implementation's floating-point radix is not a - * power of two, and @x@ is a nonzero finite value, then + * power of two, and @x@ is a nonzero finite value, then the * @FLTERR_INEXACT@ error bit is set (unconditionally), and * the rounded value (according to the rounding mode @r@) is * stored in as many fraction words as necessary to identify @@ -674,7 +596,7 @@ extern unsigned fltfmt_decldbl(struct floatbits */*z_out*/, * Use: Encode a native C floating-point value in an external format. * * The @CTY@ is an abbreviation for a C type: @flt@ for @float@, - * or @dbl@ for @double@; @fty@ is an abbreviation for the + * or @dbl@ for @double@; @FTY@ is an abbreviation for the * external format, @f32@ for IEEE Binary32, or @f64@ for IEEE * Binary64; and @E@ is @l@ for little-endian or @b@ for * big-endian byte order. Not all combinations are currently @@ -700,7 +622,7 @@ extern unsigned fltfmt_dbltof64b(octet */*p*/, double /*x*/, unsigned /*r*/); * Use: Decodes a floating point value in an external format into a * native value. * - * The naming conventions are the same as for @fltfmt_dbltof64b@ + * The naming conventions are the same as for @fltfmt_CTYtoFTYE@ * above. * * On platforms where the external format is used natively, -- [mdw]