mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-27 07:37:33 +00:00
Don’t signal overflow for (expt 1 bignum)
Similarly for (expt 0 bignum) and (expt -1 bignum). The result is always a -1, 0 or 1, so do not signal overflow. * src/data.c (expt_integer): Do not signal an overflow if -1 <= X <= 1. Be clearer about when overflow is signaled. * test/src/floatfns-tests.el (bignum-expt): Test this.
This commit is contained in:
parent
96c8e4fa41
commit
5ab29400a4
27
src/data.c
27
src/data.c
@ -3290,14 +3290,29 @@ In this case, the sign bit is duplicated. */)
|
||||
Lisp_Object
|
||||
expt_integer (Lisp_Object x, Lisp_Object y)
|
||||
{
|
||||
/* Special cases for -1 <= x <= 1, which never overflow. */
|
||||
if (EQ (x, make_fixnum (1)))
|
||||
return x;
|
||||
if (EQ (x, make_fixnum (0)))
|
||||
return EQ (x, y) ? make_fixnum (1) : x;
|
||||
if (EQ (x, make_fixnum (-1)))
|
||||
return ((FIXNUMP (y) ? XFIXNUM (y) & 1 : mpz_odd_p (*xbignum_val (y)))
|
||||
? x : make_fixnum (1));
|
||||
|
||||
unsigned long exp;
|
||||
if (TYPE_RANGED_FIXNUMP (unsigned long, y))
|
||||
exp = XFIXNUM (y);
|
||||
else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (y)
|
||||
&& mpz_fits_ulong_p (*xbignum_val (y)))
|
||||
exp = mpz_get_ui (*xbignum_val (y));
|
||||
if (FIXNUMP (y))
|
||||
{
|
||||
if (ULONG_MAX < XFIXNUM (y))
|
||||
overflow_error ();
|
||||
exp = XFIXNUM (y);
|
||||
}
|
||||
else
|
||||
overflow_error ();
|
||||
{
|
||||
if (ULONG_MAX <= MOST_POSITIVE_FIXNUM
|
||||
|| !mpz_fits_ulong_p (*xbignum_val (y)))
|
||||
overflow_error ();
|
||||
exp = mpz_get_ui (*xbignum_val (y));
|
||||
}
|
||||
|
||||
emacs_mpz_pow_ui (mpz[0], *bignum_integer (&mpz[0], x), exp);
|
||||
return make_integer_mpz ();
|
||||
|
@ -51,7 +51,12 @@
|
||||
(ert-deftest bignum-expt ()
|
||||
(dolist (n (list most-positive-fixnum (1+ most-positive-fixnum)
|
||||
most-negative-fixnum (1- most-negative-fixnum)
|
||||
(* 5 most-negative-fixnum)
|
||||
(* 5 (1+ most-positive-fixnum))
|
||||
-2 -1 0 1 2))
|
||||
(should (or (<= n 0) (= (expt 0 n) 0)))
|
||||
(should (= (expt 1 n) 1))
|
||||
(should (or (< n 0) (= (expt -1 n) (if (zerop (logand n 1)) 1 -1))))
|
||||
(should (= (expt n 0) 1))
|
||||
(should (= (expt n 1) n))
|
||||
(should (= (expt n 2) (* n n)))
|
||||
|
Loading…
Reference in New Issue
Block a user