diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/data.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/data.c b/src/data.c index 1d9222e75a7..a338dadfb69 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -3290,14 +3290,29 @@ In this case, the sign bit is duplicated. */) | |||
| 3290 | Lisp_Object | 3290 | Lisp_Object |
| 3291 | expt_integer (Lisp_Object x, Lisp_Object y) | 3291 | expt_integer (Lisp_Object x, Lisp_Object y) |
| 3292 | { | 3292 | { |
| 3293 | /* Special cases for -1 <= x <= 1, which never overflow. */ | ||
| 3294 | if (EQ (x, make_fixnum (1))) | ||
| 3295 | return x; | ||
| 3296 | if (EQ (x, make_fixnum (0))) | ||
| 3297 | return EQ (x, y) ? make_fixnum (1) : x; | ||
| 3298 | if (EQ (x, make_fixnum (-1))) | ||
| 3299 | return ((FIXNUMP (y) ? XFIXNUM (y) & 1 : mpz_odd_p (*xbignum_val (y))) | ||
| 3300 | ? x : make_fixnum (1)); | ||
| 3301 | |||
| 3293 | unsigned long exp; | 3302 | unsigned long exp; |
| 3294 | if (TYPE_RANGED_FIXNUMP (unsigned long, y)) | 3303 | if (FIXNUMP (y)) |
| 3295 | exp = XFIXNUM (y); | 3304 | { |
| 3296 | else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (y) | 3305 | if (ULONG_MAX < XFIXNUM (y)) |
| 3297 | && mpz_fits_ulong_p (*xbignum_val (y))) | 3306 | overflow_error (); |
| 3298 | exp = mpz_get_ui (*xbignum_val (y)); | 3307 | exp = XFIXNUM (y); |
| 3308 | } | ||
| 3299 | else | 3309 | else |
| 3300 | overflow_error (); | 3310 | { |
| 3311 | if (ULONG_MAX <= MOST_POSITIVE_FIXNUM | ||
| 3312 | || !mpz_fits_ulong_p (*xbignum_val (y))) | ||
| 3313 | overflow_error (); | ||
| 3314 | exp = mpz_get_ui (*xbignum_val (y)); | ||
| 3315 | } | ||
| 3301 | 3316 | ||
| 3302 | emacs_mpz_pow_ui (mpz[0], *bignum_integer (&mpz[0], x), exp); | 3317 | emacs_mpz_pow_ui (mpz[0], *bignum_integer (&mpz[0], x), exp); |
| 3303 | return make_integer_mpz (); | 3318 | return make_integer_mpz (); |