emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] feature/bignum 27980e3 21/24: Make ash and lsh handle bign


From: Tom Tromey
Subject: [Emacs-diffs] feature/bignum 27980e3 21/24: Make ash and lsh handle bignums
Date: Fri, 13 Jul 2018 00:25:10 -0400 (EDT)

branch: feature/bignum
commit 27980e36040d0693fe997de6b6b73c09c3ce1cb5
Author: Tom Tromey <address@hidden>
Commit: Tom Tromey <address@hidden>

    Make ash and lsh handle bignums
    
    * src/data.c (ash_lsh_impl): Handle bignums.
    * test/src/data-tests.el (data-tests-ash-lsh): New test.
---
 src/data.c             | 37 ++++++++++++++++++++++++++++---------
 test/src/data-tests.el |  6 ++++++
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/src/data.c b/src/data.c
index ac74ff5..8a2d600 100644
--- a/src/data.c
+++ b/src/data.c
@@ -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;
 }
 
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 2423d7a..07159df 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -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



reply via email to

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