Quelques réponses trop complexes ici. La technique Debruin ne doit être utilisée que lorsque l'entrée est déjà une puissance de deux, sinon il existe un meilleur moyen. Pour une puissance de 2 entrées, Debruin est le plus rapide absolu, encore plus rapide que _BitScanReverse
sur n'importe quel processeur que j'ai testé. Cependant, dans le cas général, _BitScanReverse
(ou quel que soit le nom intrinsèque de votre compilateur) est le plus rapide (sur certains processeurs, il peut cependant être microcodé).
Si la fonction intrinsèque n'est pas une option, voici une solution logicielle optimale pour le traitement des entrées générales.
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;
}
Notez que cette version ne nécessite pas de recherche Debruin à la fin, contrairement à la plupart des autres réponses. Il calcule la position en place.
Les tables peuvent être préférables cependant, si vous les appelez à plusieurs reprises, le risque de manque de cache est éclipsé par l'accélération d'une table.
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;
}
Cela devrait produire le débit le plus élevé de toutes les réponses logicielles données ici, mais si vous ne l'appelez qu'occasionnellement, préférez une solution sans table comme mon premier extrait de code.