(scm_integer_length): On negative bignums, adjust
authorKevin Ryde <user42@zip.com.au>
Sat, 10 May 2003 00:05:51 +0000 (00:05 +0000)
committerKevin Ryde <user42@zip.com.au>
Sat, 10 May 2003 00:05:51 +0000 (00:05 +0000)
mpz_sizeinbase to account for it looking at absolute value where we
want ones-complement.

libguile/numbers.c

index 3fc5126..4a82873 100644 (file)
@@ -1438,7 +1438,14 @@ SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
     };
     return SCM_MAKINUM (c - 4 + l);
   } else if (SCM_BIGP (n)) {
+    /* mpz_sizeinbase looks at the absolute value of negatives, whereas we
+       want a ones-complement.  If n is ...111100..00 then mpz_sizeinbase is
+       1 too big, so check for that and adjust.  */
     size_t size = mpz_sizeinbase (SCM_I_BIG_MPZ (n), 2);
+    if (mpz_sgn (SCM_I_BIG_MPZ (n)) < 0
+        && mpz_scan0 (SCM_I_BIG_MPZ (n),  /* no 0 bits above the lowest 1 */
+                      mpz_scan1 (SCM_I_BIG_MPZ (n), 0)) == ULONG_MAX)
+      size--;
     scm_remember_upto_here_1 (n);
     return SCM_MAKINUM (size);
   } else {