В зависимости от того, сколько памяти у вас есть, вы можете выбрать подход из таблицы поиска.Например, если вы можете потратить 256 байтов, то следующая функция сделает это за один uint32_t
:
static const int table[256] = {
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,
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,
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,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 0, 0,
};
int func(uint32_t b, int i)
{
b = (b << (31-i));
if ((b & 0xFFFF0000) != 0xFFFF0000)
{
return ((b & 0xFF000000) != 0xFF000000)
? table[(b >> 24) & 0xFF] + 24 - (31-i)
: table[(b >> 16) & 0xFF] + 16 - (31-i);
}
else
{
return ((b & 0xFF00) != 0xFF00)
? table[(b >> 8) & 0xFF] + 8 - (31-i)
: table[(b >> 0) & 0xFF] + 0 - (31-i);
}
}
Я уверен, что это можно оптимизировать дальше.Например, безусловно, есть способы устранения дорогих условных веток;вы можете использовать тот факт, что булевы условия оцениваются как 1
или 0
, и использовать их в качестве мультипликатов.
Если у вас доступно 64 КБ, то вы делаете это для 16-битных блоков одновременнои так далее.Конечно, использование произвольного доступа на большом столе может привести к эффектам кэширования, поэтому вам нужно будет поэкспериментировать и составить профиль.