mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-18 10:16:51 +00:00
Improve --with-wide-int mpz_t→fixnum conversion
These tuneups and minor simplifications should affect only platforms with EMACS_INT wider than ‘long’. * src/alloc.c (make_number): If the number fits in long but not in fixnum, do not attempt to convert to fixnum again. Tighten the compile-time check for whether the second attempt is worth trying, from sizeof (long) < sizeof (EMACS_INT) to LONG_WIDTH < FIXNUM_BITS. Do not bother computing the sign of the value to tighten the bounds for whether to try the second attempt, as it’s not worth the effort. Do not call mpz_size, which is unnecessary since the number of bits is already known and the loop can iterate over a shift count instead. Avoid unnecessary casts. Use + instead of | where either will do, as + is typically better for optimization. Improve mpz_t to fixnum when --with-wide-int * src/alloc.c (make_number): Avoid undefined behavior when shifting an EMACS_UINT by more than EMACS_UINT_WIDTH bits. Check for integer overflow when shifting.
This commit is contained in:
parent
1d2df2fd03
commit
6eade1efde
19
src/alloc.c
19
src/alloc.c
@ -3752,25 +3752,20 @@ make_number (mpz_t value)
|
||||
if (!FIXNUM_OVERFLOW_P (l))
|
||||
return make_fixnum (l);
|
||||
}
|
||||
|
||||
/* Check if fixnum can be larger than long. */
|
||||
if (sizeof (EMACS_INT) > sizeof (long))
|
||||
else if (LONG_WIDTH < FIXNUM_BITS)
|
||||
{
|
||||
size_t bits = mpz_sizeinbase (value, 2);
|
||||
int sign = mpz_sgn (value);
|
||||
|
||||
if (bits < FIXNUM_BITS + (sign < 0))
|
||||
if (bits <= FIXNUM_BITS)
|
||||
{
|
||||
EMACS_INT v = 0;
|
||||
size_t limbs = mpz_size (value);
|
||||
mp_size_t i;
|
||||
|
||||
for (i = 0; i < limbs; i++)
|
||||
int i = 0;
|
||||
for (int shift = 0; shift < bits; shift += mp_bits_per_limb)
|
||||
{
|
||||
mp_limb_t limb = mpz_getlimbn (value, i);
|
||||
v |= (EMACS_INT) ((EMACS_UINT) limb << (i * mp_bits_per_limb));
|
||||
EMACS_INT limb = mpz_getlimbn (value, i++);
|
||||
v += limb << shift;
|
||||
}
|
||||
if (sign < 0)
|
||||
if (mpz_sgn (value) < 0)
|
||||
v = -v;
|
||||
|
||||
if (!FIXNUM_OVERFLOW_P (v))
|
||||
|
Loading…
Reference in New Issue
Block a user