Bit twiddling

Thomas Lindgren thomasl_erlang@REDACTED
Thu Mar 31 17:56:00 CEST 2005


--- Joel Reymont <joelr1@REDACTED> wrote:
> Folks,
> 
> What's the most effective way to do bit twiddling in
> Erlang? 
> 
> Should I convert the int into a list of bits? How
> would I efficiently do this?

No, a list of bits is not the way to go.

> I'm looking to figure out the highest and lowest bit
> set in an integer as
> well as count the number of bits set.

I won't claim these to be ultimately fast, but they
can serve as a starting point.

All of the following work by breaking down the integer
into a number of subfields, then using the subfield to
index into a table, and finally summing the results.
The table implementation is what differs.

Note: these won't work for negative numbers.

1.
The straightforward approach is to define a function
as a lookup table, e.g. something like:

-module(bits).
-export([count_byte/1, ...]).

%% simple 4-bit lookup table

count_bits(2#0000) -> 0;
count_bits(2#0001) -> 1;
count_bits(2#0010) -> 1;
...
count_bits(2#1111) -> 4.

%% count bits per integer

count(X) -> count(X, 0).

count(0, N) -> N;
count(X, N) -> 
   count(X bsr 4, N + count_bits(X band 15)).

%% if you have, say, a 4-byte int, then try unrolling
%% the above loop into eight count_bits calls and see
%% if that's faster

2. The lookup table could alternatively be implemented
as an ets-table, which you have to populate
beforehand. Ets is a bit messier to use, but if you
are indexing on a large subword (a short, even?), it
might scale better than using a function as a table
like above. Here is the equivalent of the above loop. 

count_bits(0, N) -> N;
count_bits(X, N) ->
   case ets:lookup(?bit_table, X band ?mask) of
      [{_X, NumBits}] -> 
         count_bits(X bsr ?shift, N+NumBits);
      [] -> %% oops
         exit({bad_value, X band ?mask});
   end.

3. Or a third kind of lookup table: use the humble
tuple as a vector. In this case, create a tuple where
position N holds the number of bits in N (or N-1):

Create table:
   Table = list_to_tuple([0, 1, 1, ...])

Note that you can create very large tuples if you
like, but do pass the Table around in the loop once
you have created it. Repeatedly evaluating Table = ...
will end in tears, performancewise.

Index into it:

   ...
   Index = X band 15,
   NumBits = element(Index+1, Table),
   ...

(Since tuple indexing is 1-based, we have to adjust
Index)

Highest and lowest bit can be coded as variations of
the above.

Best,
Thomas


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the erlang-questions mailing list