emacs-devel
[Top][All Lists]
Advanced

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

Re: Merging bignum to master


From: Andy Moreton
Subject: Re: Merging bignum to master
Date: Tue, 14 Aug 2018 01:21:51 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1.50 (windows-nt)

On Sun 12 Aug 2018, Tom Tromey wrote:

>>>>>> "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.  */

You have dropped some of the commentary that explains how it is trying
to give similar behaviour to Common Lisp. See the description at:
<http://www.lispworks.com/documentation/lw50/CLHS/Body/f_exp_e.htm>

>        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));

This doesn't work for systems where sizeof (EMACS_INT) > sizeof (long).
> +       xp = &x;
>       }
> -      XSETINT (val, acc);
> +
> +      mpz_init (r);
> +      mpz_pow_ui (r, *xp, XFIXNUM (arg2));
Likewise.

> +
> +      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]