25#ifndef __BITPIT_PABLO_MORTON_HPP__
26#define __BITPIT_PABLO_MORTON_HPP__
37const uint64_t INVALID_MORTON = std::numeric_limits<uint64_t>::max();
61inline int8_t computeMaximumLevel(uint8_t dimension)
68 int8_t level = (8 *
sizeof(uint64_t)) / dimension;
71 level = std::min(
static_cast<int8_t
>((8 *
sizeof(uint32_t)) - 1), level);
74 level = std::min(
static_cast<int8_t
>((8 *
sizeof(uint64_t)) / dimension - 1), level);
87inline uint64_t splitBy3(uint32_t a)
89 uint64_t x = a & 0x1fffff;
90 x = (x | x << 32) & 0x001F00000000FFFF;
91 x = (x | x << 16) & 0x001F0000FF0000FF;
92 x = (x | x << 8) & 0x100F00F00F00F00F;
93 x = (x | x << 4) & 0x10C30C30C30C30C3;
94 x = (x | x << 2) & 0x1249249249249249;
107inline uint64_t splitBy2(uint32_t a)
110 x = (x | x << 32) & 0x00000000FFFFFFFF;
111 x = (x | x << 16) & 0x0000FFFF0000FFFF;
112 x = (x | x << 8) & 0x00FF00FF00FF00FF;
113 x = (x | x << 4) & 0x0F0F0F0F0F0F0F0F;
114 x = (x | x << 2) & 0x3333333333333333;
115 x = (x | x << 1) & 0x5555555555555555;
128inline uint32_t getThirdBits(uint64_t morton)
130 uint64_t x = morton & 0x1249249249249249;
131 x = (x ^ (x >> 2)) & 0x10C30C30C30C30C3;
132 x = (x ^ (x >> 4)) & 0x100F00F00F00F00F;
133 x = (x ^ (x >> 8)) & 0x001F0000FF0000FF;
134 x = (x ^ (x >> 16)) & 0x001F00000000FFFF;
135 x = (x ^ (x >> 32)) & 0x00000000001FFFFF;
137 return static_cast<uint32_t
>(x);
148inline uint32_t getSecondBits(uint64_t morton)
150 uint64_t x = morton & 0x5555555555555555;
151 x = (x ^ (x >> 1)) & 0x3333333333333333;
152 x = (x ^ (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
153 x = (x ^ (x >> 4)) & 0x00FF00FF00FF00FF;
154 x = (x ^ (x >> 8)) & 0x0000FFFF0000FFFF;
155 x = (x ^ (x >> 16)) & 0x00000000FFFFFFFF;
157 return static_cast<uint32_t
>(x);
171inline uint64_t computeMorton3D(uint32_t x, uint32_t y, uint32_t z)
173 uint64_t morton = splitBy3(x) | (splitBy3(y) << 1) | (splitBy3(z) << 2);
188inline uint64_t computeMorton2D(uint32_t x, uint32_t y)
190 uint64_t morton = splitBy2(x) | (splitBy2(y) << 1);
207inline uint64_t computeMorton(uint8_t dimension, uint32_t x, uint32_t y, uint32_t z)
209 if (dimension == 3) {
210 return computeMorton3D(x, y, z);
211 }
else if (dimension == 2) {
212 return computeMorton2D(x, y);
214 throw std::runtime_error(
"Requested dimension is not supported");
228inline uint32_t computeCoordinate3D(uint64_t morton,
int coord)
230 return getThirdBits(morton >> coord);
243inline uint32_t computeCoordinate2D(uint64_t morton,
int coord)
246 return getSecondBits(morton >> coord);
263inline uint32_t computeCoordinate(uint8_t dimension, uint64_t morton,
int coord)
265 if (dimension == 3) {
266 return computeCoordinate3D(morton, coord);
267 }
else if (dimension == 2) {
268 return computeCoordinate2D(morton, coord);
270 throw std::runtime_error(
"Requested dimension is not supported");
286inline uint64_t computeXYZKey3D(uint32_t x, uint32_t y, uint32_t z)
288 static const int SHIFT = (8 *
sizeof(uint64_t)) / 3;
290 uint64_t key = x | (
static_cast<uint_fast64_t
>(y) << SHIFT) | (
static_cast<uint_fast64_t
>(z) << (2 * SHIFT));
306inline uint64_t computeXYZKey2D(uint32_t x, uint32_t y)
308 static const int SHIFT = (8 *
sizeof(uint64_t)) / 2;
310 uint64_t key = x | (
static_cast<uint_fast64_t
>(y) << SHIFT);
328inline uint64_t computeXYZKey(uint8_t dimension, uint32_t x, uint32_t y, uint32_t z)
330 if (dimension == 3) {
331 return computeXYZKey3D(x, y, z);
332 }
else if (dimension == 2) {
333 return computeXYZKey2D(x, y);
335 throw std::runtime_error(
"Requested dimension is not supported");