]> git.eshelyaron.com Git - emacs.git/commitdiff
Make ash and lsh handle bignums
authorTom Tromey <tom@tromey.com>
Sun, 8 Jul 2018 15:22:17 +0000 (09:22 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 13 Jul 2018 04:12:28 +0000 (22:12 -0600)
* src/data.c (ash_lsh_impl): Handle bignums.
* test/src/data-tests.el (data-tests-ash-lsh): New test.

src/data.c
test/src/data-tests.el

index ac74ff5547fe918320419e7a63aeebea76826d0a..8a2d600b30d823cae48c12379b9012a651fbb72c 100644 (file)
@@ -3298,18 +3298,37 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh)
 
   Lisp_Object val;
 
-  CHECK_FIXNUM (value);
+  CHECK_INTEGER (value);
   CHECK_FIXNUM (count);
 
-  if (XINT (count) >= EMACS_INT_WIDTH)
-    XSETINT (val, 0);
-  else if (XINT (count) > 0)
-    XSETINT (val, XUINT (value) << XINT (count));
-  else if (XINT (count) <= -EMACS_INT_WIDTH)
-    XSETINT (val, lsh ? 0 : XINT (value) < 0 ? -1 : 0);
+  if (BIGNUMP (value))
+    {
+      mpz_t result;
+      mpz_init (result);
+      if (XINT (count) >= 0)
+       mpz_mul_2exp (result, XBIGNUM (value)->value, XINT (count));
+      else
+       mpz_tdiv_q_2exp (result, XBIGNUM (value)->value, - XINT (count));
+      val = make_number (result);
+      mpz_clear (result);
+    }
   else
-    XSETINT (val, (lsh ? XUINT (value) >> -XINT (count)
-                  : XINT (value) >> -XINT (count)));
+    {
+      /* Just do the work as bignums to make the code simpler.  */
+      mpz_t result;
+      eassume (FIXNUMP (value));
+      if (lsh)
+       mpz_init_set_ui (result, XUINT (value));
+      else
+       mpz_init_set_si (result, XINT (value));
+      if (XINT (count) >= 0)
+       mpz_mul_2exp (result, result, XINT (count));
+      else
+       mpz_tdiv_q_2exp (result, result, - XINT (count));
+      val = make_number (result);
+      mpz_clear (result);
+    }
+
   return val;
 }
 
index 2423d7a7098f34c873985a0b1d3a583ff654235f..07159df48cf91c89735786adb3a54bd2c4117e80 100644 (file)
@@ -614,4 +614,10 @@ comparing the subr with a much slower lisp implementation."
     (data-tests-check-sign (% -1 -3) (% nb1 nb3))
     (data-tests-check-sign (mod -1 -3) (mod nb1 nb3))))
 
+(ert-deftest data-tests-ash-lsh ()
+  (should (= (ash most-negative-fixnum 1)
+             (* most-negative-fixnum 2)))
+  (should (= (lsh most-negative-fixnum 1)
+             (* (abs most-negative-fixnum) 2))))
+
 ;;; data-tests.el ends here