mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 16:51:06 -07:00
* lisp.h (bits_word, BITS_WORD_MAX): New type and macro.
All uses of 'size_t' and 'SIZE_MAX' changed to use them, when they're talking about words in Lisp bool vectors. (BITS_PER_BITS_WORD): Rename from BITS_PER_SIZE_T. All uses changed.
This commit is contained in:
parent
4425606000
commit
87c4314d27
4 changed files with 81 additions and 69 deletions
|
|
@ -1,3 +1,10 @@
|
|||
2013-10-08 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* lisp.h (bits_word, BITS_WORD_MAX): New type and macro.
|
||||
All uses of 'size_t' and 'SIZE_MAX' changed to use them, when
|
||||
they're talking about words in Lisp bool vectors.
|
||||
(BITS_PER_BITS_WORD): Rename from BITS_PER_SIZE_T. All uses changed.
|
||||
|
||||
2013-10-07 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Improve support for popcount and counting trailing zeros (Bug#15550).
|
||||
|
|
|
|||
|
|
@ -2017,8 +2017,8 @@ INIT must be an integer that represents a character. */)
|
|||
return val;
|
||||
}
|
||||
|
||||
verify (sizeof (size_t) * CHAR_BIT == BITS_PER_SIZE_T);
|
||||
verify ((BITS_PER_SIZE_T & (BITS_PER_SIZE_T - 1)) == 0);
|
||||
verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD);
|
||||
verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0);
|
||||
|
||||
static ptrdiff_t
|
||||
bool_vector_payload_bytes (ptrdiff_t nr_bits,
|
||||
|
|
@ -2030,14 +2030,14 @@ bool_vector_payload_bytes (ptrdiff_t nr_bits,
|
|||
eassert (nr_bits >= 0);
|
||||
|
||||
exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT;
|
||||
needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_SIZE_T) / CHAR_BIT;
|
||||
needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_BITS_WORD) / CHAR_BIT;
|
||||
|
||||
if (needed_bytes == 0)
|
||||
{
|
||||
/* Always allocate at least one machine word of payload so that
|
||||
bool-vector operations in data.c don't need a special case
|
||||
for empty vectors. */
|
||||
needed_bytes = sizeof (size_t);
|
||||
needed_bytes = sizeof (bits_word);
|
||||
}
|
||||
|
||||
if (exact_needed_bytes_out != NULL)
|
||||
|
|
|
|||
128
src/data.c
128
src/data.c
|
|
@ -2963,24 +2963,24 @@ lowercase l) for small endian machines. */)
|
|||
/* Because we round up the bool vector allocate size to word_size
|
||||
units, we can safely read past the "end" of the vector in the
|
||||
operations below. These extra bits are always zero. Also, we
|
||||
always allocate bool vectors with at least one size_t of storage so
|
||||
always allocate bool vectors with at least one bits_word of storage so
|
||||
that we don't have to special-case empty bit vectors. */
|
||||
|
||||
static size_t
|
||||
static bits_word
|
||||
bool_vector_spare_mask (ptrdiff_t nr_bits)
|
||||
{
|
||||
eassert (nr_bits > 0);
|
||||
return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1;
|
||||
return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1;
|
||||
}
|
||||
|
||||
#if SIZE_MAX <= UINT_MAX
|
||||
# define popcount_size_t count_one_bits
|
||||
#elif SIZE_MAX <= ULONG_MAX
|
||||
# define popcount_size_t count_one_bits_l
|
||||
#elif SIZE_MAX <= ULLONG_MAX
|
||||
# define popcount_size_t count_one_bits_ll
|
||||
#if BITS_WORD_MAX <= UINT_MAX
|
||||
# define popcount_bits_word count_one_bits
|
||||
#elif BITS_WORD_MAX <= ULONG_MAX
|
||||
# define popcount_bits_word count_one_bits_l
|
||||
#elif BITS_WORD_MAX <= ULLONG_MAX
|
||||
# define popcount_bits_word count_one_bits_ll
|
||||
#else
|
||||
# error "size_t wider than long long? Please file a bug report."
|
||||
# error "bits_word wider than long long? Please file a bug report."
|
||||
#endif
|
||||
|
||||
enum bool_vector_op { bool_vector_exclusive_or,
|
||||
|
|
@ -2996,10 +2996,10 @@ bool_vector_binop_driver (Lisp_Object op1,
|
|||
enum bool_vector_op op)
|
||||
{
|
||||
EMACS_INT nr_bits;
|
||||
size_t *adata, *bdata, *cdata;
|
||||
bits_word *adata, *bdata, *cdata;
|
||||
ptrdiff_t i;
|
||||
size_t changed = 0;
|
||||
size_t mword;
|
||||
bits_word changed = 0;
|
||||
bits_word mword;
|
||||
ptrdiff_t nr_words;
|
||||
|
||||
CHECK_BOOL_VECTOR (op1);
|
||||
|
|
@ -3020,11 +3020,11 @@ bool_vector_binop_driver (Lisp_Object op1,
|
|||
}
|
||||
|
||||
eassert (nr_bits >= 0);
|
||||
nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T;
|
||||
nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
|
||||
|
||||
adata = (size_t *) XBOOL_VECTOR (dest)->data;
|
||||
bdata = (size_t *) XBOOL_VECTOR (op1)->data;
|
||||
cdata = (size_t *) XBOOL_VECTOR (op2)->data;
|
||||
adata = (bits_word *) XBOOL_VECTOR (dest)->data;
|
||||
bdata = (bits_word *) XBOOL_VECTOR (op1)->data;
|
||||
cdata = (bits_word *) XBOOL_VECTOR (op2)->data;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
|
|
@ -3054,47 +3054,47 @@ bool_vector_binop_driver (Lisp_Object op1,
|
|||
/* Compute the number of trailing zero bits in val. If val is zero,
|
||||
return the number of bits in val. */
|
||||
static int
|
||||
count_trailing_zero_bits (size_t val)
|
||||
count_trailing_zero_bits (bits_word val)
|
||||
{
|
||||
if (SIZE_MAX == UINT_MAX)
|
||||
if (BITS_WORD_MAX == UINT_MAX)
|
||||
return count_trailing_zeros (val);
|
||||
if (SIZE_MAX == ULONG_MAX)
|
||||
if (BITS_WORD_MAX == ULONG_MAX)
|
||||
return count_trailing_zeros_l (val);
|
||||
# if HAVE_UNSIGNED_LONG_LONG_INT
|
||||
if (SIZE_MAX == ULLONG_MAX)
|
||||
if (BITS_WORD_MAX == ULLONG_MAX)
|
||||
return count_trailing_zeros_ll (val);
|
||||
# endif
|
||||
|
||||
/* The rest of this code is for the unlikely platform where size_t differs
|
||||
/* The rest of this code is for the unlikely platform where bits_word differs
|
||||
in width from unsigned int, unsigned long, and unsigned long long. */
|
||||
if (val == 0)
|
||||
return CHAR_BIT * sizeof (val);
|
||||
if (SIZE_MAX <= UINT_MAX)
|
||||
if (BITS_WORD_MAX <= UINT_MAX)
|
||||
return count_trailing_zeros (val);
|
||||
if (SIZE_MAX <= ULONG_MAX)
|
||||
if (BITS_WORD_MAX <= ULONG_MAX)
|
||||
return count_trailing_zeros_l (val);
|
||||
{
|
||||
# if HAVE_UNSIGNED_LONG_LONG_INT
|
||||
verify (SIZE_MAX <= ULLONG_MAX);
|
||||
verify (BITS_WORD_MAX <= ULLONG_MAX);
|
||||
return count_trailing_zeros_ll (val);
|
||||
# else
|
||||
verify (SIZE_MAX <= ULONG_MAX);
|
||||
verify (BITS_WORD_MAX <= ULONG_MAX);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
size_t_to_host_endian (size_t val)
|
||||
static bits_word
|
||||
bits_word_to_host_endian (bits_word val)
|
||||
{
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
return val;
|
||||
#elif SIZE_MAX >> 31 == 1
|
||||
#elif BITS_WORD_MAX >> 31 == 1
|
||||
return bswap_32 (val);
|
||||
#elif SIZE_MAX >> 31 >> 31 >> 1 == 1
|
||||
#elif BITS_WORD_MAX >> 31 >> 31 >> 1 == 1
|
||||
return bswap_64 (val);
|
||||
#else
|
||||
int i;
|
||||
size_t r = 0;
|
||||
bits_word r = 0;
|
||||
for (i = 0; i < sizeof val; i++)
|
||||
{
|
||||
r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1));
|
||||
|
|
@ -3167,9 +3167,9 @@ Return the destination vector. */)
|
|||
(Lisp_Object a, Lisp_Object b)
|
||||
{
|
||||
EMACS_INT nr_bits;
|
||||
size_t *bdata, *adata;
|
||||
bits_word *bdata, *adata;
|
||||
ptrdiff_t i;
|
||||
size_t mword;
|
||||
bits_word mword;
|
||||
|
||||
CHECK_BOOL_VECTOR (a);
|
||||
nr_bits = XBOOL_VECTOR (a)->size;
|
||||
|
|
@ -3182,20 +3182,20 @@ Return the destination vector. */)
|
|||
nr_bits = min (nr_bits, XBOOL_VECTOR (b)->size);
|
||||
}
|
||||
|
||||
bdata = (size_t *) XBOOL_VECTOR (b)->data;
|
||||
adata = (size_t *) XBOOL_VECTOR (a)->data;
|
||||
bdata = (bits_word *) XBOOL_VECTOR (b)->data;
|
||||
adata = (bits_word *) XBOOL_VECTOR (a)->data;
|
||||
|
||||
eassert (nr_bits >= 0);
|
||||
|
||||
for (i = 0; i < nr_bits / BITS_PER_SIZE_T; i++)
|
||||
for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++)
|
||||
bdata[i] = ~adata[i];
|
||||
|
||||
if (nr_bits % BITS_PER_SIZE_T)
|
||||
if (nr_bits % BITS_PER_BITS_WORD)
|
||||
{
|
||||
mword = size_t_to_host_endian (adata[i]);
|
||||
mword = bits_word_to_host_endian (adata[i]);
|
||||
mword = ~mword;
|
||||
mword &= bool_vector_spare_mask (nr_bits);
|
||||
bdata[i] = size_t_to_host_endian (mword);
|
||||
bdata[i] = bits_word_to_host_endian (mword);
|
||||
}
|
||||
|
||||
return b;
|
||||
|
|
@ -3209,28 +3209,28 @@ A must be a bool vector. B is a generalized bool. */)
|
|||
{
|
||||
ptrdiff_t count;
|
||||
EMACS_INT nr_bits;
|
||||
size_t *adata;
|
||||
size_t match;
|
||||
bits_word *adata;
|
||||
bits_word match;
|
||||
ptrdiff_t i;
|
||||
|
||||
CHECK_BOOL_VECTOR (a);
|
||||
|
||||
nr_bits = XBOOL_VECTOR (a)->size;
|
||||
count = 0;
|
||||
match = NILP (b) ? (size_t) -1 : 0;
|
||||
adata = (size_t *) XBOOL_VECTOR (a)->data;
|
||||
match = NILP (b) ? -1 : 0;
|
||||
adata = (bits_word *) XBOOL_VECTOR (a)->data;
|
||||
|
||||
eassert (nr_bits >= 0);
|
||||
|
||||
for (i = 0; i < nr_bits / BITS_PER_SIZE_T; ++i)
|
||||
count += popcount_size_t (adata[i] ^ match);
|
||||
for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i)
|
||||
count += popcount_bits_word (adata[i] ^ match);
|
||||
|
||||
/* Mask out trailing parts of final mword. */
|
||||
if (nr_bits % BITS_PER_SIZE_T)
|
||||
if (nr_bits % BITS_PER_BITS_WORD)
|
||||
{
|
||||
size_t mword = adata[i] ^ match;
|
||||
mword = size_t_to_host_endian (mword);
|
||||
count += popcount_size_t (mword & bool_vector_spare_mask (nr_bits));
|
||||
bits_word mword = adata[i] ^ match;
|
||||
mword = bits_word_to_host_endian (mword);
|
||||
count += popcount_bits_word (mword & bool_vector_spare_mask (nr_bits));
|
||||
}
|
||||
|
||||
return make_number (count);
|
||||
|
|
@ -3247,9 +3247,9 @@ index into the vector. */)
|
|||
ptrdiff_t count;
|
||||
EMACS_INT nr_bits;
|
||||
ptrdiff_t offset;
|
||||
size_t *adata;
|
||||
size_t twiddle;
|
||||
size_t mword; /* Machine word. */
|
||||
bits_word *adata;
|
||||
bits_word twiddle;
|
||||
bits_word mword; /* Machine word. */
|
||||
ptrdiff_t pos;
|
||||
ptrdiff_t nr_words;
|
||||
|
||||
|
|
@ -3260,30 +3260,30 @@ index into the vector. */)
|
|||
if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */
|
||||
args_out_of_range (a, i);
|
||||
|
||||
adata = (size_t *) XBOOL_VECTOR (a)->data;
|
||||
adata = (bits_word *) XBOOL_VECTOR (a)->data;
|
||||
|
||||
assume (nr_bits >= 0);
|
||||
nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T;
|
||||
nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
|
||||
|
||||
pos = XFASTINT (i) / BITS_PER_SIZE_T;
|
||||
offset = XFASTINT (i) % BITS_PER_SIZE_T;
|
||||
pos = XFASTINT (i) / BITS_PER_BITS_WORD;
|
||||
offset = XFASTINT (i) % BITS_PER_BITS_WORD;
|
||||
count = 0;
|
||||
|
||||
/* By XORing with twiddle, we transform the problem of "count
|
||||
consecutive equal values" into "count the zero bits". The latter
|
||||
operation usually has hardware support. */
|
||||
twiddle = NILP (b) ? 0 : (size_t) -1;
|
||||
twiddle = NILP (b) ? 0 : -1;
|
||||
|
||||
/* Scan the remainder of the mword at the current offset. */
|
||||
if (pos < nr_words && offset != 0)
|
||||
{
|
||||
mword = size_t_to_host_endian (adata[pos]);
|
||||
mword = bits_word_to_host_endian (adata[pos]);
|
||||
mword ^= twiddle;
|
||||
mword >>= offset;
|
||||
count = count_trailing_zero_bits (mword);
|
||||
count = min (count, BITS_PER_SIZE_T - offset);
|
||||
count = min (count, BITS_PER_BITS_WORD - offset);
|
||||
pos++;
|
||||
if (count + offset < BITS_PER_SIZE_T)
|
||||
if (count + offset < BITS_PER_BITS_WORD)
|
||||
return make_number (count);
|
||||
}
|
||||
|
||||
|
|
@ -3292,7 +3292,7 @@ index into the vector. */)
|
|||
endian-independent. */
|
||||
while (pos < nr_words && adata[pos] == twiddle)
|
||||
{
|
||||
count += BITS_PER_SIZE_T;
|
||||
count += BITS_PER_BITS_WORD;
|
||||
++pos;
|
||||
}
|
||||
|
||||
|
|
@ -3300,16 +3300,16 @@ index into the vector. */)
|
|||
{
|
||||
/* If we stopped because of a mismatch, see how many bits match
|
||||
in the current mword. */
|
||||
mword = size_t_to_host_endian (adata[pos]);
|
||||
mword = bits_word_to_host_endian (adata[pos]);
|
||||
mword ^= twiddle;
|
||||
count += count_trailing_zero_bits (mword);
|
||||
}
|
||||
else if (nr_bits % BITS_PER_SIZE_T != 0)
|
||||
else if (nr_bits % BITS_PER_BITS_WORD != 0)
|
||||
{
|
||||
/* If we hit the end, we might have overshot our count. Reduce
|
||||
the total by the number of spare bits at the end of the
|
||||
vector. */
|
||||
count -= BITS_PER_SIZE_T - nr_bits % BITS_PER_SIZE_T;
|
||||
count -= BITS_PER_BITS_WORD - nr_bits % BITS_PER_BITS_WORD;
|
||||
}
|
||||
|
||||
return make_number (count);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ typedef unsigned int EMACS_UINT;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* An unsigned integer type representing a fixed-length bit sequence,
|
||||
suitable for words in a Lisp bool vector. */
|
||||
typedef size_t bits_word;
|
||||
#define BITS_WORD_MAX SIZE_MAX
|
||||
|
||||
/* Number of bits in some machine integer types. */
|
||||
enum
|
||||
{
|
||||
|
|
@ -71,7 +76,7 @@ enum
|
|||
BITS_PER_SHORT = CHAR_BIT * sizeof (short),
|
||||
BITS_PER_INT = CHAR_BIT * sizeof (int),
|
||||
BITS_PER_LONG = CHAR_BIT * sizeof (long int),
|
||||
BITS_PER_SIZE_T = CHAR_BIT * sizeof (size_t),
|
||||
BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word),
|
||||
BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT)
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue