Здесь есть слишком сложные ответы. Технику Debruin следует использовать только тогда, когда вход уже является степенью двойки, иначе есть способ лучше. При мощности двух входов Debruin является самым быстрым, даже быстрее, чем _BitScanReverse
на любом процессоре, который я тестировал. Однако в общем случае _BitScanReverse
(или независимо от того, что внутреннее свойство вызывается в вашем компиляторе) является самым быстрым (хотя на некоторых процессорах он может быть микрокодирован).
Если внутренняя функция не подходит, вот оптимальное программное решение для обработки общих входных данных.
u8 inline log2 (u32 val) {
u8 k = 0;
if (val > 0x0000FFFFu) { val >>= 16; k = 16; }
if (val > 0x000000FFu) { val >>= 8; k |= 8; }
if (val > 0x0000000Fu) { val >>= 4; k |= 4; }
if (val > 0x00000003u) { val >>= 2; k |= 2; }
k |= (val & 2) >> 1;
return k;
}
Обратите внимание, что эта версия не требует поиска Debruin в конце, в отличие от большинства других ответов. Он вычисляет положение на месте.
Таблицы могут быть предпочтительнее, однако, если вы вызываете его несколько раз, риск промаха кеша будет затмевается ускорением таблицы.
u8 kTableLog2[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
u8 log2_table(u32 val) {
u8 k = 0;
if (val > 0x0000FFFFuL) { val >>= 16; k = 16; }
if (val > 0x000000FFuL) { val >>= 8; k |= 8; }
k |= kTableLog2[val]; // precompute the Log2 of the low byte
return k;
}
Это должно обеспечить наивысшую пропускную способность из всех приведенных здесь программных ответов, но если вы вызываете его только изредка, предпочтите решение без таблиц, такое как мой первый фрагмент.