diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/alloc.c b/src/alloc.c index 1dc1bbb031a..367bb73fc15 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3815,6 +3815,34 @@ make_number (mpz_t value) | |||
| 3815 | } | 3815 | } |
| 3816 | } | 3816 | } |
| 3817 | 3817 | ||
| 3818 | /* Check if fixnum can be larger than long. */ | ||
| 3819 | if (sizeof (EMACS_INT) > sizeof (long)) | ||
| 3820 | { | ||
| 3821 | size_t bits = mpz_sizeinbase (value, 2); | ||
| 3822 | int sign = mpz_sgn (value); | ||
| 3823 | |||
| 3824 | if (bits < FIXNUM_BITS + (sign < 0)) | ||
| 3825 | { | ||
| 3826 | EMACS_INT v = 0; | ||
| 3827 | size_t limbs = mpz_size (value); | ||
| 3828 | mp_size_t i; | ||
| 3829 | |||
| 3830 | for (i = 0; i < limbs; i++) | ||
| 3831 | { | ||
| 3832 | mp_limb_t limb = mpz_getlimbn (value, i); | ||
| 3833 | v |= (EMACS_INT) ((EMACS_UINT) limb << (i * GMP_NUMB_BITS)); | ||
| 3834 | } | ||
| 3835 | if (sign < 0) | ||
| 3836 | v = -v; | ||
| 3837 | |||
| 3838 | if (!FIXNUM_OVERFLOW_P (v)) | ||
| 3839 | { | ||
| 3840 | XSETINT (obj, v); | ||
| 3841 | return obj; | ||
| 3842 | } | ||
| 3843 | } | ||
| 3844 | } | ||
| 3845 | |||
| 3818 | obj = allocate_misc (Lisp_Misc_Bignum); | 3846 | obj = allocate_misc (Lisp_Misc_Bignum); |
| 3819 | b = XBIGNUM (obj); | 3847 | b = XBIGNUM (obj); |
| 3820 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the | 3848 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the |