Re: RFA: Support infinity, NaN, and denormalized numbers in floatformat.c

Andreas Schwab
2012-08-16T16:20:56Z

Ian Lance Taylor <ian@wasabisystems.com> writes:

> @@ -306,8 +359,18 @@ floatformat_to_double (fmt, from, to)
> mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
> mant_off, mant_bits);
>
> - dto += ldexp ((double)mant, exponent - mant_bits);
> - exponent -= mant_bits;
> + /* Handle denormalized numbers. FIXME: What should we do for
> + non-IEEE formats? */
> + if (exponent == 0 && mant != 0)
> + dto += ldexp ((double)mant,
> + (- fmt->exp_bias
> + - mant_bits
> + - (mant_off - fmt->man_start)
> + + 1));
> + else
> + dto += ldexp ((double)mant, exponent - mant_bits);
> + if (exponent != 0)
> + exponent -= mant_bits;

That mishandles numbers between 1 and 2 (ie. where the unbiased exponent
is zero) with floating-point formats with more than 32 mantissa bits.
Also, the handling of denormal numbers can be simplified by just setting
exponent appropriately.

Andreas.

* floatformat.c (floatformat_to_double): Correctly handle numbers
between 1 and 2. Simplify handling of denormal number.
(main): Test with 1.1.
---
libiberty/floatformat.c | 38 ++++++++++++++------------------------
1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/libiberty/floatformat.c b/libiberty/floatformat.c
index 1116c63..c58ab01 100644
--- a/libiberty/floatformat.c
+++ b/libiberty/floatformat.c
@@ -1,5 +1,5 @@
/* IEEE floating point support routines, for GDB, the GNU Debugger.
- Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006, 2010
+ Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006, 2010, 2012
Free Software Foundation, Inc.

This file is part of GDB.
@@ -463,7 +463,6 @@ floatformat_to_double (const struct floatformat *fmt,
unsigned long mant;
unsigned int mant_bits, mant_off;
int mant_bits_left;
- int special_exponent; /* It's a NaN, denorm or zero */

/* Split values are not handled specially, since the top half has
the correctly rounded double value (in the only supported case of
@@ -503,20 +502,20 @@ floatformat_to_double (const struct floatformat *fmt,
mant_off = fmt->man_start;
dto = 0.0;

- special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
-
- /* Don't bias zero's, denorms or NaNs. */
- if (!special_exponent)
- exponent -= fmt->exp_bias;
-
/* Build the result algebraically. Might go infinite, underflow, etc;
who cares. */

- /* If this format uses a hidden bit, explicitly add it in now. Otherwise,
- increment the exponent by one to account for the integer bit. */
-
- if (!special_exponent)
+ /* For denorms use minimum exponent. */
+ if (exponent == 0)
+ exponent = 1 - fmt->exp_bias;
+ else
{
+ exponent -= fmt->exp_bias;
+
+ /* If this format uses a hidden bit, explicitly add it in now.
+ Otherwise, increment the exponent by one to account for the
+ integer bit. */
+
if (fmt->intbit == floatformat_intbit_no)
dto = ldexp (1.0, exponent);
else
@@ -530,18 +529,8 @@ floatformat_to_double (const struct floatformat *fmt,
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
mant_off, mant_bits);

- /* Handle denormalized numbers. FIXME: What should we do for
- non-IEEE formats? */
- if (special_exponent && exponent == 0 && mant != 0)
- dto += ldexp ((double)mant,
- (- fmt->exp_bias
- - mant_bits
- - (mant_off - fmt->man_start)
- + 1));
- else
- dto += ldexp ((double)mant, exponent - mant_bits);
- if (exponent != 0)
- exponent -= mant_bits;
+ dto += ldexp ((double) mant, exponent - mant_bits);
+ exponent -= mant_bits;
mant_off += mant_bits;
mant_bits_left -= mant_bits;
}
@@ -756,6 +745,7 @@ main (void)
{
ieee_test (0.0);
ieee_test (0.5);
+ ieee_test (1.1);
ieee_test (256.0);
ieee_test (0.12345);
ieee_test (234235.78907234);
--
1.7.11.5

--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."