Как работает эта реализация bitset:: count()?

Здесь реализация std::bitset::count с MSVC 2010:

size_t count() const
    {   // count number of set bits
    static char _Bitsperhex[] = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";
    size_t _Val = 0;
    for (int _Wpos = _Words; 0 <= _Wpos; --_Wpos)
        for (_Ty _Wordval = _Array[_Wpos]; _Wordval != 0; _Wordval >>= 4)
            _Val += _Bitsperhex[_Wordval & 0xF];
    return (_Val);
    }

Может кто-нибудь объяснить мне, как это работает? что трюк с _Bitsperhex?

Ответ 1

_Bitsperhex содержит количество заданных битов в шестнадцатеричной цифре, индексированное цифрой.

digit: 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
value: 0    1    1    2    1    2    2    3    1    2    2    3    2    3    3    4
index: 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F

Функция получает одну цифру за раз от значения, с которым она работает, с помощью ANDing с 0xF (двоичный код 1111), просматривает количество заданных бит в этой цифре и суммирует их.

Ответ 2

_Bitsperhex - массив из 16 элементов, который отображает число в диапазоне [0..15] в число бит 1 в двоичном представлении этого числа. Например, _Bitsperhex[3] равно 2, который представляет собой число бит 1 в двоичном представлении 3.

Остальное легко: каждое многобитовое слово во внутреннем массиве _Array интерпретируется как последовательность 4-битных значений. Каждое 4-битное значение подается через вышеприведенную таблицу _Bitsperhex для подсчета бит.

Это немного другая реализация описанного здесь метода на основе таблицы поиска: http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetTable. По ссылке они используют таблицу из 256 элементов и разбивают 32-битные слова на четыре 8-битных значения.