RFA: Fix _DOUBLE_IS_32BITS handling of denormals in dtoa.c
Jeff Johnston
jjohnstn@redhat.com
Thu Aug 3 20:39:00 GMT 2006
Patch checked in. Thanks.
-- Jeff J.
Joern RENNECKE wrote:
> Paranoia fails for sh-elf -m4-single-only with current newlib mainline.
> Paranoia wnts to print the smallest representable floating point number,
> which is a denormal with only the least significant bit set.
> dtoa.c calculates correctly that there is only one bit, but it assumes
> it has
> to pick it out of a 64 bit double, i.e. it shifts word1, which is always 0,
> left by 31. Hence converting to floating point yields 0.0, and subtracting
> 31 from the exponent causes an underflow. Hence we end up with a ds
> that is larger than INT_MAX, and a k of INT_MAX.
> Hence we run out of memory when while calculating
> pow5mult (ptr, S, s5), and the memory gets corrupted when Balloc fails.
>
> The attached patch fixes this by getting the fraction buts from the
> right place.
> I've also fixed the rounding of the constant used to compute ds for
> _DOUBLE_IS_32BITS so that we keep the error strictly positive as the
> comment above requires.
>
> I've sucessfully run a check-gcc check-target-libstdc++-v3 regresion test
> with this patch.
> check-target-newlib already failed for the baseline, see
> http://sourceware.org/ml/newlib/2006/msg00635.html . I can't investigate
> this now because I have some GCC problems to look into.
>
>
> ------------------------------------------------------------------------
>
> 2006-08-01 J"orn Rennecke <joern.rennecke@st.com>
>
> * dtoa.c (dtoa_r): Handle the denormalized _DOUBLE_IS_32BITS case
> properly.
>
> --- dtoa.c 2002-02-05 17:14:35.000000000 +0000
> +++ /home/afra/users/renneckej/dtoa.c 2006-08-01 18:49:31.000000000 +0100
> @@ -338,15 +338,23 @@ _DEFUN (_dtoa_r,
> /* d is denormalized */
>
> i = bbits + be + (Bias + (P - 1) - 1);
> +#if defined (_DOUBLE_IS_32BITS)
> + x = word0 (d) << (32 - i);
> +#else
> x = (i > 32) ? (word0 (d) << (64 - i)) | (word1 (d) >> (i - 32))
> : (word1 (d) << (32 - i));
> +#endif
> d2.d = x;
> word0 (d2) -= 31 * Exp_msk1; /* adjust exponent */
> i -= (Bias + (P - 1) - 1) + 1;
> denorm = 1;
> }
> #endif
> +#if defined (_DOUBLE_IS_32BITS)
> + ds = (d2.d - 1.5) * 0.289529651 + 0.176091269 + i * 0.30103001;
> +#else
> ds = (d2.d - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
> +#endif
> k = (int) ds;
> if (ds < 0. && ds != k)
> k--; /* want k = floor(ds) */
More information about the Newlib
mailing list