Function: bool-vector-count-consecutive
bool-vector-count-consecutive is a function defined in data.c.
Signature
(bool-vector-count-consecutive A B I)
Documentation
Count how many consecutive elements in A equal B starting at I.
A is a bool vector, B is t or nil, and I is an index into A.
Probably introduced at or before Emacs version 24.4.
Source Code
// Defined in /usr/src/emacs/src/data.c
{
EMACS_INT count;
EMACS_INT nr_bits;
int offset;
bits_word *adata;
bits_word twiddle;
bits_word mword; /* Machine word. */
ptrdiff_t pos, pos0;
ptrdiff_t nr_words;
CHECK_BOOL_VECTOR (a);
CHECK_FIXNAT (i);
nr_bits = bool_vector_size (a);
if (XFIXNAT (i) > nr_bits) /* Allow one past the end for convenience */
args_out_of_range (a, i);
adata = bool_vector_data (a);
nr_words = bool_vector_words (nr_bits);
pos = XFIXNAT (i) / BITS_PER_BITS_WORD;
offset = XFIXNAT (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 : BITS_WORD_MAX;
/* Scan the remainder of the mword at the current offset. */
if (pos < nr_words && offset != 0)
{
mword = bits_word_to_host_endian (adata[pos]);
mword ^= twiddle;
mword >>= offset;
/* Do not count the pad bits. */
mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset);
count = stdc_trailing_zeros (mword);
pos++;
if (count + offset < BITS_PER_BITS_WORD)
return make_fixnum (count);
}
/* Scan whole words until we either reach the end of the vector or
find an mword that doesn't completely match. twiddle is
endian-independent. */
pos0 = pos;
while (pos < nr_words && adata[pos] == twiddle)
pos++;
count += (pos - pos0) * BITS_PER_BITS_WORD;
if (pos < nr_words)
{
/* If we stopped because of a mismatch, see how many bits match
in the current mword. */
mword = bits_word_to_host_endian (adata[pos]);
mword ^= twiddle;
count += stdc_trailing_zeros (mword);
}
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_BITS_WORD - nr_bits % BITS_PER_BITS_WORD;
}
return make_fixnum (count);
}