This is the mail archive of the newlib@sourceware.org mailing list for the newlib 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: RFA: Fix _DOUBLE_IS_32BITS handling of denormals in dtoa.c


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) */


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