Очень хорошая общая реализация.
вопрос:Как удалить чередование битов (UnMortonizing?) имеет хороший ответ для извлечения одной из двух половин числа Мортона (только нечетные биты), но мне нужно решение, которое извлекает обе части (нечетные биты и четные биты) за как можно меньшее количество операций.
Для моего использования мне нужно было бы взять 32-битное целое число и извлечь две 16-битные целые, где один - четные биты, а другой - нечетные биты, сдвинутые вправо на 1 бит, например
input, z: 11101101 01010111 11011011 01101110
output, x: 11100001 10110111 // odd bits shifted right by 1
y: 10111111 11011010 // even bits
Кажется, существует множество решений, использующих сдвиги и маски с магическими числами для генерации чисел Мортона (то есть чередования битов), напримерЧередование битов по двоичным магическим числам, но я еще не нашел ничего для того, чтобы сделать обратное (то есть деинтерлейсинг).
ОБНОВИТЬ
Перечитав раздел «Восхищение Хакера», посвященный идеальным перемешкам / растасовкам, я нашел несколько полезных примеров, которые я адаптировал следующим образом:
// morton1 - extract even bits
uint32_t morton1(uint32_t x)
{
x = x & 0x55555555;
x = (x | (x >> 1)) & 0x33333333;
x = (x | (x >> 2)) & 0x0F0F0F0F;
x = (x | (x >> 4)) & 0x00FF00FF;
x = (x | (x >> 8)) & 0x0000FFFF;
return x;
}
// morton2 - extract odd and even bits
void morton2(uint32_t *x, uint32_t *y, uint32_t z)
{
*x = morton1(z);
*y = morton1(z >> 1);
}
Я думаю, что это все еще можно улучшить, как в его нынешней скалярной форме, так и за счет использования SIMD, поэтому я все еще заинтересован в лучших решениях (либо скалярных, либо SIMD).