scm-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Scm-discuss] int2dbl() bug on 32-bit systems


From: Steve VanDevender
Subject: [Scm-discuss] int2dbl() bug on 32-bit systems
Date: Fri, 13 Oct 2017 22:00:09 -0700

While playing around with the latest development snapshot of SCM on a
32-bit system I discovered another bug.  The most simple way to
reproduce it:

(exact->inexact (+ most-positive-fixnum 1)) => 0.

Specifically numbers in the range (+ most-positive-fixnum 1) and
(- (expt 2 (* 3 BITSPERDIG)) 1), or bignums with 2 or 3 BIGDIGS, convert
to 0. instead of the correct value on 32-bit systems.

This is because in int2dbl(), the "sizet" type, which is unsigned, is
used for a variable 'j' but a negative value may be computed for it and
instead treated as a very large positive result.  Since 'j' can never
test as less than 0, a later comparison does not set it to zero if it
has a negative value, and a loop that extracts BIGDIGs for conversion
will not run either, leaving 'ans' at its initial value of 0.  This is
another problem that does not occur on 64-bit systems as the typical
values of dbl_mant_dig and BITSPERDIG do not result in a negative value
being assigned to 'j' for bignums of 2 or 3 BIGDIGS.

Here is a proposed patch:

--- scl.c~      2016-09-01 16:53:54.000000000 -0700
+++ scl.c       2017-10-13 21:23:26.918663120 -0700
@@ -2835,9 +2835,10 @@
       ans = ldexp((double)(INUM(quo)), bex);
     else {
       sizet i = NUMDIGS(quo);
-      sizet j = i - (dbl_mant_dig + BITSPERDIG - 1)/BITSPERDIG;
+      sizet j = (dbl_mant_dig + BITSPERDIG - 1)/BITSPERDIG;
       BIGDIG *digits = BDIGITS(quo);
-      if (j < 0) j = 0;
+      if (j < i) j = i - j;
+      else j = 0;
       while (i-- > j) ans = digits[i] + ldexp(ans, BITSPERDIG);
       bex += j * BITSPERDIG;
       if (bex > 0) ans = ldexp(ans, bex);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]