emacs-devel
[Top][All Lists]
Advanced

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

Re: Merging bignum to master


From: Tom Tromey
Subject: Re: Merging bignum to master
Date: Sun, 12 Aug 2018 10:34:29 -0600
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1.50 (gnu/linux)

>>>>> "Basil" == Basil L Contovounesios <address@hidden> writes:

Basil> It'd be nice if expt could be updated to handle bignums:

What do you think of this?

Tom

diff --git a/src/floatfns.c b/src/floatfns.c
index bbf7df4db3..c55418a35c 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -206,25 +206,28 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
 {
   CHECK_FIXNUM_OR_FLOAT (arg1);
   CHECK_FIXNUM_OR_FLOAT (arg2);
-  if (FIXNUMP (arg1)     /* common lisp spec */
+  if (INTEGERP (arg1)     /* common lisp spec */
       && FIXNUMP (arg2)   /* don't promote, if both are ints, and */
       && XFIXNUM (arg2) >= 0) /* we are sure the result is not fractional */
     {                          /* this can be improved by pre-calculating */
-      EMACS_INT y;             /* some binary powers of x then accumulating */
-      EMACS_UINT acc, x;  /* Unsigned so that overflow is well defined.  */
       Lisp_Object val;
+      mpz_t x, *xp, r;
 
-      x = XFIXNUM (arg1);
-      y = XFIXNUM (arg2);
-      acc = (y & 1 ? x : 1);
-
-      while ((y >>= 1) != 0)
+      if (BIGNUMP (arg1))
+       xp = &XBIGNUM (arg1)->value;
+      else
        {
-         x *= x;
-         if (y & 1)
-           acc *= x;
+         mpz_init_set_si (x, XFIXNUM (arg1));
+         xp = &x;
        }
-      XSETINT (val, acc);
+
+      mpz_init (r);
+      mpz_pow_ui (r, *xp, XFIXNUM (arg2));
+
+      val = make_number (r);
+      mpz_clear (r);
+      if (xp == &x)
+       mpz_clear (x);
       return val;
     }
   return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2)));
diff --git a/test/src/floatfns-tests.el b/test/src/floatfns-tests.el
index 7714c05d60..4fab032ecb 100644
--- a/test/src/floatfns-tests.el
+++ b/test/src/floatfns-tests.el
@@ -46,4 +46,8 @@
   (should (= (+ (logb most-positive-fixnum) 1)
              (logb (+ most-positive-fixnum 1)))))
 
+(ert-deftest bignum-expt ()
+  (should (= (expt 10 100)
+             (apply #'* (make-list 100 10)))))
+
 (provide 'floatfns-tests)



reply via email to

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