scm-discuss
[Top][All Lists]
Advanced

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

[Scm-discuss] 5f2 regression: r4rstest.scm fails on 32-bit


From: Steve VanDevender
Subject: [Scm-discuss] 5f2 regression: r4rstest.scm fails on 32-bit
Date: Thu, 12 Oct 2017 11:45:15 -0700

Here is a patch that fixes the problems with floating-point number
conversion to strings on 32-bit systems.  With this SCM 5f2 passes all
of its distributed tests even when compiled with -O2 (at least using GCC
6.3.0 in Debian Stretch).

The issue is that on a 32-bit system, certain intermediate results
during number->string conversion have to be held in SCM bignums, and
some SCM procedures return their argument value when it would not be
modified by an operation (such as product(n, 1) or scm_ash(n, 0)
returning n rather than a copy of n).  This caused some bignum values to
become aliases of each other so when bigrecy() was called on one, it
would wipe out the other that was still to be used later.  This problem
does not occur on 64-bit systems where the intermediate values fit in a
SCM INUM and bignum recycling does not apply.  Adding a few checks in
pdbl2str and pmantexp2bdl to prevent recycling when such aliasing occurs
eliminates the problems (other functions involved in number->string
conversion have similar checks).

--- scm/scl.c~  2015-01-02 19:43:33.000000000 -0800
+++ scm/scl.c   2017-10-12 11:18:36.010486623 -0700
@@ -166,7 +166,7 @@
     /* try first with starved precision */
     {
       num = scm_ash(mant, MAKINUM(e2 - point));
-      bigrecy(mant);
+      if (num != mant) bigrecy(mant);
       quo = scm_round_quotient(num, VELTS(pows5)[(long) point]);
       if (pmantexp2dbl(quo, point) != f) {
        bigrecy(quo); quo = num;
@@ -180,7 +180,7 @@
     {
       SCM den = scm_ash(MAKINUM(1L), MAKINUM(point - e2));
       num = product(mant, VELTS(pows5)[- (long) point]);
-      bigrecy(mant);
+      if (num != mant) bigrecy(mant);
       quo = scm_round_quotient(num, den);
       if (pmantexp2dbl(quo, point) != f) {
        bigrecy(quo); quo = num;
@@ -192,7 +192,7 @@
       bigrecy(den);
     }
   }
-  bigrecy(num);
+  if (num != mant) bigrecy(num);
   a[ch++] = '.';
   /* if (sizeof(UBIGLONG)>=sizeof(double)) /\* Is ulong larger than mantissa? 
*\/ */
   /*   ch += iulong2str(num2ulong(quo, (char *)ARG1, s_number2string), 10, 
&a[ch]); */
@@ -680,7 +680,7 @@
       ans = ldexp(ans, bex + point);
     }
     if (num != quo) bigrecy(quo);
-    if (bmant != MAKINUM(1L)) bigrecy(num);
+    if (num != bmant && bmant != MAKINUM(1L)) bigrecy(num);
     return ans;
   } else {
     int maxpow = LENGTH(pows5) - 1;



reply via email to

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