Un'efficiente soluzione specifica di Microsoft (ad esempio Visual Studio 2017) in C / C ++ per l'input di numeri interi. Gestisce il caso dell'input che corrisponde esattamente a una potenza di due valori decrementando prima di controllare la posizione dell'1 bit più significativo.
inline unsigned int ExpandToPowerOf2(unsigned int Value)
{
unsigned long Index;
_BitScanReverse(&Index, Value - 1);
return (1U << (Index + 1));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#if defined(WIN64) // The _BitScanReverse64 intrinsic is only available for 64 bit builds because it depends on x64
inline unsigned long long ExpandToPowerOf2(unsigned long long Value)
{
unsigned long Index;
_BitScanReverse64(&Index, Value - 1);
return (1ULL << (Index + 1));
}
#endif
Questo genera circa 5 istruzioni incorporate per un processore Intel simile al seguente:
dec eax
bsr rcx, rax
inc ecx
mov eax, 1
shl rax, cl
Apparentemente il compilatore di Visual Studio C ++ non è codificato per ottimizzare ciò per i valori in fase di compilazione, ma non è che ci siano molte istruzioni lì.
Modificare:
Se si desidera che un valore di input pari a 1 dia 1 (2 alla potenza di zeroth), una piccola modifica al codice sopra genera comunque istruzioni dirette senza diramazione.
inline unsigned int ExpandToPowerOf2(unsigned int Value)
{
unsigned long Index;
_BitScanReverse(&Index, --Value);
if (Value == 0)
Index = (unsigned long) -1;
return (1U << (Index + 1));
}
Genera solo alcune altre istruzioni. Il trucco è che Index può essere sostituito da un test seguito da un'istruzione cmove.