/* Count Leading Zeroes */
static uint8_t clzlut[256] = {
8,7,6,6,5,5,5,5,
4,4,4,4,4,4,4,4,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
uint32_t clz(uint32_t val)
{
uint32_t accum = 0;
accum += clzlut[val >> 24];
accum += (accum == 8 ) ? clzlut[(val >> 16) & 0xFF] : 0;
accum += (accum == 16) ? clzlut[(val >> 8) & 0xFF] : 0;
accum += (accum == 24) ? clzlut[ val & 0xFF] : 0;
return accum;
}
Пояснение:
Это работает путем сохранения числа начальных нулей для каждой перестановки байта в качестве справочной таблицы. Вы используете значение байта, чтобы найти количество ведущих нулей для этого значения. Поскольку в примере это делается для целого без знака, вы сдвигаете и маскируете четыре отдельных байта и соответственно накапливаете результаты поиска. Тернарный оператор используется для остановки накопления, как только мы находим бит, который установлен. То, что накопленное значение равно 8, 16 или 24, означает, что пока не найдено ни одного установленного бита.
Кроме того, некоторые архитектуры имеют аппаратную поддержку для этого (как инструкция). Мнемоника сборки часто называется «CLZ» или «BSR». Они являются аббревиатурами для «Подсчета лидирующих нулей» и «Обратного сканирования битов» соответственно.