Упорядочение Мортона в 3D, используя в качестве входных данных unit64_t
Я пытаюсь использовать код Мортона для создания уникальной кодировки для заданного (x,y,z), где x, y, z - числа с плавающей запятой двойной точности. Я предполагаю, что могу использовать приведение типов, чтобы преобразовать числа с плавающей точкой в целые числа и выполнить упорядочение Мортона по этим целым числам. Например, рассмотрим следующее C++
код. (Я не знаю, как сделать то же самое в C
)
double x=-1.123456789123456E205;
int64_t i = reinterpret_cast<int64_t &>(x);
cout<<i<<endl;
output >>> i = -1548698869907112442
И то же самое для расширения x,y
, Как только у меня появятся "переосмысленные" значения, я бы хотел использовать их в качестве подпрограммы для кодирования Мортона.
Я проверил приведенное выше приведение типа, и он работал нормально в обратном порядке
double y = reinterpret_cast<double &>(i);
cout<<setprecision(16)<<y<<endl;
output>>-1.123456789123456e+205
Мне удалось найти некоторые коды для кодирования Мортона, даже некоторые из них на этом форуме, но ни один из них не использовал int64_t
в 3D. Поэтому мне понадобится помощь экспертов на форуме, как кодировать и декодировать int64_t
целые числа.
Мне удалось перепроектировать следующий код. К сожалению, есть некоторая ошибка, я не получаю правильные числа, когда я запускаю часть декодирования. Буду признателен за любую помощь, чтобы выяснить, что не так.
2D Morton-код кодирует / декодирует 64 бит.
#include <iostream>
#include <stdint.h>
#include<iomanip>
using namespace std;
uint64_t code_2D_M(double xd,double yd){
uint64_t x = reinterpret_cast<uint64_t& >(xd);
uint64_t y = reinterpret_cast<uint64_t& >(yd);
x = (x | (x << 16)) & 0x0000FFFF0000FFFF;
x = (x | (x << 8)) & 0x00FF00FF00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0F;
x = (x | (x << 2)) & 0x3333333333333333;
x = (x | (x << 1)) & 0x5555555555555555;
y = (y | (y << 16)) & 0x0000FFFF0000FFFF;
y = (y | (y << 8)) & 0x00FF00FF00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
y = (y | (y << 2)) & 0x3333333333333333;
y = (y | (y << 1)) & 0x5555555555555555;
return x | (y << 1);
}
uint64_t code_3D_M(double xd,double yd,double zd){
uint64_t x = reinterpret_cast<uint64_t& >(xd);
uint64_t y = reinterpret_cast<uint64_t& >(yd);
uint64_t z = reinterpret_cast<uint64_t& >(zd);
x = (x | (x << 16)) & 0x0000FFFF0000FFFF;
x = (x | (x << 8)) & 0x00FF00FF00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0F;
x = (x | (x << 2)) & 0x3333333333333333;
x = (x | (x << 1)) & 0x5555555555555555;
y = (y | (y << 16)) & 0x0000FFFF0000FFFF;
y = (y | (y << 8)) & 0x00FF00FF00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
y = (y | (y << 2)) & 0x3333333333333333;
y = (y | (y << 1)) & 0x5555555555555555;
z = (y | (y << 16)) & 0x0000FFFF0000FFFF;
z = (y | (y << 8)) & 0x00FF00FF00FF00FF;
z = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
z = (y | (y << 2)) & 0x3333333333333333;
z = (y | (y << 1)) & 0x5555555555555555;
return x | (y << 1) | (z << 2);
}
double decode_M(uint64_t x)
{
x = x & 0x5555555555555555;
x = (x | (x >> 1)) & 0x3333333333333333;
x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
x = (x | (x >> 4)) & 0x00FF00FF00FF00FF;
x = (x | (x >> 8)) & 0x0000FFFF0000FFFF;
x = (x | (x >> 16)) & 0xFFFFFFFFFFFFFFFF;
return reinterpret_cast<double& >(x);
}
int main (void){
uint64_t mort;
double x,y,z;
// test input
x=2.123456789123459E205;
y=1.789789123456129E205;
z=9.999999912345779E205;
// echo the input
cout<<setprecision(17)<<x<<endl;
cout<<setprecision(17)<<y<<endl;
cout<<setprecision(17)<<z<<endl;
// encode 2D case
mort = code_2D_M(x,y);
//decode and print the results to see if all was fine
cout<<setprecision(17)<<decode_M(mort>>0)<<endl;
cout<<setprecision(17)<<decode_M(mort>>1)<<endl;
// encode 3D case
mort = code_3D_M(x,y,z);
//decode and print the results to see if all was fine
cout<<setprecision(17)<<decode_M(mort>>0)<<endl;
cout<<setprecision(17)<<decode_M(mort>>1)<<endl;
cout<<setprecision(17)<<decode_M(mort>>2)<<endl;
return 0;
}
Я делаю это, потому что я хотел бы сохранить координаты не как трехмерную точку (x,y,z), а как одно длинное целое число и декодировать их при необходимости. Тем самым я уменьшу размер моего массива хранения координат в 3 раза.