]> git.eshelyaron.com Git - emacs.git/commitdiff
Make comparison operators handle bignums
authorTom Tromey <tom@tromey.com>
Sat, 7 Jul 2018 21:44:15 +0000 (15:44 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 13 Jul 2018 04:12:27 +0000 (22:12 -0600)
* sc/data.c (bignumcompare): New function.
(arithcompare): Handle bignums.

src/data.c

index 8ffed8bbb52d9f9705565f6356e80e79b33a180c..97554c7e1d27e44b0421c8a628dd2bbd52a8efa1 100644 (file)
@@ -2397,6 +2397,70 @@ bool-vector.  IDX starts at 0.  */)
 \f
 /* Arithmetic functions */
 
+static Lisp_Object
+bignumcompare (Lisp_Object num1, Lisp_Object num2,
+              enum Arith_Comparison comparison)
+{
+  int cmp;
+  bool test;
+
+  if (BIGNUMP (num1))
+    {
+      if (FLOATP (num2))
+       cmp = mpz_cmp_d (XBIGNUM (num1)->value, XFLOAT_DATA (num2));
+      else if (FIXNUMP (num2))
+       cmp = mpz_cmp_si (XBIGNUM (num1)->value, XINT (num2));
+      else
+       {
+         eassume (BIGNUMP (num2));
+         cmp = mpz_cmp (XBIGNUM (num1)->value, XBIGNUM (num2)->value);
+       }
+    }
+  else
+    {
+      eassume (BIGNUMP (num2));
+      if (FLOATP (num1))
+       cmp = - mpz_cmp_d (XBIGNUM (num2)->value, XFLOAT_DATA (num1));
+      else
+       {
+         eassume (FIXNUMP (num1));
+         cmp = - mpz_cmp_si (XBIGNUM (num2)->value, XINT (num1));
+       }
+    }
+
+  switch (comparison)
+    {
+    case ARITH_EQUAL:
+      test = cmp == 0;
+      break;
+
+    case ARITH_NOTEQUAL:
+      test = cmp != 0;
+      break;
+
+    case ARITH_LESS:
+      test = cmp < 0;
+      break;
+
+    case ARITH_LESS_OR_EQUAL:
+      test = cmp <= 0;
+      break;
+
+    case ARITH_GRTR:
+      test = cmp > 0;
+      break;
+
+    case ARITH_GRTR_OR_EQUAL:
+      test = cmp >= 0;
+      break;
+
+    default:
+      eassume (false);
+    }
+
+  return test ? Qt : Qnil;
+}
+
 Lisp_Object
 arithcompare (Lisp_Object num1, Lisp_Object num2,
              enum Arith_Comparison comparison)
@@ -2406,8 +2470,11 @@ arithcompare (Lisp_Object num1, Lisp_Object num2,
   bool fneq;
   bool test;
 
-  CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (num1);
-  CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (num2);
+  CHECK_NUMBER_COERCE_MARKER (num1);
+  CHECK_NUMBER_COERCE_MARKER (num2);
+
+  if (BIGNUMP (num1) || BIGNUMP (num2))
+    return bignumcompare (num1, num2, comparison);
 
   /* If either arg is floating point, set F1 and F2 to the 'double'
      approximations of the two arguments, and set FNEQ if floating-point