* numbers.c (scm_mkbig): Add cast, and note that signed/unsigned
authorJim Blandy <jimb@red-bean.com>
Sun, 6 Sep 1998 18:15:59 +0000 (18:15 +0000)
committerJim Blandy <jimb@red-bean.com>
Sun, 6 Sep 1998 18:15:59 +0000 (18:15 +0000)
comparison is okay here.
* numbers.c (scm_istr2int): Add cast; len is known to be positive.
* numbers.c (scm_bigcomp): Clarify logic, and avoid relying on the
(true, but confusing) fact that -1 == ((unsigned) 0 - 1).
* numbers.c (scm_adjbig): Make nsiz an scm_sizet, to avoid mixing
signed/unsigned.

libguile/numbers.c

index e981484..3a3e10a 100644 (file)
@@ -712,7 +712,8 @@ scm_mkbig(nlen, sign)
      int sign;
 {
   SCM v = nlen;
-  if (((v << 16) >> 16) != nlen)
+  /* Cast to SCM to avoid signed/unsigned comparison warnings.  */
+  if (((v << 16) >> 16) != (SCM) nlen)
     scm_wta(SCM_MAKINUM(nlen), (char *)SCM_NALLOC, s_bignum);
   SCM_NEWCELL(v);
   SCM_DEFER_INTS;
@@ -746,13 +747,21 @@ scm_adjbig(b, nlen)
      SCM b;
      scm_sizet nlen;
 {
-  long nsiz = nlen;
-  if (((nsiz << 16) >> 16) != nlen) scm_wta(SCM_MAKINUM(nsiz), (char *)SCM_NALLOC, s_adjbig);
+  scm_sizet nsiz = nlen;
+  if (((nsiz << 16) >> 16) != nlen)
+    scm_wta (scm_ulong2num (nsiz), (char *)SCM_NALLOC, s_adjbig);
+
   SCM_DEFER_INTS;
-  SCM_SETCHARS(b, (SCM_BIGDIG *)scm_must_realloc((char *)SCM_CHARS(b),
-                                        (long)(SCM_NUMDIGS(b)*sizeof(SCM_BIGDIG)),
-                                        (long)(nsiz*sizeof(SCM_BIGDIG)), s_adjbig));
-  SCM_SETNUMDIGS(b, nsiz, SCM_TYP16(b));
+  {
+    SCM_BIGDIG *digits
+      = ((SCM_BIGDIG *)
+        scm_must_realloc((char *)SCM_CHARS(b),
+                         (long)(SCM_NUMDIGS(b)*sizeof(SCM_BIGDIG)),
+                         (long)(nsiz*sizeof(SCM_BIGDIG)), s_adjbig));
+
+    SCM_SETCHARS (b, digits);
+    SCM_SETNUMDIGS (b, nsiz, SCM_TYP16(b));
+  }
   SCM_ALLOW_INTS;
   return b;
 }
@@ -903,14 +912,32 @@ scm_bigcomp(x, y)
   int xsign = SCM_BIGSIGN(x);
   int ysign = SCM_BIGSIGN(y);
   scm_sizet xlen, ylen;
+
+  /* Look at the signs, first.  */
   if (ysign < xsign) return 1;
   if (ysign > xsign) return -1;
-  if ((ylen = SCM_NUMDIGS(y)) > (xlen = SCM_NUMDIGS(x))) return (xsign) ? -1 : 1;
+
+  /* They're the same sign, so see which one has more digits.  Note
+     that, if they are negative, the longer number is the lesser.  */
+  ylen = SCM_NUMDIGS(y);
+  xlen = SCM_NUMDIGS(x);
+  if (ylen > xlen)
+    return (xsign) ? -1 : 1;
   if (ylen < xlen) return (xsign) ? 1 : -1;
-  while(xlen-- && (SCM_BDIGITS(y)[xlen]==SCM_BDIGITS(x)[xlen]));
-  if (-1==xlen) return 0;
-  return (SCM_BDIGITS(y)[xlen] > SCM_BDIGITS(x)[xlen]) ?
-    (xsign ? -1 : 1) : (xsign ? 1 : -1);
+
+  /* They have the same number of digits, so find the most significant
+     digit where they differ.  */
+  while (xlen)
+    {
+      --xlen;
+      if (SCM_BDIGITS (y)[xlen] != SCM_BDIGITS (x)[xlen])
+       /* Make the discrimination based on the digit that differs.  */
+       return (SCM_BDIGITS(y)[xlen] > SCM_BDIGITS(x)[xlen]) ?
+         (xsign ? -1 : 1) : (xsign ? 1 : -1);
+    }
+
+  /* The numbers are identical.  */
+  return 0;
 }
 
 #ifndef SCM_DIGSTOOBIG
@@ -1550,7 +1577,9 @@ scm_istr2int(str, len, radix)
   else j = 1+(len*sizeof(char))/(SCM_BITSPERDIG);
   switch (str[0]) {            /* leading sign */
   case '-':
-  case '+': if (++i==len) return SCM_BOOL_F; /* bad if lone `+' or `-' */
+  case '+':
+    if (++i==(unsigned) len)
+      return SCM_BOOL_F; /* bad if lone `+' or `-' */
   }
   res = scm_mkbig(j, '-'==str[0]);
   ds = SCM_BDIGITS(res);
@@ -1583,7 +1612,7 @@ scm_istr2int(str, len, radix)
     default:
       return SCM_BOOL_F;               /* not a digit */
     }
-  } while (i < len);
+  } while (i < (unsigned) len);
   if (blen * SCM_BITSPERDIG/SCM_CHAR_BIT <= sizeof(SCM))
     if SCM_INUMP(res = scm_big2inum(res, blen)) return res;
   if (j==blen) return res;