diff --git a/README.md b/README.md index 7cc7837..9090ddd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Libmorton v0.2.12 -[![CMake](https://github.com/Forceflow/libmorton/actions/workflows/cmake.yml/badge.svg)](https://github.com/Forceflow/libmorton/actions/workflows/cmake.yml) [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://opensource.org/licenses/MIT) +[![CMake](https://github.com/Forceflow/libmorton/actions/workflows/cmake.yml/badge.svg)](https://github.com/Forceflow/libmorton/actions/workflows/cmake.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) * Libmorton is a **C++ header-only library** with methods to efficiently encode/decode 64, 32 and 16-bit Morton codes and coordinates, in 2D and 3D. *Morton order* is also known as *Z-order* or *[the Z-order curve](https://en.wikipedia.org/wiki/Z-order_curve)*. * Libmorton is a **lightweight and portable** library - the only dependencies are standard C++ headers. Architecture-specific optimizations are available. diff --git a/include/libmorton/morton2D.h b/include/libmorton/morton2D.h index 6631c1c..0c38715 100644 --- a/include/libmorton/morton2D.h +++ b/include/libmorton/morton2D.h @@ -38,8 +38,21 @@ namespace libmorton { unsigned int shift = (i - 1) * 8; answer = answer << 16 | - Morton2D_encode_y_256[(y >> shift) & EIGHTBITMASK] | - Morton2D_encode_x_256[(x >> shift) & EIGHTBITMASK]; + Morton2D_encode_y_256_32[(y >> shift) & EIGHTBITMASK] | + Morton2D_encode_x_256_32[(x >> shift) & EIGHTBITMASK]; + } + return answer; + } + + template::value>> + inline morton m2D_e_sLUT(const coord x, const coord y) { + morton answer = 0; + for (unsigned int i = sizeof(coord); i > 0; --i) { + unsigned int shift = (i - 1) * 8; + answer = + answer << 16 | + Morton2D_encode_y_256_64[(y >> shift) & EIGHTBITMASK] | + Morton2D_encode_x_256_64[(x >> shift) & EIGHTBITMASK]; } return answer; } @@ -52,22 +65,36 @@ namespace libmorton { unsigned int shift = (i - 1) * 8; answer = answer << 16 | - (Morton2D_encode_x_256[(y >> shift) & EIGHTBITMASK] << morton(1)) | - (Morton2D_encode_x_256[(x >> shift) & EIGHTBITMASK]); + (Morton2D_encode_x_256_32[(y >> shift) & EIGHTBITMASK] << morton(1)) | + (Morton2D_encode_x_256_32[(x >> shift) & EIGHTBITMASK]); + } + return answer; + } + + template::value>> + inline morton m2D_e_LUT(const coord x, const coord y) { + morton answer = 0; + for (unsigned int i = sizeof(coord); i > 0; --i) { + unsigned int shift = (i - 1) * 8; + answer = + answer << 16 | + (Morton2D_encode_x_256_64[(y >> shift) & EIGHTBITMASK] << morton(1)) | + (Morton2D_encode_x_256_64[(x >> shift) & EIGHTBITMASK]); } return answer; } // HELPER METHOD for Early Termination LUT Encode - template - inline morton compute2D_ET_LUT_encode(const coord c, const coord *LUT) { + template + inline morton compute2D_ET_LUT_encode(const coord c, const lutT *LUT) { unsigned long maxbit = 0; if (findFirstSetBit(c, &maxbit) == 0) { return 0; } + // highest byte index containing any set bit + int highest_byte = static_cast((maxbit + 1) / 8); morton answer = 0; - unsigned int i = 0; - while (maxbit >= i) { - answer |= ((morton)LUT[(c >> i) & EIGHTBITMASK]) << i * 2; - i += 8; + for (int i = highest_byte; i >= 0; --i) { + unsigned int shift = i * 8; + answer = (answer << 16) | static_cast(LUT[(c >> shift) & EIGHTBITMASK]); } return answer; } @@ -77,16 +104,34 @@ namespace libmorton { // Figuring this out is probably too costly in most cases. template inline morton m2D_e_sLUT_ET(const coord x, const coord y) { - morton answer_x = compute2D_ET_LUT_encode(x, Morton2D_encode_x_256); - morton answer_y = compute2D_ET_LUT_encode(y, Morton2D_encode_y_256); + morton answer_x = compute2D_ET_LUT_encode(x, Morton2D_encode_x_256_32); + morton answer_y = compute2D_ET_LUT_encode(y, Morton2D_encode_y_256_32); + return answer_y | answer_x; + } + + template::value>> + inline morton m2D_e_sLUT_ET(const coord x, const coord y) { + morton answer_x = compute2D_ET_LUT_encode(x, Morton2D_encode_x_256_64); + morton answer_y = compute2D_ET_LUT_encode(y, Morton2D_encode_y_256_64); return answer_y | answer_x; } // ENCODE 2D Morton code : LUT (Early termination version) template inline morton m2D_e_LUT_ET(const coord x, const coord y) { - morton answer_x = compute2D_ET_LUT_encode(x, Morton2D_encode_x_256); - morton answer_y = compute2D_ET_LUT_encode(y, Morton2D_encode_x_256); + morton answer_x = compute2D_ET_LUT_encode(x, Morton2D_encode_x_256_32); + // This is because `Morton2D_encode_(y|z)_256_*` is basically just `Morton3D_encode_x_256_*` with some pre-shifting. + // And we don't want any pre-shifting in this case. + morton answer_y = compute2D_ET_LUT_encode(y, Morton2D_encode_x_256_32); + return (answer_y << 1) | answer_x; + } + + template::value>> + inline morton m2D_e_LUT_ET(const coord x, const coord y) { + morton answer_x = compute2D_ET_LUT_encode(x, Morton2D_encode_x_256_64); + // This is because `Morton2D_encode_(y|z)_256_*` is basically just `Morton3D_encode_x_256_*` with some pre-shifting. + // And we don't want any pre-shifting in this case. + morton answer_y = compute2D_ET_LUT_encode(y, Morton2D_encode_x_256_64); return (answer_y << 1) | answer_x; } @@ -176,15 +221,15 @@ namespace libmorton { // DECODE 2D Morton code : Shifted LUT template inline void m2D_d_sLUT(const morton m, coord& x, coord& y) { - x = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_x_256, 0); - y = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_y_256, 0); + x = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_preshifted_x_256, 0); + y = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_preshifted_y_256, 0); } // DECODE 2D 64-bit morton code : LUT template inline void m2D_d_LUT(const morton m, coord& x, coord& y) { x = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_x_256, 0); - y = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_x_256, 1); + y = morton2D_DecodeCoord_LUT256(m, Morton2D_decode_y_256, 1); } // DECODE 2D Morton code : Shifted LUT (early termination) @@ -197,8 +242,8 @@ namespace libmorton { unsigned int shiftback = 0; while (firstbit_location > i) { morton m_shifted = (m >> i) & EIGHTBITMASK; - x |= (coord)Morton2D_decode_x_256[m_shifted] << shiftback; - y |= (coord)Morton2D_decode_y_256[m_shifted] << shiftback; + x |= (coord)Morton2D_decode_preshifted_x_256[m_shifted] << shiftback; + y |= (coord)Morton2D_decode_preshifted_y_256[m_shifted] << shiftback; shiftback += 4; i += 8; } @@ -214,7 +259,7 @@ namespace libmorton { unsigned int shiftback = 0; while (firstbit_location > i) { x |= (coord)Morton2D_decode_x_256[(m >> i) & EIGHTBITMASK] << shiftback; - y |= (coord)Morton2D_decode_x_256[(m >> (i + 1)) & EIGHTBITMASK] << shiftback; + y |= (coord)Morton2D_decode_y_256[(m >> (i + 1)) & EIGHTBITMASK] << shiftback; shiftback += 4; i += 8; } @@ -257,7 +302,7 @@ namespace libmorton { inline void m2D_d_for(const morton m, coord& x, coord& y) { x = 0; y = 0; unsigned int checkbits = sizeof(morton) * 4; - for (unsigned int i = 0; i <= checkbits; ++i) { + for (unsigned int i = 0; i < checkbits; ++i) { morton selector = 1; unsigned int shift_selector = 2 * i; x |= (m & (selector << shift_selector)) >> i; @@ -271,7 +316,7 @@ namespace libmorton { x = 0; y = 0; unsigned long firstbit_location = 0; if (!findFirstSetBit(m, &firstbit_location)) return; - float defaultbits = sizeof(morton) * 4; + float defaultbits = (sizeof(morton) * 8) / 2; unsigned int checkbits = static_cast(std::min(defaultbits, firstbit_location / 2.0f)); for (unsigned int i = 0; i <= checkbits; ++i) { morton selector = 1; diff --git a/include/libmorton/morton2D_LUTs.h b/include/libmorton/morton2D_LUTs.h index 730eb02..4512369 100644 --- a/include/libmorton/morton2D_LUTs.h +++ b/include/libmorton/morton2D_LUTs.h @@ -2,119 +2,234 @@ #include -namespace libmorton { - - // LUT for Morton2D encode X - static const uint_fast16_t Morton2D_encode_x_256[256] = - { - 0, 1, 4, 5, 16, 17, 20, 21, - 64, 65, 68, 69, 80, 81, 84, 85, - 256, 257, 260, 261, 272, 273, 276, 277, - 320, 321, 324, 325, 336, 337, 340, 341, - 1024, 1025, 1028, 1029, 1040, 1041, 1044, 1045, - 1088, 1089, 1092, 1093, 1104, 1105, 1108, 1109, - 1280, 1281, 1284, 1285, 1296, 1297, 1300, 1301, - 1344, 1345, 1348, 1349, 1360, 1361, 1364, 1365, - 4096, 4097, 4100, 4101, 4112, 4113, 4116, 4117, - 4160, 4161, 4164, 4165, 4176, 4177, 4180, 4181, - 4352, 4353, 4356, 4357, 4368, 4369, 4372, 4373, - 4416, 4417, 4420, 4421, 4432, 4433, 4436, 4437, - 5120, 5121, 5124, 5125, 5136, 5137, 5140, 5141, - 5184, 5185, 5188, 5189, 5200, 5201, 5204, 5205, - 5376, 5377, 5380, 5381, 5392, 5393, 5396, 5397, - 5440, 5441, 5444, 5445, 5456, 5457, 5460, 5461, - 16384, 16385, 16388, 16389, 16400, 16401, 16404, 16405, - 16448, 16449, 16452, 16453, 16464, 16465, 16468, 16469, - 16640, 16641, 16644, 16645, 16656, 16657, 16660, 16661, - 16704, 16705, 16708, 16709, 16720, 16721, 16724, 16725, - 17408, 17409, 17412, 17413, 17424, 17425, 17428, 17429, - 17472, 17473, 17476, 17477, 17488, 17489, 17492, 17493, - 17664, 17665, 17668, 17669, 17680, 17681, 17684, 17685, - 17728, 17729, 17732, 17733, 17744, 17745, 17748, 17749, - 20480, 20481, 20484, 20485, 20496, 20497, 20500, 20501, - 20544, 20545, 20548, 20549, 20560, 20561, 20564, 20565, - 20736, 20737, 20740, 20741, 20752, 20753, 20756, 20757, - 20800, 20801, 20804, 20805, 20816, 20817, 20820, 20821, - 21504, 21505, 21508, 21509, 21520, 21521, 21524, 21525, - 21568, 21569, 21572, 21573, 21584, 21585, 21588, 21589, - 21760, 21761, 21764, 21765, 21776, 21777, 21780, 21781, - 21824, 21825, 21828, 21829, 21840, 21841, 21844, 21845 +namespace libmorton +{ + // preshifted 2D Encode LUTs (32-bit) + static const uint_fast32_t Morton2D_encode_x_256_32[256] = { + 0x00000000, 0x00000001, 0x00000004, 0x00000005, 0x00000010, 0x00000011, 0x00000014, 0x00000015, + 0x00000040, 0x00000041, 0x00000044, 0x00000045, 0x00000050, 0x00000051, 0x00000054, 0x00000055, + 0x00000100, 0x00000101, 0x00000104, 0x00000105, 0x00000110, 0x00000111, 0x00000114, 0x00000115, + 0x00000140, 0x00000141, 0x00000144, 0x00000145, 0x00000150, 0x00000151, 0x00000154, 0x00000155, + 0x00000400, 0x00000401, 0x00000404, 0x00000405, 0x00000410, 0x00000411, 0x00000414, 0x00000415, + 0x00000440, 0x00000441, 0x00000444, 0x00000445, 0x00000450, 0x00000451, 0x00000454, 0x00000455, + 0x00000500, 0x00000501, 0x00000504, 0x00000505, 0x00000510, 0x00000511, 0x00000514, 0x00000515, + 0x00000540, 0x00000541, 0x00000544, 0x00000545, 0x00000550, 0x00000551, 0x00000554, 0x00000555, + 0x00001000, 0x00001001, 0x00001004, 0x00001005, 0x00001010, 0x00001011, 0x00001014, 0x00001015, + 0x00001040, 0x00001041, 0x00001044, 0x00001045, 0x00001050, 0x00001051, 0x00001054, 0x00001055, + 0x00001100, 0x00001101, 0x00001104, 0x00001105, 0x00001110, 0x00001111, 0x00001114, 0x00001115, + 0x00001140, 0x00001141, 0x00001144, 0x00001145, 0x00001150, 0x00001151, 0x00001154, 0x00001155, + 0x00001400, 0x00001401, 0x00001404, 0x00001405, 0x00001410, 0x00001411, 0x00001414, 0x00001415, + 0x00001440, 0x00001441, 0x00001444, 0x00001445, 0x00001450, 0x00001451, 0x00001454, 0x00001455, + 0x00001500, 0x00001501, 0x00001504, 0x00001505, 0x00001510, 0x00001511, 0x00001514, 0x00001515, + 0x00001540, 0x00001541, 0x00001544, 0x00001545, 0x00001550, 0x00001551, 0x00001554, 0x00001555, + 0x00004000, 0x00004001, 0x00004004, 0x00004005, 0x00004010, 0x00004011, 0x00004014, 0x00004015, + 0x00004040, 0x00004041, 0x00004044, 0x00004045, 0x00004050, 0x00004051, 0x00004054, 0x00004055, + 0x00004100, 0x00004101, 0x00004104, 0x00004105, 0x00004110, 0x00004111, 0x00004114, 0x00004115, + 0x00004140, 0x00004141, 0x00004144, 0x00004145, 0x00004150, 0x00004151, 0x00004154, 0x00004155, + 0x00004400, 0x00004401, 0x00004404, 0x00004405, 0x00004410, 0x00004411, 0x00004414, 0x00004415, + 0x00004440, 0x00004441, 0x00004444, 0x00004445, 0x00004450, 0x00004451, 0x00004454, 0x00004455, + 0x00004500, 0x00004501, 0x00004504, 0x00004505, 0x00004510, 0x00004511, 0x00004514, 0x00004515, + 0x00004540, 0x00004541, 0x00004544, 0x00004545, 0x00004550, 0x00004551, 0x00004554, 0x00004555, + 0x00005000, 0x00005001, 0x00005004, 0x00005005, 0x00005010, 0x00005011, 0x00005014, 0x00005015, + 0x00005040, 0x00005041, 0x00005044, 0x00005045, 0x00005050, 0x00005051, 0x00005054, 0x00005055, + 0x00005100, 0x00005101, 0x00005104, 0x00005105, 0x00005110, 0x00005111, 0x00005114, 0x00005115, + 0x00005140, 0x00005141, 0x00005144, 0x00005145, 0x00005150, 0x00005151, 0x00005154, 0x00005155, + 0x00005400, 0x00005401, 0x00005404, 0x00005405, 0x00005410, 0x00005411, 0x00005414, 0x00005415, + 0x00005440, 0x00005441, 0x00005444, 0x00005445, 0x00005450, 0x00005451, 0x00005454, 0x00005455, + 0x00005500, 0x00005501, 0x00005504, 0x00005505, 0x00005510, 0x00005511, 0x00005514, 0x00005515, + 0x00005540, 0x00005541, 0x00005544, 0x00005545, 0x00005550, 0x00005551, 0x00005554, 0x00005555 + }; - // LUT for Morton2D encode Y - static const uint_fast16_t Morton2D_encode_y_256[256] = - { - 0, 2, 8, 10, 32, 34, 40, 42, - 128, 130, 136, 138, 160, 162, 168, 170, - 512, 514, 520, 522, 544, 546, 552, 554, - 640, 642, 648, 650, 672, 674, 680, 682, - 2048, 2050, 2056, 2058, 2080, 2082, 2088, 2090, - 2176, 2178, 2184, 2186, 2208, 2210, 2216, 2218, - 2560, 2562, 2568, 2570, 2592, 2594, 2600, 2602, - 2688, 2690, 2696, 2698, 2720, 2722, 2728, 2730, - 8192, 8194, 8200, 8202, 8224, 8226, 8232, 8234, - 8320, 8322, 8328, 8330, 8352, 8354, 8360, 8362, - 8704, 8706, 8712, 8714, 8736, 8738, 8744, 8746, - 8832, 8834, 8840, 8842, 8864, 8866, 8872, 8874, - 10240, 10242, 10248, 10250, 10272, 10274, 10280, 10282, - 10368, 10370, 10376, 10378, 10400, 10402, 10408, 10410, - 10752, 10754, 10760, 10762, 10784, 10786, 10792, 10794, - 10880, 10882, 10888, 10890, 10912, 10914, 10920, 10922, - 32768, 32770, 32776, 32778, 32800, 32802, 32808, 32810, - 32896, 32898, 32904, 32906, 32928, 32930, 32936, 32938, - 33280, 33282, 33288, 33290, 33312, 33314, 33320, 33322, - 33408, 33410, 33416, 33418, 33440, 33442, 33448, 33450, - 34816, 34818, 34824, 34826, 34848, 34850, 34856, 34858, - 34944, 34946, 34952, 34954, 34976, 34978, 34984, 34986, - 35328, 35330, 35336, 35338, 35360, 35362, 35368, 35370, - 35456, 35458, 35464, 35466, 35488, 35490, 35496, 35498, - 40960, 40962, 40968, 40970, 40992, 40994, 41000, 41002, - 41088, 41090, 41096, 41098, 41120, 41122, 41128, 41130, - 41472, 41474, 41480, 41482, 41504, 41506, 41512, 41514, - 41600, 41602, 41608, 41610, 41632, 41634, 41640, 41642, - 43008, 43010, 43016, 43018, 43040, 43042, 43048, 43050, - 43136, 43138, 43144, 43146, 43168, 43170, 43176, 43178, - 43520, 43522, 43528, 43530, 43552, 43554, 43560, 43562, - 43648, 43650, 43656, 43658, 43680, 43682, 43688, 43690 + static const uint_fast32_t Morton2D_encode_y_256_32[256] = { + 0x00000000, 0x00000002, 0x00000008, 0x0000000a, 0x00000020, 0x00000022, 0x00000028, 0x0000002a, + 0x00000080, 0x00000082, 0x00000088, 0x0000008a, 0x000000a0, 0x000000a2, 0x000000a8, 0x000000aa, + 0x00000200, 0x00000202, 0x00000208, 0x0000020a, 0x00000220, 0x00000222, 0x00000228, 0x0000022a, + 0x00000280, 0x00000282, 0x00000288, 0x0000028a, 0x000002a0, 0x000002a2, 0x000002a8, 0x000002aa, + 0x00000800, 0x00000802, 0x00000808, 0x0000080a, 0x00000820, 0x00000822, 0x00000828, 0x0000082a, + 0x00000880, 0x00000882, 0x00000888, 0x0000088a, 0x000008a0, 0x000008a2, 0x000008a8, 0x000008aa, + 0x00000a00, 0x00000a02, 0x00000a08, 0x00000a0a, 0x00000a20, 0x00000a22, 0x00000a28, 0x00000a2a, + 0x00000a80, 0x00000a82, 0x00000a88, 0x00000a8a, 0x00000aa0, 0x00000aa2, 0x00000aa8, 0x00000aaa, + 0x00002000, 0x00002002, 0x00002008, 0x0000200a, 0x00002020, 0x00002022, 0x00002028, 0x0000202a, + 0x00002080, 0x00002082, 0x00002088, 0x0000208a, 0x000020a0, 0x000020a2, 0x000020a8, 0x000020aa, + 0x00002200, 0x00002202, 0x00002208, 0x0000220a, 0x00002220, 0x00002222, 0x00002228, 0x0000222a, + 0x00002280, 0x00002282, 0x00002288, 0x0000228a, 0x000022a0, 0x000022a2, 0x000022a8, 0x000022aa, + 0x00002800, 0x00002802, 0x00002808, 0x0000280a, 0x00002820, 0x00002822, 0x00002828, 0x0000282a, + 0x00002880, 0x00002882, 0x00002888, 0x0000288a, 0x000028a0, 0x000028a2, 0x000028a8, 0x000028aa, + 0x00002a00, 0x00002a02, 0x00002a08, 0x00002a0a, 0x00002a20, 0x00002a22, 0x00002a28, 0x00002a2a, + 0x00002a80, 0x00002a82, 0x00002a88, 0x00002a8a, 0x00002aa0, 0x00002aa2, 0x00002aa8, 0x00002aaa, + 0x00008000, 0x00008002, 0x00008008, 0x0000800a, 0x00008020, 0x00008022, 0x00008028, 0x0000802a, + 0x00008080, 0x00008082, 0x00008088, 0x0000808a, 0x000080a0, 0x000080a2, 0x000080a8, 0x000080aa, + 0x00008200, 0x00008202, 0x00008208, 0x0000820a, 0x00008220, 0x00008222, 0x00008228, 0x0000822a, + 0x00008280, 0x00008282, 0x00008288, 0x0000828a, 0x000082a0, 0x000082a2, 0x000082a8, 0x000082aa, + 0x00008800, 0x00008802, 0x00008808, 0x0000880a, 0x00008820, 0x00008822, 0x00008828, 0x0000882a, + 0x00008880, 0x00008882, 0x00008888, 0x0000888a, 0x000088a0, 0x000088a2, 0x000088a8, 0x000088aa, + 0x00008a00, 0x00008a02, 0x00008a08, 0x00008a0a, 0x00008a20, 0x00008a22, 0x00008a28, 0x00008a2a, + 0x00008a80, 0x00008a82, 0x00008a88, 0x00008a8a, 0x00008aa0, 0x00008aa2, 0x00008aa8, 0x00008aaa, + 0x0000a000, 0x0000a002, 0x0000a008, 0x0000a00a, 0x0000a020, 0x0000a022, 0x0000a028, 0x0000a02a, + 0x0000a080, 0x0000a082, 0x0000a088, 0x0000a08a, 0x0000a0a0, 0x0000a0a2, 0x0000a0a8, 0x0000a0aa, + 0x0000a200, 0x0000a202, 0x0000a208, 0x0000a20a, 0x0000a220, 0x0000a222, 0x0000a228, 0x0000a22a, + 0x0000a280, 0x0000a282, 0x0000a288, 0x0000a28a, 0x0000a2a0, 0x0000a2a2, 0x0000a2a8, 0x0000a2aa, + 0x0000a800, 0x0000a802, 0x0000a808, 0x0000a80a, 0x0000a820, 0x0000a822, 0x0000a828, 0x0000a82a, + 0x0000a880, 0x0000a882, 0x0000a888, 0x0000a88a, 0x0000a8a0, 0x0000a8a2, 0x0000a8a8, 0x0000a8aa, + 0x0000aa00, 0x0000aa02, 0x0000aa08, 0x0000aa0a, 0x0000aa20, 0x0000aa22, 0x0000aa28, 0x0000aa2a, + 0x0000aa80, 0x0000aa82, 0x0000aa88, 0x0000aa8a, 0x0000aaa0, 0x0000aaa2, 0x0000aaa8, 0x0000aaaa + + }; + + // preshifted 2D Encode LUTs (64-bit) + static const uint_fast64_t Morton2D_encode_x_256_64[256] = { + 0x0000000000000000, 0x0000000000000001, 0x0000000000000004, 0x0000000000000005, 0x0000000000000010, 0x0000000000000011, 0x0000000000000014, 0x0000000000000015, + 0x0000000000000040, 0x0000000000000041, 0x0000000000000044, 0x0000000000000045, 0x0000000000000050, 0x0000000000000051, 0x0000000000000054, 0x0000000000000055, + 0x0000000000000100, 0x0000000000000101, 0x0000000000000104, 0x0000000000000105, 0x0000000000000110, 0x0000000000000111, 0x0000000000000114, 0x0000000000000115, + 0x0000000000000140, 0x0000000000000141, 0x0000000000000144, 0x0000000000000145, 0x0000000000000150, 0x0000000000000151, 0x0000000000000154, 0x0000000000000155, + 0x0000000000000400, 0x0000000000000401, 0x0000000000000404, 0x0000000000000405, 0x0000000000000410, 0x0000000000000411, 0x0000000000000414, 0x0000000000000415, + 0x0000000000000440, 0x0000000000000441, 0x0000000000000444, 0x0000000000000445, 0x0000000000000450, 0x0000000000000451, 0x0000000000000454, 0x0000000000000455, + 0x0000000000000500, 0x0000000000000501, 0x0000000000000504, 0x0000000000000505, 0x0000000000000510, 0x0000000000000511, 0x0000000000000514, 0x0000000000000515, + 0x0000000000000540, 0x0000000000000541, 0x0000000000000544, 0x0000000000000545, 0x0000000000000550, 0x0000000000000551, 0x0000000000000554, 0x0000000000000555, + 0x0000000000001000, 0x0000000000001001, 0x0000000000001004, 0x0000000000001005, 0x0000000000001010, 0x0000000000001011, 0x0000000000001014, 0x0000000000001015, + 0x0000000000001040, 0x0000000000001041, 0x0000000000001044, 0x0000000000001045, 0x0000000000001050, 0x0000000000001051, 0x0000000000001054, 0x0000000000001055, + 0x0000000000001100, 0x0000000000001101, 0x0000000000001104, 0x0000000000001105, 0x0000000000001110, 0x0000000000001111, 0x0000000000001114, 0x0000000000001115, + 0x0000000000001140, 0x0000000000001141, 0x0000000000001144, 0x0000000000001145, 0x0000000000001150, 0x0000000000001151, 0x0000000000001154, 0x0000000000001155, + 0x0000000000001400, 0x0000000000001401, 0x0000000000001404, 0x0000000000001405, 0x0000000000001410, 0x0000000000001411, 0x0000000000001414, 0x0000000000001415, + 0x0000000000001440, 0x0000000000001441, 0x0000000000001444, 0x0000000000001445, 0x0000000000001450, 0x0000000000001451, 0x0000000000001454, 0x0000000000001455, + 0x0000000000001500, 0x0000000000001501, 0x0000000000001504, 0x0000000000001505, 0x0000000000001510, 0x0000000000001511, 0x0000000000001514, 0x0000000000001515, + 0x0000000000001540, 0x0000000000001541, 0x0000000000001544, 0x0000000000001545, 0x0000000000001550, 0x0000000000001551, 0x0000000000001554, 0x0000000000001555, + 0x0000000000004000, 0x0000000000004001, 0x0000000000004004, 0x0000000000004005, 0x0000000000004010, 0x0000000000004011, 0x0000000000004014, 0x0000000000004015, + 0x0000000000004040, 0x0000000000004041, 0x0000000000004044, 0x0000000000004045, 0x0000000000004050, 0x0000000000004051, 0x0000000000004054, 0x0000000000004055, + 0x0000000000004100, 0x0000000000004101, 0x0000000000004104, 0x0000000000004105, 0x0000000000004110, 0x0000000000004111, 0x0000000000004114, 0x0000000000004115, + 0x0000000000004140, 0x0000000000004141, 0x0000000000004144, 0x0000000000004145, 0x0000000000004150, 0x0000000000004151, 0x0000000000004154, 0x0000000000004155, + 0x0000000000004400, 0x0000000000004401, 0x0000000000004404, 0x0000000000004405, 0x0000000000004410, 0x0000000000004411, 0x0000000000004414, 0x0000000000004415, + 0x0000000000004440, 0x0000000000004441, 0x0000000000004444, 0x0000000000004445, 0x0000000000004450, 0x0000000000004451, 0x0000000000004454, 0x0000000000004455, + 0x0000000000004500, 0x0000000000004501, 0x0000000000004504, 0x0000000000004505, 0x0000000000004510, 0x0000000000004511, 0x0000000000004514, 0x0000000000004515, + 0x0000000000004540, 0x0000000000004541, 0x0000000000004544, 0x0000000000004545, 0x0000000000004550, 0x0000000000004551, 0x0000000000004554, 0x0000000000004555, + 0x0000000000005000, 0x0000000000005001, 0x0000000000005004, 0x0000000000005005, 0x0000000000005010, 0x0000000000005011, 0x0000000000005014, 0x0000000000005015, + 0x0000000000005040, 0x0000000000005041, 0x0000000000005044, 0x0000000000005045, 0x0000000000005050, 0x0000000000005051, 0x0000000000005054, 0x0000000000005055, + 0x0000000000005100, 0x0000000000005101, 0x0000000000005104, 0x0000000000005105, 0x0000000000005110, 0x0000000000005111, 0x0000000000005114, 0x0000000000005115, + 0x0000000000005140, 0x0000000000005141, 0x0000000000005144, 0x0000000000005145, 0x0000000000005150, 0x0000000000005151, 0x0000000000005154, 0x0000000000005155, + 0x0000000000005400, 0x0000000000005401, 0x0000000000005404, 0x0000000000005405, 0x0000000000005410, 0x0000000000005411, 0x0000000000005414, 0x0000000000005415, + 0x0000000000005440, 0x0000000000005441, 0x0000000000005444, 0x0000000000005445, 0x0000000000005450, 0x0000000000005451, 0x0000000000005454, 0x0000000000005455, + 0x0000000000005500, 0x0000000000005501, 0x0000000000005504, 0x0000000000005505, 0x0000000000005510, 0x0000000000005511, 0x0000000000005514, 0x0000000000005515, + 0x0000000000005540, 0x0000000000005541, 0x0000000000005544, 0x0000000000005545, 0x0000000000005550, 0x0000000000005551, 0x0000000000005554, 0x0000000000005555 + }; - // LUT for Morton2D decode X + static const uint_fast64_t Morton2D_encode_y_256_64[256] = { + 0x0000000000000000, 0x0000000000000002, 0x0000000000000008, 0x000000000000000a, 0x0000000000000020, 0x0000000000000022, 0x0000000000000028, 0x000000000000002a, + 0x0000000000000080, 0x0000000000000082, 0x0000000000000088, 0x000000000000008a, 0x00000000000000a0, 0x00000000000000a2, 0x00000000000000a8, 0x00000000000000aa, + 0x0000000000000200, 0x0000000000000202, 0x0000000000000208, 0x000000000000020a, 0x0000000000000220, 0x0000000000000222, 0x0000000000000228, 0x000000000000022a, + 0x0000000000000280, 0x0000000000000282, 0x0000000000000288, 0x000000000000028a, 0x00000000000002a0, 0x00000000000002a2, 0x00000000000002a8, 0x00000000000002aa, + 0x0000000000000800, 0x0000000000000802, 0x0000000000000808, 0x000000000000080a, 0x0000000000000820, 0x0000000000000822, 0x0000000000000828, 0x000000000000082a, + 0x0000000000000880, 0x0000000000000882, 0x0000000000000888, 0x000000000000088a, 0x00000000000008a0, 0x00000000000008a2, 0x00000000000008a8, 0x00000000000008aa, + 0x0000000000000a00, 0x0000000000000a02, 0x0000000000000a08, 0x0000000000000a0a, 0x0000000000000a20, 0x0000000000000a22, 0x0000000000000a28, 0x0000000000000a2a, + 0x0000000000000a80, 0x0000000000000a82, 0x0000000000000a88, 0x0000000000000a8a, 0x0000000000000aa0, 0x0000000000000aa2, 0x0000000000000aa8, 0x0000000000000aaa, + 0x0000000000002000, 0x0000000000002002, 0x0000000000002008, 0x000000000000200a, 0x0000000000002020, 0x0000000000002022, 0x0000000000002028, 0x000000000000202a, + 0x0000000000002080, 0x0000000000002082, 0x0000000000002088, 0x000000000000208a, 0x00000000000020a0, 0x00000000000020a2, 0x00000000000020a8, 0x00000000000020aa, + 0x0000000000002200, 0x0000000000002202, 0x0000000000002208, 0x000000000000220a, 0x0000000000002220, 0x0000000000002222, 0x0000000000002228, 0x000000000000222a, + 0x0000000000002280, 0x0000000000002282, 0x0000000000002288, 0x000000000000228a, 0x00000000000022a0, 0x00000000000022a2, 0x00000000000022a8, 0x00000000000022aa, + 0x0000000000002800, 0x0000000000002802, 0x0000000000002808, 0x000000000000280a, 0x0000000000002820, 0x0000000000002822, 0x0000000000002828, 0x000000000000282a, + 0x0000000000002880, 0x0000000000002882, 0x0000000000002888, 0x000000000000288a, 0x00000000000028a0, 0x00000000000028a2, 0x00000000000028a8, 0x00000000000028aa, + 0x0000000000002a00, 0x0000000000002a02, 0x0000000000002a08, 0x0000000000002a0a, 0x0000000000002a20, 0x0000000000002a22, 0x0000000000002a28, 0x0000000000002a2a, + 0x0000000000002a80, 0x0000000000002a82, 0x0000000000002a88, 0x0000000000002a8a, 0x0000000000002aa0, 0x0000000000002aa2, 0x0000000000002aa8, 0x0000000000002aaa, + 0x0000000000008000, 0x0000000000008002, 0x0000000000008008, 0x000000000000800a, 0x0000000000008020, 0x0000000000008022, 0x0000000000008028, 0x000000000000802a, + 0x0000000000008080, 0x0000000000008082, 0x0000000000008088, 0x000000000000808a, 0x00000000000080a0, 0x00000000000080a2, 0x00000000000080a8, 0x00000000000080aa, + 0x0000000000008200, 0x0000000000008202, 0x0000000000008208, 0x000000000000820a, 0x0000000000008220, 0x0000000000008222, 0x0000000000008228, 0x000000000000822a, + 0x0000000000008280, 0x0000000000008282, 0x0000000000008288, 0x000000000000828a, 0x00000000000082a0, 0x00000000000082a2, 0x00000000000082a8, 0x00000000000082aa, + 0x0000000000008800, 0x0000000000008802, 0x0000000000008808, 0x000000000000880a, 0x0000000000008820, 0x0000000000008822, 0x0000000000008828, 0x000000000000882a, + 0x0000000000008880, 0x0000000000008882, 0x0000000000008888, 0x000000000000888a, 0x00000000000088a0, 0x00000000000088a2, 0x00000000000088a8, 0x00000000000088aa, + 0x0000000000008a00, 0x0000000000008a02, 0x0000000000008a08, 0x0000000000008a0a, 0x0000000000008a20, 0x0000000000008a22, 0x0000000000008a28, 0x0000000000008a2a, + 0x0000000000008a80, 0x0000000000008a82, 0x0000000000008a88, 0x0000000000008a8a, 0x0000000000008aa0, 0x0000000000008aa2, 0x0000000000008aa8, 0x0000000000008aaa, + 0x000000000000a000, 0x000000000000a002, 0x000000000000a008, 0x000000000000a00a, 0x000000000000a020, 0x000000000000a022, 0x000000000000a028, 0x000000000000a02a, + 0x000000000000a080, 0x000000000000a082, 0x000000000000a088, 0x000000000000a08a, 0x000000000000a0a0, 0x000000000000a0a2, 0x000000000000a0a8, 0x000000000000a0aa, + 0x000000000000a200, 0x000000000000a202, 0x000000000000a208, 0x000000000000a20a, 0x000000000000a220, 0x000000000000a222, 0x000000000000a228, 0x000000000000a22a, + 0x000000000000a280, 0x000000000000a282, 0x000000000000a288, 0x000000000000a28a, 0x000000000000a2a0, 0x000000000000a2a2, 0x000000000000a2a8, 0x000000000000a2aa, + 0x000000000000a800, 0x000000000000a802, 0x000000000000a808, 0x000000000000a80a, 0x000000000000a820, 0x000000000000a822, 0x000000000000a828, 0x000000000000a82a, + 0x000000000000a880, 0x000000000000a882, 0x000000000000a888, 0x000000000000a88a, 0x000000000000a8a0, 0x000000000000a8a2, 0x000000000000a8a8, 0x000000000000a8aa, + 0x000000000000aa00, 0x000000000000aa02, 0x000000000000aa08, 0x000000000000aa0a, 0x000000000000aa20, 0x000000000000aa22, 0x000000000000aa28, 0x000000000000aa2a, + 0x000000000000aa80, 0x000000000000aa82, 0x000000000000aa88, 0x000000000000aa8a, 0x000000000000aaa0, 0x000000000000aaa2, 0x000000000000aaa8, 0x000000000000aaaa + + }; + + // preshifted 2D Decode LUTs (256 entries) + static const uint_fast8_t Morton2D_decode_preshifted_x_256[256] = { + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15 + + }; + + static const uint_fast8_t Morton2D_decode_preshifted_y_256[256] = { + 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, + 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, + 4, 4, 5, 5, 4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 7, 7, + 4, 4, 5, 5, 4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 7, 7, + 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, + 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, + 4, 4, 5, 5, 4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 7, 7, + 4, 4, 5, 5, 4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 7, 7, + 8, 8, 9, 9, 8, 8, 9, 9, 10, 10, 11, 11, 10, 10, 11, 11, + 8, 8, 9, 9, 8, 8, 9, 9, 10, 10, 11, 11, 10, 10, 11, 11, + 12, 12, 13, 13, 12, 12, 13, 13, 14, 14, 15, 15, 14, 14, 15, 15, + 12, 12, 13, 13, 12, 12, 13, 13, 14, 14, 15, 15, 14, 14, 15, 15, + 8, 8, 9, 9, 8, 8, 9, 9, 10, 10, 11, 11, 10, 10, 11, 11, + 8, 8, 9, 9, 8, 8, 9, 9, 10, 10, 11, 11, 10, 10, 11, 11, + 12, 12, 13, 13, 12, 12, 13, 13, 14, 14, 15, 15, 14, 14, 15, 15, + 12, 12, 13, 13, 12, 12, 13, 13, 14, 14, 15, 15, 14, 14, 15, 15 + + }; + + // 2D Decode LUTs (256 entries) static const uint_fast8_t Morton2D_decode_x_256[256] = { - 0,1,0,1,2,3,2,3,0,1,0,1,2,3,2,3, - 4,5,4,5,6,7,6,7,4,5,4,5,6,7,6,7, - 0,1,0,1,2,3,2,3,0,1,0,1,2,3,2,3, - 4,5,4,5,6,7,6,7,4,5,4,5,6,7,6,7, - 8,9,8,9,10,11,10,11,8,9,8,9,10,11,10,11, - 12,13,12,13,14,15,14,15,12,13,12,13,14,15,14,15, - 8,9,8,9,10,11,10,11,8,9,8,9,10,11,10,11, - 12,13,12,13,14,15,14,15,12,13,12,13,14,15,14,15, - 0,1,0,1,2,3,2,3,0,1,0,1,2,3,2,3, - 4,5,4,5,6,7,6,7,4,5,4,5,6,7,6,7, - 0,1,0,1,2,3,2,3,0,1,0,1,2,3,2,3, - 4,5,4,5,6,7,6,7,4,5,4,5,6,7,6,7, - 8,9,8,9,10,11,10,11,8,9,8,9,10,11,10,11, - 12,13,12,13,14,15,14,15,12,13,12,13,14,15,14,15, - 8,9,8,9,10,11,10,11,8,9,8,9,10,11,10,11, - 12,13,12,13,14,15,14,15,12,13,12,13,14,15,14,15 + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15 + }; - // LUT for Morton2D decode Y static const uint_fast8_t Morton2D_decode_y_256[256] = { - 0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3, - 0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3, - 4,4,5,5,4,4,5,5,6,6,7,7,6,6,7,7, - 4,4,5,5,4,4,5,5,6,6,7,7,6,6,7,7, - 0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3, - 0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3, - 4,4,5,5,4,4,5,5,6,6,7,7,6,6,7,7, - 4,4,5,5,4,4,5,5,6,6,7,7,6,6,7,7, - 8,8,9,9,8,8,9,9,10,10,11,11,10,10,11,11, - 8,8,9,9,8,8,9,9,10,10,11,11,10,10,11,11, - 12,12,13,13,12,12,13,13,14,14,15,15,14,14,15,15, - 12,12,13,13,12,12,13,13,14,14,15,15,14,14,15,15, - 8,8,9,9,8,8,9,9,10,10,11,11,10,10,11,11, - 8,8,9,9,8,8,9,9,10,10,11,11,10,10,11,11, - 12,12,13,13,12,12,13,13,14,14,15,15,14,14,15,15, - 12,12,13,13,12,12,13,13,14,14,15,15,14,14,15,15 + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15 + }; + } diff --git a/include/libmorton/morton3D.h b/include/libmorton/morton3D.h index d5b0692..0b3e0bb 100644 --- a/include/libmorton/morton3D.h +++ b/include/libmorton/morton3D.h @@ -3,6 +3,7 @@ // Libmorton - Methods to encode/decode 64-bit morton codes from/to 32-bit (x,y,z) coordinates // Warning: morton.h will always point to the functions that use the fastest available method. +#include #include #include #include @@ -39,9 +40,23 @@ namespace libmorton { unsigned int shift = (i - 1) * 8; answer = answer << 24 | - (Morton3D_encode_z_256[(z >> shift) & EIGHTBITMASK] | - Morton3D_encode_y_256[(y >> shift) & EIGHTBITMASK] | - Morton3D_encode_x_256[(x >> shift) & EIGHTBITMASK]); + (Morton3D_encode_z_256_32[(z >> shift) & EIGHTBITMASK] | + Morton3D_encode_y_256_32[(y >> shift) & EIGHTBITMASK] | + Morton3D_encode_x_256_32[(x >> shift) & EIGHTBITMASK]); + } + return answer; + } + + template::value>> + inline morton m3D_e_sLUT(const coord x, const coord y, const coord z) { + morton answer = 0; + for (unsigned int i = sizeof(coord); i > 0; --i) { + unsigned int shift = (i - 1) * 8; + answer = + answer << 24 | + (Morton3D_encode_z_256_64[(z >> shift) & EIGHTBITMASK] | + Morton3D_encode_y_256_64[(y >> shift) & EIGHTBITMASK] | + Morton3D_encode_x_256_64[(x >> shift) & EIGHTBITMASK]); } return answer; } @@ -54,22 +69,39 @@ namespace libmorton { unsigned int shift = (i - 1) * 8; answer = answer << 24 | - (Morton3D_encode_x_256[(z >> shift) & EIGHTBITMASK] << morton(2)) | - (Morton3D_encode_x_256[(y >> shift) & EIGHTBITMASK] << morton(1)) | - Morton3D_encode_x_256[(x >> shift) & EIGHTBITMASK]; - } + (Morton3D_encode_x_256_32[(z >> shift) & EIGHTBITMASK] << morton(2)) | + (Morton3D_encode_x_256_32[(y >> shift) & EIGHTBITMASK] << morton(1)) | + Morton3D_encode_x_256_32[(x >> shift) & EIGHTBITMASK]; + } + return answer; + } + + // ENCODE 3D Morton code : LookUpTable (LUT) + template::value>> + inline morton m3D_e_LUT(const coord x, const coord y, const coord z) { + morton answer = 0; + for (unsigned int i = sizeof(coord); i > 0; --i) { + unsigned int shift = (i - 1) * 8; + answer = + answer << 24 | + (Morton3D_encode_x_256_64[(z >> shift) & EIGHTBITMASK] << morton(2)) | + (Morton3D_encode_x_256_64[(y >> shift) & EIGHTBITMASK] << morton(1)) | + Morton3D_encode_x_256_64[(x >> shift) & EIGHTBITMASK]; + } return answer; } // HELPER METHOD for ET LUT encode - template - inline morton compute3D_ET_LUT_encode(const coord c, const coord *LUT) { + template + inline morton compute3D_ET_LUT_encode(const coord c, const lutT *LUT) { unsigned long maxbit = 0; if (findFirstSetBit(c, &maxbit) == 0) { return 0; } + // highest byte index containing any set bit + int highest_byte = static_cast((maxbit + 1) / 8); morton answer = 0; - for (int i = (int)ceil((maxbit + 1) / 8.0f); i >= 0; --i) { + for (int i = highest_byte; i >= 0; --i) { unsigned int shift = i * 8; - answer = answer << 24 | (LUT[(c >> shift) & EIGHTBITMASK]); + answer = (answer << 24) | static_cast(LUT[(c >> shift) & EIGHTBITMASK]); } return answer; } @@ -79,9 +111,17 @@ namespace libmorton { // Figuring this out is probably too costly in most cases. template inline morton m3D_e_sLUT_ET(const coord x, const coord y, const coord z) { - morton answer_x = compute3D_ET_LUT_encode(x, Morton3D_encode_x_256); - morton answer_y = compute3D_ET_LUT_encode(y, Morton3D_encode_y_256); - morton answer_z = compute3D_ET_LUT_encode(z, Morton3D_encode_z_256); + morton answer_x = compute3D_ET_LUT_encode(x, Morton3D_encode_x_256_32); + morton answer_y = compute3D_ET_LUT_encode(y, Morton3D_encode_y_256_32); + morton answer_z = compute3D_ET_LUT_encode(z, Morton3D_encode_z_256_32); + return answer_z | answer_y | answer_x; + } + + template::value>> + inline morton m3D_e_sLUT_ET(const coord x, const coord y, const coord z) { + morton answer_x = compute3D_ET_LUT_encode(x, Morton3D_encode_x_256_64); + morton answer_y = compute3D_ET_LUT_encode(y, Morton3D_encode_y_256_64); + morton answer_z = compute3D_ET_LUT_encode(z, Morton3D_encode_z_256_64); return answer_z | answer_y | answer_x; } @@ -90,9 +130,21 @@ namespace libmorton { // Figuring this out is probably too costly in most cases. template inline morton m3D_e_LUT_ET(const coord x, const coord y, const coord z) { - morton answer_x = compute3D_ET_LUT_encode(x, Morton3D_encode_x_256); - morton answer_y = compute3D_ET_LUT_encode(y, Morton3D_encode_x_256); - morton answer_z = compute3D_ET_LUT_encode(z, Morton3D_encode_x_256); + morton answer_x = compute3D_ET_LUT_encode(x, Morton3D_encode_x_256_32); + // This is because `Morton3D_encode_(y|z)_256_*` is basically just `Morton3D_encode_x_256_*` with some pre-shifting. + // And we don't want any pre-shifting in this case. + morton answer_y = compute3D_ET_LUT_encode(y, Morton3D_encode_x_256_32); + morton answer_z = compute3D_ET_LUT_encode(z, Morton3D_encode_x_256_32); + return (answer_z << 2) | (answer_y << 1) | answer_x; + } + + template::value>> + inline morton m3D_e_LUT_ET(const coord x, const coord y, const coord z) { + morton answer_x = compute3D_ET_LUT_encode(x, Morton3D_encode_x_256_64); + // This is because `Morton3D_encode_(y|z)_256_*` is basically just `Morton3D_encode_x_256_*` with some pre-shifting. + // And we don't want any pre-shifting in this case. + morton answer_y = compute3D_ET_LUT_encode(y, Morton3D_encode_x_256_64); + morton answer_z = compute3D_ET_LUT_encode(z, Morton3D_encode_x_256_64); return (answer_z << 2) | (answer_y << 1) | answer_x; } @@ -172,17 +224,17 @@ namespace libmorton { // DECODE 3D Morton code : Shifted LUT template inline void m3D_d_sLUT(const morton m, coord& x, coord& y, coord& z) { - x = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_x_512, 0); - y = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_y_512, 0); - z = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_z_512, 0); + x = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_preshifted_x_512_gen, 0); + y = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_preshifted_y_512_gen, 0); + z = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_preshifted_z_512_gen, 0); } // DECODE 3D Morton code : LUT template inline void m3D_d_LUT(const morton m, coord& x, coord& y, coord& z) { - x = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_x_512, 0); - y = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_x_512, 1); - z = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_x_512, 2); + x = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_x_512_gen, 0); + y = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_y_512_gen, 1); + z = morton3D_DecodeCoord_LUT256(m, Morton3D_decode_z_512_gen, 2); } // DECODE 3D Morton code : Shifted LUT (Early termination version) @@ -195,9 +247,9 @@ namespace libmorton { unsigned int shiftback = 0; while (firstbit_location > i) { morton m_shifted = (m >> i) & NINEBITMASK; - x |= (coord)Morton3D_decode_x_512[m_shifted] << shiftback; - y |= (coord)Morton3D_decode_y_512[m_shifted] << shiftback; - z |= (coord)Morton3D_decode_z_512[m_shifted] << shiftback; + x |= (coord)Morton3D_decode_preshifted_x_512_gen[m_shifted] << shiftback; + y |= (coord)Morton3D_decode_preshifted_y_512_gen[m_shifted] << shiftback; + z |= (coord)Morton3D_decode_preshifted_z_512_gen[m_shifted] << shiftback; shiftback += 3; i += 9; } @@ -213,9 +265,9 @@ namespace libmorton { unsigned int i = 0; unsigned int shiftback = 0; while (i < firstbit_location) { - x = x | (coord)Morton3D_decode_x_512[(m >> i) & NINEBITMASK] << shiftback; - y = y | (coord)Morton3D_decode_x_512[(m >> (i + 1)) & NINEBITMASK] << shiftback; - z = z | (coord)Morton3D_decode_x_512[(m >> (i + 2)) & NINEBITMASK] << shiftback; + x = x | (coord)Morton3D_decode_x_512_gen[(m >> i) & NINEBITMASK] << shiftback; + y = y | (coord)Morton3D_decode_y_512_gen[(m >> (i + 1)) & NINEBITMASK] << shiftback; + z = z | (coord)Morton3D_decode_z_512_gen[(m >> (i + 2)) & NINEBITMASK] << shiftback; i += 9; shiftback += 3; } diff --git a/include/libmorton/morton3D_LUTs.h b/include/libmorton/morton3D_LUTs.h index fedf063..8974e62 100644 --- a/include/libmorton/morton3D_LUTs.h +++ b/include/libmorton/morton3D_LUTs.h @@ -2,121 +2,228 @@ #include -namespace libmorton { - // LUT for Morton3D encode X - static const uint_fast32_t Morton3D_encode_x_256[256] = - { - 0x00000000, - 0x00000001, 0x00000008, 0x00000009, 0x00000040, 0x00000041, 0x00000048, 0x00000049, 0x00000200, - 0x00000201, 0x00000208, 0x00000209, 0x00000240, 0x00000241, 0x00000248, 0x00000249, 0x00001000, - 0x00001001, 0x00001008, 0x00001009, 0x00001040, 0x00001041, 0x00001048, 0x00001049, 0x00001200, - 0x00001201, 0x00001208, 0x00001209, 0x00001240, 0x00001241, 0x00001248, 0x00001249, 0x00008000, - 0x00008001, 0x00008008, 0x00008009, 0x00008040, 0x00008041, 0x00008048, 0x00008049, 0x00008200, - 0x00008201, 0x00008208, 0x00008209, 0x00008240, 0x00008241, 0x00008248, 0x00008249, 0x00009000, - 0x00009001, 0x00009008, 0x00009009, 0x00009040, 0x00009041, 0x00009048, 0x00009049, 0x00009200, - 0x00009201, 0x00009208, 0x00009209, 0x00009240, 0x00009241, 0x00009248, 0x00009249, 0x00040000, - 0x00040001, 0x00040008, 0x00040009, 0x00040040, 0x00040041, 0x00040048, 0x00040049, 0x00040200, - 0x00040201, 0x00040208, 0x00040209, 0x00040240, 0x00040241, 0x00040248, 0x00040249, 0x00041000, - 0x00041001, 0x00041008, 0x00041009, 0x00041040, 0x00041041, 0x00041048, 0x00041049, 0x00041200, - 0x00041201, 0x00041208, 0x00041209, 0x00041240, 0x00041241, 0x00041248, 0x00041249, 0x00048000, - 0x00048001, 0x00048008, 0x00048009, 0x00048040, 0x00048041, 0x00048048, 0x00048049, 0x00048200, - 0x00048201, 0x00048208, 0x00048209, 0x00048240, 0x00048241, 0x00048248, 0x00048249, 0x00049000, - 0x00049001, 0x00049008, 0x00049009, 0x00049040, 0x00049041, 0x00049048, 0x00049049, 0x00049200, - 0x00049201, 0x00049208, 0x00049209, 0x00049240, 0x00049241, 0x00049248, 0x00049249, 0x00200000, - 0x00200001, 0x00200008, 0x00200009, 0x00200040, 0x00200041, 0x00200048, 0x00200049, 0x00200200, - 0x00200201, 0x00200208, 0x00200209, 0x00200240, 0x00200241, 0x00200248, 0x00200249, 0x00201000, - 0x00201001, 0x00201008, 0x00201009, 0x00201040, 0x00201041, 0x00201048, 0x00201049, 0x00201200, - 0x00201201, 0x00201208, 0x00201209, 0x00201240, 0x00201241, 0x00201248, 0x00201249, 0x00208000, - 0x00208001, 0x00208008, 0x00208009, 0x00208040, 0x00208041, 0x00208048, 0x00208049, 0x00208200, - 0x00208201, 0x00208208, 0x00208209, 0x00208240, 0x00208241, 0x00208248, 0x00208249, 0x00209000, - 0x00209001, 0x00209008, 0x00209009, 0x00209040, 0x00209041, 0x00209048, 0x00209049, 0x00209200, - 0x00209201, 0x00209208, 0x00209209, 0x00209240, 0x00209241, 0x00209248, 0x00209249, 0x00240000, - 0x00240001, 0x00240008, 0x00240009, 0x00240040, 0x00240041, 0x00240048, 0x00240049, 0x00240200, - 0x00240201, 0x00240208, 0x00240209, 0x00240240, 0x00240241, 0x00240248, 0x00240249, 0x00241000, - 0x00241001, 0x00241008, 0x00241009, 0x00241040, 0x00241041, 0x00241048, 0x00241049, 0x00241200, - 0x00241201, 0x00241208, 0x00241209, 0x00241240, 0x00241241, 0x00241248, 0x00241249, 0x00248000, - 0x00248001, 0x00248008, 0x00248009, 0x00248040, 0x00248041, 0x00248048, 0x00248049, 0x00248200, - 0x00248201, 0x00248208, 0x00248209, 0x00248240, 0x00248241, 0x00248248, 0x00248249, 0x00249000, - 0x00249001, 0x00249008, 0x00249009, 0x00249040, 0x00249041, 0x00249048, 0x00249049, 0x00249200, - 0x00249201, 0x00249208, 0x00249209, 0x00249240, 0x00249241, 0x00249248, 0x00249249 +namespace libmorton +{ + // 3D Encode LUTs (32-bit) + static const uint_fast32_t Morton3D_encode_x_256_32[256] = { + 0x00000000, 0x00000001, 0x00000008, 0x00000009, 0x00000040, 0x00000041, 0x00000048, 0x00000049, + 0x00000200, 0x00000201, 0x00000208, 0x00000209, 0x00000240, 0x00000241, 0x00000248, 0x00000249, + 0x00001000, 0x00001001, 0x00001008, 0x00001009, 0x00001040, 0x00001041, 0x00001048, 0x00001049, + 0x00001200, 0x00001201, 0x00001208, 0x00001209, 0x00001240, 0x00001241, 0x00001248, 0x00001249, + 0x00008000, 0x00008001, 0x00008008, 0x00008009, 0x00008040, 0x00008041, 0x00008048, 0x00008049, + 0x00008200, 0x00008201, 0x00008208, 0x00008209, 0x00008240, 0x00008241, 0x00008248, 0x00008249, + 0x00009000, 0x00009001, 0x00009008, 0x00009009, 0x00009040, 0x00009041, 0x00009048, 0x00009049, + 0x00009200, 0x00009201, 0x00009208, 0x00009209, 0x00009240, 0x00009241, 0x00009248, 0x00009249, + 0x00040000, 0x00040001, 0x00040008, 0x00040009, 0x00040040, 0x00040041, 0x00040048, 0x00040049, + 0x00040200, 0x00040201, 0x00040208, 0x00040209, 0x00040240, 0x00040241, 0x00040248, 0x00040249, + 0x00041000, 0x00041001, 0x00041008, 0x00041009, 0x00041040, 0x00041041, 0x00041048, 0x00041049, + 0x00041200, 0x00041201, 0x00041208, 0x00041209, 0x00041240, 0x00041241, 0x00041248, 0x00041249, + 0x00048000, 0x00048001, 0x00048008, 0x00048009, 0x00048040, 0x00048041, 0x00048048, 0x00048049, + 0x00048200, 0x00048201, 0x00048208, 0x00048209, 0x00048240, 0x00048241, 0x00048248, 0x00048249, + 0x00049000, 0x00049001, 0x00049008, 0x00049009, 0x00049040, 0x00049041, 0x00049048, 0x00049049, + 0x00049200, 0x00049201, 0x00049208, 0x00049209, 0x00049240, 0x00049241, 0x00049248, 0x00049249, + 0x00200000, 0x00200001, 0x00200008, 0x00200009, 0x00200040, 0x00200041, 0x00200048, 0x00200049, + 0x00200200, 0x00200201, 0x00200208, 0x00200209, 0x00200240, 0x00200241, 0x00200248, 0x00200249, + 0x00201000, 0x00201001, 0x00201008, 0x00201009, 0x00201040, 0x00201041, 0x00201048, 0x00201049, + 0x00201200, 0x00201201, 0x00201208, 0x00201209, 0x00201240, 0x00201241, 0x00201248, 0x00201249, + 0x00208000, 0x00208001, 0x00208008, 0x00208009, 0x00208040, 0x00208041, 0x00208048, 0x00208049, + 0x00208200, 0x00208201, 0x00208208, 0x00208209, 0x00208240, 0x00208241, 0x00208248, 0x00208249, + 0x00209000, 0x00209001, 0x00209008, 0x00209009, 0x00209040, 0x00209041, 0x00209048, 0x00209049, + 0x00209200, 0x00209201, 0x00209208, 0x00209209, 0x00209240, 0x00209241, 0x00209248, 0x00209249, + 0x00240000, 0x00240001, 0x00240008, 0x00240009, 0x00240040, 0x00240041, 0x00240048, 0x00240049, + 0x00240200, 0x00240201, 0x00240208, 0x00240209, 0x00240240, 0x00240241, 0x00240248, 0x00240249, + 0x00241000, 0x00241001, 0x00241008, 0x00241009, 0x00241040, 0x00241041, 0x00241048, 0x00241049, + 0x00241200, 0x00241201, 0x00241208, 0x00241209, 0x00241240, 0x00241241, 0x00241248, 0x00241249, + 0x00248000, 0x00248001, 0x00248008, 0x00248009, 0x00248040, 0x00248041, 0x00248048, 0x00248049, + 0x00248200, 0x00248201, 0x00248208, 0x00248209, 0x00248240, 0x00248241, 0x00248248, 0x00248249, + 0x00249000, 0x00249001, 0x00249008, 0x00249009, 0x00249040, 0x00249041, 0x00249048, 0x00249049, + 0x00249200, 0x00249201, 0x00249208, 0x00249209, 0x00249240, 0x00249241, 0x00249248, 0x00249249 + + }; + + static const uint_fast32_t Morton3D_encode_y_256_32[256] = { + 0x00000000, 0x00000002, 0x00000010, 0x00000012, 0x00000080, 0x00000082, 0x00000090, 0x00000092, + 0x00000400, 0x00000402, 0x00000410, 0x00000412, 0x00000480, 0x00000482, 0x00000490, 0x00000492, + 0x00002000, 0x00002002, 0x00002010, 0x00002012, 0x00002080, 0x00002082, 0x00002090, 0x00002092, + 0x00002400, 0x00002402, 0x00002410, 0x00002412, 0x00002480, 0x00002482, 0x00002490, 0x00002492, + 0x00010000, 0x00010002, 0x00010010, 0x00010012, 0x00010080, 0x00010082, 0x00010090, 0x00010092, + 0x00010400, 0x00010402, 0x00010410, 0x00010412, 0x00010480, 0x00010482, 0x00010490, 0x00010492, + 0x00012000, 0x00012002, 0x00012010, 0x00012012, 0x00012080, 0x00012082, 0x00012090, 0x00012092, + 0x00012400, 0x00012402, 0x00012410, 0x00012412, 0x00012480, 0x00012482, 0x00012490, 0x00012492, + 0x00080000, 0x00080002, 0x00080010, 0x00080012, 0x00080080, 0x00080082, 0x00080090, 0x00080092, + 0x00080400, 0x00080402, 0x00080410, 0x00080412, 0x00080480, 0x00080482, 0x00080490, 0x00080492, + 0x00082000, 0x00082002, 0x00082010, 0x00082012, 0x00082080, 0x00082082, 0x00082090, 0x00082092, + 0x00082400, 0x00082402, 0x00082410, 0x00082412, 0x00082480, 0x00082482, 0x00082490, 0x00082492, + 0x00090000, 0x00090002, 0x00090010, 0x00090012, 0x00090080, 0x00090082, 0x00090090, 0x00090092, + 0x00090400, 0x00090402, 0x00090410, 0x00090412, 0x00090480, 0x00090482, 0x00090490, 0x00090492, + 0x00092000, 0x00092002, 0x00092010, 0x00092012, 0x00092080, 0x00092082, 0x00092090, 0x00092092, + 0x00092400, 0x00092402, 0x00092410, 0x00092412, 0x00092480, 0x00092482, 0x00092490, 0x00092492, + 0x00400000, 0x00400002, 0x00400010, 0x00400012, 0x00400080, 0x00400082, 0x00400090, 0x00400092, + 0x00400400, 0x00400402, 0x00400410, 0x00400412, 0x00400480, 0x00400482, 0x00400490, 0x00400492, + 0x00402000, 0x00402002, 0x00402010, 0x00402012, 0x00402080, 0x00402082, 0x00402090, 0x00402092, + 0x00402400, 0x00402402, 0x00402410, 0x00402412, 0x00402480, 0x00402482, 0x00402490, 0x00402492, + 0x00410000, 0x00410002, 0x00410010, 0x00410012, 0x00410080, 0x00410082, 0x00410090, 0x00410092, + 0x00410400, 0x00410402, 0x00410410, 0x00410412, 0x00410480, 0x00410482, 0x00410490, 0x00410492, + 0x00412000, 0x00412002, 0x00412010, 0x00412012, 0x00412080, 0x00412082, 0x00412090, 0x00412092, + 0x00412400, 0x00412402, 0x00412410, 0x00412412, 0x00412480, 0x00412482, 0x00412490, 0x00412492, + 0x00480000, 0x00480002, 0x00480010, 0x00480012, 0x00480080, 0x00480082, 0x00480090, 0x00480092, + 0x00480400, 0x00480402, 0x00480410, 0x00480412, 0x00480480, 0x00480482, 0x00480490, 0x00480492, + 0x00482000, 0x00482002, 0x00482010, 0x00482012, 0x00482080, 0x00482082, 0x00482090, 0x00482092, + 0x00482400, 0x00482402, 0x00482410, 0x00482412, 0x00482480, 0x00482482, 0x00482490, 0x00482492, + 0x00490000, 0x00490002, 0x00490010, 0x00490012, 0x00490080, 0x00490082, 0x00490090, 0x00490092, + 0x00490400, 0x00490402, 0x00490410, 0x00490412, 0x00490480, 0x00490482, 0x00490490, 0x00490492, + 0x00492000, 0x00492002, 0x00492010, 0x00492012, 0x00492080, 0x00492082, 0x00492090, 0x00492092, + 0x00492400, 0x00492402, 0x00492410, 0x00492412, 0x00492480, 0x00492482, 0x00492490, 0x00492492 + + }; + + static const uint_fast32_t Morton3D_encode_z_256_32[256] = { + 0x00000000, 0x00000004, 0x00000020, 0x00000024, 0x00000100, 0x00000104, 0x00000120, 0x00000124, + 0x00000800, 0x00000804, 0x00000820, 0x00000824, 0x00000900, 0x00000904, 0x00000920, 0x00000924, + 0x00004000, 0x00004004, 0x00004020, 0x00004024, 0x00004100, 0x00004104, 0x00004120, 0x00004124, + 0x00004800, 0x00004804, 0x00004820, 0x00004824, 0x00004900, 0x00004904, 0x00004920, 0x00004924, + 0x00020000, 0x00020004, 0x00020020, 0x00020024, 0x00020100, 0x00020104, 0x00020120, 0x00020124, + 0x00020800, 0x00020804, 0x00020820, 0x00020824, 0x00020900, 0x00020904, 0x00020920, 0x00020924, + 0x00024000, 0x00024004, 0x00024020, 0x00024024, 0x00024100, 0x00024104, 0x00024120, 0x00024124, + 0x00024800, 0x00024804, 0x00024820, 0x00024824, 0x00024900, 0x00024904, 0x00024920, 0x00024924, + 0x00100000, 0x00100004, 0x00100020, 0x00100024, 0x00100100, 0x00100104, 0x00100120, 0x00100124, + 0x00100800, 0x00100804, 0x00100820, 0x00100824, 0x00100900, 0x00100904, 0x00100920, 0x00100924, + 0x00104000, 0x00104004, 0x00104020, 0x00104024, 0x00104100, 0x00104104, 0x00104120, 0x00104124, + 0x00104800, 0x00104804, 0x00104820, 0x00104824, 0x00104900, 0x00104904, 0x00104920, 0x00104924, + 0x00120000, 0x00120004, 0x00120020, 0x00120024, 0x00120100, 0x00120104, 0x00120120, 0x00120124, + 0x00120800, 0x00120804, 0x00120820, 0x00120824, 0x00120900, 0x00120904, 0x00120920, 0x00120924, + 0x00124000, 0x00124004, 0x00124020, 0x00124024, 0x00124100, 0x00124104, 0x00124120, 0x00124124, + 0x00124800, 0x00124804, 0x00124820, 0x00124824, 0x00124900, 0x00124904, 0x00124920, 0x00124924, + 0x00800000, 0x00800004, 0x00800020, 0x00800024, 0x00800100, 0x00800104, 0x00800120, 0x00800124, + 0x00800800, 0x00800804, 0x00800820, 0x00800824, 0x00800900, 0x00800904, 0x00800920, 0x00800924, + 0x00804000, 0x00804004, 0x00804020, 0x00804024, 0x00804100, 0x00804104, 0x00804120, 0x00804124, + 0x00804800, 0x00804804, 0x00804820, 0x00804824, 0x00804900, 0x00804904, 0x00804920, 0x00804924, + 0x00820000, 0x00820004, 0x00820020, 0x00820024, 0x00820100, 0x00820104, 0x00820120, 0x00820124, + 0x00820800, 0x00820804, 0x00820820, 0x00820824, 0x00820900, 0x00820904, 0x00820920, 0x00820924, + 0x00824000, 0x00824004, 0x00824020, 0x00824024, 0x00824100, 0x00824104, 0x00824120, 0x00824124, + 0x00824800, 0x00824804, 0x00824820, 0x00824824, 0x00824900, 0x00824904, 0x00824920, 0x00824924, + 0x00900000, 0x00900004, 0x00900020, 0x00900024, 0x00900100, 0x00900104, 0x00900120, 0x00900124, + 0x00900800, 0x00900804, 0x00900820, 0x00900824, 0x00900900, 0x00900904, 0x00900920, 0x00900924, + 0x00904000, 0x00904004, 0x00904020, 0x00904024, 0x00904100, 0x00904104, 0x00904120, 0x00904124, + 0x00904800, 0x00904804, 0x00904820, 0x00904824, 0x00904900, 0x00904904, 0x00904920, 0x00904924, + 0x00920000, 0x00920004, 0x00920020, 0x00920024, 0x00920100, 0x00920104, 0x00920120, 0x00920124, + 0x00920800, 0x00920804, 0x00920820, 0x00920824, 0x00920900, 0x00920904, 0x00920920, 0x00920924, + 0x00924000, 0x00924004, 0x00924020, 0x00924024, 0x00924100, 0x00924104, 0x00924120, 0x00924124, + 0x00924800, 0x00924804, 0x00924820, 0x00924824, 0x00924900, 0x00924904, 0x00924920, 0x00924924 + + }; + + // 3D Encode LUTs (64-bit) + static const uint_fast64_t Morton3D_encode_x_256_64[256] = { + 0x0000000000000000, 0x0000000000000001, 0x0000000000000008, 0x0000000000000009, 0x0000000000000040, 0x0000000000000041, 0x0000000000000048, 0x0000000000000049, + 0x0000000000000200, 0x0000000000000201, 0x0000000000000208, 0x0000000000000209, 0x0000000000000240, 0x0000000000000241, 0x0000000000000248, 0x0000000000000249, + 0x0000000000001000, 0x0000000000001001, 0x0000000000001008, 0x0000000000001009, 0x0000000000001040, 0x0000000000001041, 0x0000000000001048, 0x0000000000001049, + 0x0000000000001200, 0x0000000000001201, 0x0000000000001208, 0x0000000000001209, 0x0000000000001240, 0x0000000000001241, 0x0000000000001248, 0x0000000000001249, + 0x0000000000008000, 0x0000000000008001, 0x0000000000008008, 0x0000000000008009, 0x0000000000008040, 0x0000000000008041, 0x0000000000008048, 0x0000000000008049, + 0x0000000000008200, 0x0000000000008201, 0x0000000000008208, 0x0000000000008209, 0x0000000000008240, 0x0000000000008241, 0x0000000000008248, 0x0000000000008249, + 0x0000000000009000, 0x0000000000009001, 0x0000000000009008, 0x0000000000009009, 0x0000000000009040, 0x0000000000009041, 0x0000000000009048, 0x0000000000009049, + 0x0000000000009200, 0x0000000000009201, 0x0000000000009208, 0x0000000000009209, 0x0000000000009240, 0x0000000000009241, 0x0000000000009248, 0x0000000000009249, + 0x0000000000040000, 0x0000000000040001, 0x0000000000040008, 0x0000000000040009, 0x0000000000040040, 0x0000000000040041, 0x0000000000040048, 0x0000000000040049, + 0x0000000000040200, 0x0000000000040201, 0x0000000000040208, 0x0000000000040209, 0x0000000000040240, 0x0000000000040241, 0x0000000000040248, 0x0000000000040249, + 0x0000000000041000, 0x0000000000041001, 0x0000000000041008, 0x0000000000041009, 0x0000000000041040, 0x0000000000041041, 0x0000000000041048, 0x0000000000041049, + 0x0000000000041200, 0x0000000000041201, 0x0000000000041208, 0x0000000000041209, 0x0000000000041240, 0x0000000000041241, 0x0000000000041248, 0x0000000000041249, + 0x0000000000048000, 0x0000000000048001, 0x0000000000048008, 0x0000000000048009, 0x0000000000048040, 0x0000000000048041, 0x0000000000048048, 0x0000000000048049, + 0x0000000000048200, 0x0000000000048201, 0x0000000000048208, 0x0000000000048209, 0x0000000000048240, 0x0000000000048241, 0x0000000000048248, 0x0000000000048249, + 0x0000000000049000, 0x0000000000049001, 0x0000000000049008, 0x0000000000049009, 0x0000000000049040, 0x0000000000049041, 0x0000000000049048, 0x0000000000049049, + 0x0000000000049200, 0x0000000000049201, 0x0000000000049208, 0x0000000000049209, 0x0000000000049240, 0x0000000000049241, 0x0000000000049248, 0x0000000000049249, + 0x0000000000200000, 0x0000000000200001, 0x0000000000200008, 0x0000000000200009, 0x0000000000200040, 0x0000000000200041, 0x0000000000200048, 0x0000000000200049, + 0x0000000000200200, 0x0000000000200201, 0x0000000000200208, 0x0000000000200209, 0x0000000000200240, 0x0000000000200241, 0x0000000000200248, 0x0000000000200249, + 0x0000000000201000, 0x0000000000201001, 0x0000000000201008, 0x0000000000201009, 0x0000000000201040, 0x0000000000201041, 0x0000000000201048, 0x0000000000201049, + 0x0000000000201200, 0x0000000000201201, 0x0000000000201208, 0x0000000000201209, 0x0000000000201240, 0x0000000000201241, 0x0000000000201248, 0x0000000000201249, + 0x0000000000208000, 0x0000000000208001, 0x0000000000208008, 0x0000000000208009, 0x0000000000208040, 0x0000000000208041, 0x0000000000208048, 0x0000000000208049, + 0x0000000000208200, 0x0000000000208201, 0x0000000000208208, 0x0000000000208209, 0x0000000000208240, 0x0000000000208241, 0x0000000000208248, 0x0000000000208249, + 0x0000000000209000, 0x0000000000209001, 0x0000000000209008, 0x0000000000209009, 0x0000000000209040, 0x0000000000209041, 0x0000000000209048, 0x0000000000209049, + 0x0000000000209200, 0x0000000000209201, 0x0000000000209208, 0x0000000000209209, 0x0000000000209240, 0x0000000000209241, 0x0000000000209248, 0x0000000000209249, + 0x0000000000240000, 0x0000000000240001, 0x0000000000240008, 0x0000000000240009, 0x0000000000240040, 0x0000000000240041, 0x0000000000240048, 0x0000000000240049, + 0x0000000000240200, 0x0000000000240201, 0x0000000000240208, 0x0000000000240209, 0x0000000000240240, 0x0000000000240241, 0x0000000000240248, 0x0000000000240249, + 0x0000000000241000, 0x0000000000241001, 0x0000000000241008, 0x0000000000241009, 0x0000000000241040, 0x0000000000241041, 0x0000000000241048, 0x0000000000241049, + 0x0000000000241200, 0x0000000000241201, 0x0000000000241208, 0x0000000000241209, 0x0000000000241240, 0x0000000000241241, 0x0000000000241248, 0x0000000000241249, + 0x0000000000248000, 0x0000000000248001, 0x0000000000248008, 0x0000000000248009, 0x0000000000248040, 0x0000000000248041, 0x0000000000248048, 0x0000000000248049, + 0x0000000000248200, 0x0000000000248201, 0x0000000000248208, 0x0000000000248209, 0x0000000000248240, 0x0000000000248241, 0x0000000000248248, 0x0000000000248249, + 0x0000000000249000, 0x0000000000249001, 0x0000000000249008, 0x0000000000249009, 0x0000000000249040, 0x0000000000249041, 0x0000000000249048, 0x0000000000249049, + 0x0000000000249200, 0x0000000000249201, 0x0000000000249208, 0x0000000000249209, 0x0000000000249240, 0x0000000000249241, 0x0000000000249248, 0x0000000000249249 + }; - // LUT for Morton3D encode Y - static const uint_fast32_t Morton3D_encode_y_256[256] = { - 0x00000000, - 0x00000002, 0x00000010, 0x00000012, 0x00000080, 0x00000082, 0x00000090, 0x00000092, 0x00000400, - 0x00000402, 0x00000410, 0x00000412, 0x00000480, 0x00000482, 0x00000490, 0x00000492, 0x00002000, - 0x00002002, 0x00002010, 0x00002012, 0x00002080, 0x00002082, 0x00002090, 0x00002092, 0x00002400, - 0x00002402, 0x00002410, 0x00002412, 0x00002480, 0x00002482, 0x00002490, 0x00002492, 0x00010000, - 0x00010002, 0x00010010, 0x00010012, 0x00010080, 0x00010082, 0x00010090, 0x00010092, 0x00010400, - 0x00010402, 0x00010410, 0x00010412, 0x00010480, 0x00010482, 0x00010490, 0x00010492, 0x00012000, - 0x00012002, 0x00012010, 0x00012012, 0x00012080, 0x00012082, 0x00012090, 0x00012092, 0x00012400, - 0x00012402, 0x00012410, 0x00012412, 0x00012480, 0x00012482, 0x00012490, 0x00012492, 0x00080000, - 0x00080002, 0x00080010, 0x00080012, 0x00080080, 0x00080082, 0x00080090, 0x00080092, 0x00080400, - 0x00080402, 0x00080410, 0x00080412, 0x00080480, 0x00080482, 0x00080490, 0x00080492, 0x00082000, - 0x00082002, 0x00082010, 0x00082012, 0x00082080, 0x00082082, 0x00082090, 0x00082092, 0x00082400, - 0x00082402, 0x00082410, 0x00082412, 0x00082480, 0x00082482, 0x00082490, 0x00082492, 0x00090000, - 0x00090002, 0x00090010, 0x00090012, 0x00090080, 0x00090082, 0x00090090, 0x00090092, 0x00090400, - 0x00090402, 0x00090410, 0x00090412, 0x00090480, 0x00090482, 0x00090490, 0x00090492, 0x00092000, - 0x00092002, 0x00092010, 0x00092012, 0x00092080, 0x00092082, 0x00092090, 0x00092092, 0x00092400, - 0x00092402, 0x00092410, 0x00092412, 0x00092480, 0x00092482, 0x00092490, 0x00092492, 0x00400000, - 0x00400002, 0x00400010, 0x00400012, 0x00400080, 0x00400082, 0x00400090, 0x00400092, 0x00400400, - 0x00400402, 0x00400410, 0x00400412, 0x00400480, 0x00400482, 0x00400490, 0x00400492, 0x00402000, - 0x00402002, 0x00402010, 0x00402012, 0x00402080, 0x00402082, 0x00402090, 0x00402092, 0x00402400, - 0x00402402, 0x00402410, 0x00402412, 0x00402480, 0x00402482, 0x00402490, 0x00402492, 0x00410000, - 0x00410002, 0x00410010, 0x00410012, 0x00410080, 0x00410082, 0x00410090, 0x00410092, 0x00410400, - 0x00410402, 0x00410410, 0x00410412, 0x00410480, 0x00410482, 0x00410490, 0x00410492, 0x00412000, - 0x00412002, 0x00412010, 0x00412012, 0x00412080, 0x00412082, 0x00412090, 0x00412092, 0x00412400, - 0x00412402, 0x00412410, 0x00412412, 0x00412480, 0x00412482, 0x00412490, 0x00412492, 0x00480000, - 0x00480002, 0x00480010, 0x00480012, 0x00480080, 0x00480082, 0x00480090, 0x00480092, 0x00480400, - 0x00480402, 0x00480410, 0x00480412, 0x00480480, 0x00480482, 0x00480490, 0x00480492, 0x00482000, - 0x00482002, 0x00482010, 0x00482012, 0x00482080, 0x00482082, 0x00482090, 0x00482092, 0x00482400, - 0x00482402, 0x00482410, 0x00482412, 0x00482480, 0x00482482, 0x00482490, 0x00482492, 0x00490000, - 0x00490002, 0x00490010, 0x00490012, 0x00490080, 0x00490082, 0x00490090, 0x00490092, 0x00490400, - 0x00490402, 0x00490410, 0x00490412, 0x00490480, 0x00490482, 0x00490490, 0x00490492, 0x00492000, - 0x00492002, 0x00492010, 0x00492012, 0x00492080, 0x00492082, 0x00492090, 0x00492092, 0x00492400, - 0x00492402, 0x00492410, 0x00492412, 0x00492480, 0x00492482, 0x00492490, 0x00492492 + static const uint_fast64_t Morton3D_encode_y_256_64[256] = { + 0x0000000000000000, 0x0000000000000002, 0x0000000000000010, 0x0000000000000012, 0x0000000000000080, 0x0000000000000082, 0x0000000000000090, 0x0000000000000092, + 0x0000000000000400, 0x0000000000000402, 0x0000000000000410, 0x0000000000000412, 0x0000000000000480, 0x0000000000000482, 0x0000000000000490, 0x0000000000000492, + 0x0000000000002000, 0x0000000000002002, 0x0000000000002010, 0x0000000000002012, 0x0000000000002080, 0x0000000000002082, 0x0000000000002090, 0x0000000000002092, + 0x0000000000002400, 0x0000000000002402, 0x0000000000002410, 0x0000000000002412, 0x0000000000002480, 0x0000000000002482, 0x0000000000002490, 0x0000000000002492, + 0x0000000000010000, 0x0000000000010002, 0x0000000000010010, 0x0000000000010012, 0x0000000000010080, 0x0000000000010082, 0x0000000000010090, 0x0000000000010092, + 0x0000000000010400, 0x0000000000010402, 0x0000000000010410, 0x0000000000010412, 0x0000000000010480, 0x0000000000010482, 0x0000000000010490, 0x0000000000010492, + 0x0000000000012000, 0x0000000000012002, 0x0000000000012010, 0x0000000000012012, 0x0000000000012080, 0x0000000000012082, 0x0000000000012090, 0x0000000000012092, + 0x0000000000012400, 0x0000000000012402, 0x0000000000012410, 0x0000000000012412, 0x0000000000012480, 0x0000000000012482, 0x0000000000012490, 0x0000000000012492, + 0x0000000000080000, 0x0000000000080002, 0x0000000000080010, 0x0000000000080012, 0x0000000000080080, 0x0000000000080082, 0x0000000000080090, 0x0000000000080092, + 0x0000000000080400, 0x0000000000080402, 0x0000000000080410, 0x0000000000080412, 0x0000000000080480, 0x0000000000080482, 0x0000000000080490, 0x0000000000080492, + 0x0000000000082000, 0x0000000000082002, 0x0000000000082010, 0x0000000000082012, 0x0000000000082080, 0x0000000000082082, 0x0000000000082090, 0x0000000000082092, + 0x0000000000082400, 0x0000000000082402, 0x0000000000082410, 0x0000000000082412, 0x0000000000082480, 0x0000000000082482, 0x0000000000082490, 0x0000000000082492, + 0x0000000000090000, 0x0000000000090002, 0x0000000000090010, 0x0000000000090012, 0x0000000000090080, 0x0000000000090082, 0x0000000000090090, 0x0000000000090092, + 0x0000000000090400, 0x0000000000090402, 0x0000000000090410, 0x0000000000090412, 0x0000000000090480, 0x0000000000090482, 0x0000000000090490, 0x0000000000090492, + 0x0000000000092000, 0x0000000000092002, 0x0000000000092010, 0x0000000000092012, 0x0000000000092080, 0x0000000000092082, 0x0000000000092090, 0x0000000000092092, + 0x0000000000092400, 0x0000000000092402, 0x0000000000092410, 0x0000000000092412, 0x0000000000092480, 0x0000000000092482, 0x0000000000092490, 0x0000000000092492, + 0x0000000000400000, 0x0000000000400002, 0x0000000000400010, 0x0000000000400012, 0x0000000000400080, 0x0000000000400082, 0x0000000000400090, 0x0000000000400092, + 0x0000000000400400, 0x0000000000400402, 0x0000000000400410, 0x0000000000400412, 0x0000000000400480, 0x0000000000400482, 0x0000000000400490, 0x0000000000400492, + 0x0000000000402000, 0x0000000000402002, 0x0000000000402010, 0x0000000000402012, 0x0000000000402080, 0x0000000000402082, 0x0000000000402090, 0x0000000000402092, + 0x0000000000402400, 0x0000000000402402, 0x0000000000402410, 0x0000000000402412, 0x0000000000402480, 0x0000000000402482, 0x0000000000402490, 0x0000000000402492, + 0x0000000000410000, 0x0000000000410002, 0x0000000000410010, 0x0000000000410012, 0x0000000000410080, 0x0000000000410082, 0x0000000000410090, 0x0000000000410092, + 0x0000000000410400, 0x0000000000410402, 0x0000000000410410, 0x0000000000410412, 0x0000000000410480, 0x0000000000410482, 0x0000000000410490, 0x0000000000410492, + 0x0000000000412000, 0x0000000000412002, 0x0000000000412010, 0x0000000000412012, 0x0000000000412080, 0x0000000000412082, 0x0000000000412090, 0x0000000000412092, + 0x0000000000412400, 0x0000000000412402, 0x0000000000412410, 0x0000000000412412, 0x0000000000412480, 0x0000000000412482, 0x0000000000412490, 0x0000000000412492, + 0x0000000000480000, 0x0000000000480002, 0x0000000000480010, 0x0000000000480012, 0x0000000000480080, 0x0000000000480082, 0x0000000000480090, 0x0000000000480092, + 0x0000000000480400, 0x0000000000480402, 0x0000000000480410, 0x0000000000480412, 0x0000000000480480, 0x0000000000480482, 0x0000000000480490, 0x0000000000480492, + 0x0000000000482000, 0x0000000000482002, 0x0000000000482010, 0x0000000000482012, 0x0000000000482080, 0x0000000000482082, 0x0000000000482090, 0x0000000000482092, + 0x0000000000482400, 0x0000000000482402, 0x0000000000482410, 0x0000000000482412, 0x0000000000482480, 0x0000000000482482, 0x0000000000482490, 0x0000000000482492, + 0x0000000000490000, 0x0000000000490002, 0x0000000000490010, 0x0000000000490012, 0x0000000000490080, 0x0000000000490082, 0x0000000000490090, 0x0000000000490092, + 0x0000000000490400, 0x0000000000490402, 0x0000000000490410, 0x0000000000490412, 0x0000000000490480, 0x0000000000490482, 0x0000000000490490, 0x0000000000490492, + 0x0000000000492000, 0x0000000000492002, 0x0000000000492010, 0x0000000000492012, 0x0000000000492080, 0x0000000000492082, 0x0000000000492090, 0x0000000000492092, + 0x0000000000492400, 0x0000000000492402, 0x0000000000492410, 0x0000000000492412, 0x0000000000492480, 0x0000000000492482, 0x0000000000492490, 0x0000000000492492 + }; - // LUT for Morton3D encode Z - static const uint_fast32_t Morton3D_encode_z_256[256] = { - 0x00000000, - 0x00000004, 0x00000020, 0x00000024, 0x00000100, 0x00000104, 0x00000120, 0x00000124, 0x00000800, - 0x00000804, 0x00000820, 0x00000824, 0x00000900, 0x00000904, 0x00000920, 0x00000924, 0x00004000, - 0x00004004, 0x00004020, 0x00004024, 0x00004100, 0x00004104, 0x00004120, 0x00004124, 0x00004800, - 0x00004804, 0x00004820, 0x00004824, 0x00004900, 0x00004904, 0x00004920, 0x00004924, 0x00020000, - 0x00020004, 0x00020020, 0x00020024, 0x00020100, 0x00020104, 0x00020120, 0x00020124, 0x00020800, - 0x00020804, 0x00020820, 0x00020824, 0x00020900, 0x00020904, 0x00020920, 0x00020924, 0x00024000, - 0x00024004, 0x00024020, 0x00024024, 0x00024100, 0x00024104, 0x00024120, 0x00024124, 0x00024800, - 0x00024804, 0x00024820, 0x00024824, 0x00024900, 0x00024904, 0x00024920, 0x00024924, 0x00100000, - 0x00100004, 0x00100020, 0x00100024, 0x00100100, 0x00100104, 0x00100120, 0x00100124, 0x00100800, - 0x00100804, 0x00100820, 0x00100824, 0x00100900, 0x00100904, 0x00100920, 0x00100924, 0x00104000, - 0x00104004, 0x00104020, 0x00104024, 0x00104100, 0x00104104, 0x00104120, 0x00104124, 0x00104800, - 0x00104804, 0x00104820, 0x00104824, 0x00104900, 0x00104904, 0x00104920, 0x00104924, 0x00120000, - 0x00120004, 0x00120020, 0x00120024, 0x00120100, 0x00120104, 0x00120120, 0x00120124, 0x00120800, - 0x00120804, 0x00120820, 0x00120824, 0x00120900, 0x00120904, 0x00120920, 0x00120924, 0x00124000, - 0x00124004, 0x00124020, 0x00124024, 0x00124100, 0x00124104, 0x00124120, 0x00124124, 0x00124800, - 0x00124804, 0x00124820, 0x00124824, 0x00124900, 0x00124904, 0x00124920, 0x00124924, 0x00800000, - 0x00800004, 0x00800020, 0x00800024, 0x00800100, 0x00800104, 0x00800120, 0x00800124, 0x00800800, - 0x00800804, 0x00800820, 0x00800824, 0x00800900, 0x00800904, 0x00800920, 0x00800924, 0x00804000, - 0x00804004, 0x00804020, 0x00804024, 0x00804100, 0x00804104, 0x00804120, 0x00804124, 0x00804800, - 0x00804804, 0x00804820, 0x00804824, 0x00804900, 0x00804904, 0x00804920, 0x00804924, 0x00820000, - 0x00820004, 0x00820020, 0x00820024, 0x00820100, 0x00820104, 0x00820120, 0x00820124, 0x00820800, - 0x00820804, 0x00820820, 0x00820824, 0x00820900, 0x00820904, 0x00820920, 0x00820924, 0x00824000, - 0x00824004, 0x00824020, 0x00824024, 0x00824100, 0x00824104, 0x00824120, 0x00824124, 0x00824800, - 0x00824804, 0x00824820, 0x00824824, 0x00824900, 0x00824904, 0x00824920, 0x00824924, 0x00900000, - 0x00900004, 0x00900020, 0x00900024, 0x00900100, 0x00900104, 0x00900120, 0x00900124, 0x00900800, - 0x00900804, 0x00900820, 0x00900824, 0x00900900, 0x00900904, 0x00900920, 0x00900924, 0x00904000, - 0x00904004, 0x00904020, 0x00904024, 0x00904100, 0x00904104, 0x00904120, 0x00904124, 0x00904800, - 0x00904804, 0x00904820, 0x00904824, 0x00904900, 0x00904904, 0x00904920, 0x00904924, 0x00920000, - 0x00920004, 0x00920020, 0x00920024, 0x00920100, 0x00920104, 0x00920120, 0x00920124, 0x00920800, - 0x00920804, 0x00920820, 0x00920824, 0x00920900, 0x00920904, 0x00920920, 0x00920924, 0x00924000, - 0x00924004, 0x00924020, 0x00924024, 0x00924100, 0x00924104, 0x00924120, 0x00924124, 0x00924800, - 0x00924804, 0x00924820, 0x00924824, 0x00924900, 0x00924904, 0x00924920, 0x00924924 + static const uint_fast64_t Morton3D_encode_z_256_64[256] = { + 0x0000000000000000, 0x0000000000000004, 0x0000000000000020, 0x0000000000000024, 0x0000000000000100, 0x0000000000000104, 0x0000000000000120, 0x0000000000000124, + 0x0000000000000800, 0x0000000000000804, 0x0000000000000820, 0x0000000000000824, 0x0000000000000900, 0x0000000000000904, 0x0000000000000920, 0x0000000000000924, + 0x0000000000004000, 0x0000000000004004, 0x0000000000004020, 0x0000000000004024, 0x0000000000004100, 0x0000000000004104, 0x0000000000004120, 0x0000000000004124, + 0x0000000000004800, 0x0000000000004804, 0x0000000000004820, 0x0000000000004824, 0x0000000000004900, 0x0000000000004904, 0x0000000000004920, 0x0000000000004924, + 0x0000000000020000, 0x0000000000020004, 0x0000000000020020, 0x0000000000020024, 0x0000000000020100, 0x0000000000020104, 0x0000000000020120, 0x0000000000020124, + 0x0000000000020800, 0x0000000000020804, 0x0000000000020820, 0x0000000000020824, 0x0000000000020900, 0x0000000000020904, 0x0000000000020920, 0x0000000000020924, + 0x0000000000024000, 0x0000000000024004, 0x0000000000024020, 0x0000000000024024, 0x0000000000024100, 0x0000000000024104, 0x0000000000024120, 0x0000000000024124, + 0x0000000000024800, 0x0000000000024804, 0x0000000000024820, 0x0000000000024824, 0x0000000000024900, 0x0000000000024904, 0x0000000000024920, 0x0000000000024924, + 0x0000000000100000, 0x0000000000100004, 0x0000000000100020, 0x0000000000100024, 0x0000000000100100, 0x0000000000100104, 0x0000000000100120, 0x0000000000100124, + 0x0000000000100800, 0x0000000000100804, 0x0000000000100820, 0x0000000000100824, 0x0000000000100900, 0x0000000000100904, 0x0000000000100920, 0x0000000000100924, + 0x0000000000104000, 0x0000000000104004, 0x0000000000104020, 0x0000000000104024, 0x0000000000104100, 0x0000000000104104, 0x0000000000104120, 0x0000000000104124, + 0x0000000000104800, 0x0000000000104804, 0x0000000000104820, 0x0000000000104824, 0x0000000000104900, 0x0000000000104904, 0x0000000000104920, 0x0000000000104924, + 0x0000000000120000, 0x0000000000120004, 0x0000000000120020, 0x0000000000120024, 0x0000000000120100, 0x0000000000120104, 0x0000000000120120, 0x0000000000120124, + 0x0000000000120800, 0x0000000000120804, 0x0000000000120820, 0x0000000000120824, 0x0000000000120900, 0x0000000000120904, 0x0000000000120920, 0x0000000000120924, + 0x0000000000124000, 0x0000000000124004, 0x0000000000124020, 0x0000000000124024, 0x0000000000124100, 0x0000000000124104, 0x0000000000124120, 0x0000000000124124, + 0x0000000000124800, 0x0000000000124804, 0x0000000000124820, 0x0000000000124824, 0x0000000000124900, 0x0000000000124904, 0x0000000000124920, 0x0000000000124924, + 0x0000000000800000, 0x0000000000800004, 0x0000000000800020, 0x0000000000800024, 0x0000000000800100, 0x0000000000800104, 0x0000000000800120, 0x0000000000800124, + 0x0000000000800800, 0x0000000000800804, 0x0000000000800820, 0x0000000000800824, 0x0000000000800900, 0x0000000000800904, 0x0000000000800920, 0x0000000000800924, + 0x0000000000804000, 0x0000000000804004, 0x0000000000804020, 0x0000000000804024, 0x0000000000804100, 0x0000000000804104, 0x0000000000804120, 0x0000000000804124, + 0x0000000000804800, 0x0000000000804804, 0x0000000000804820, 0x0000000000804824, 0x0000000000804900, 0x0000000000804904, 0x0000000000804920, 0x0000000000804924, + 0x0000000000820000, 0x0000000000820004, 0x0000000000820020, 0x0000000000820024, 0x0000000000820100, 0x0000000000820104, 0x0000000000820120, 0x0000000000820124, + 0x0000000000820800, 0x0000000000820804, 0x0000000000820820, 0x0000000000820824, 0x0000000000820900, 0x0000000000820904, 0x0000000000820920, 0x0000000000820924, + 0x0000000000824000, 0x0000000000824004, 0x0000000000824020, 0x0000000000824024, 0x0000000000824100, 0x0000000000824104, 0x0000000000824120, 0x0000000000824124, + 0x0000000000824800, 0x0000000000824804, 0x0000000000824820, 0x0000000000824824, 0x0000000000824900, 0x0000000000824904, 0x0000000000824920, 0x0000000000824924, + 0x0000000000900000, 0x0000000000900004, 0x0000000000900020, 0x0000000000900024, 0x0000000000900100, 0x0000000000900104, 0x0000000000900120, 0x0000000000900124, + 0x0000000000900800, 0x0000000000900804, 0x0000000000900820, 0x0000000000900824, 0x0000000000900900, 0x0000000000900904, 0x0000000000900920, 0x0000000000900924, + 0x0000000000904000, 0x0000000000904004, 0x0000000000904020, 0x0000000000904024, 0x0000000000904100, 0x0000000000904104, 0x0000000000904120, 0x0000000000904124, + 0x0000000000904800, 0x0000000000904804, 0x0000000000904820, 0x0000000000904824, 0x0000000000904900, 0x0000000000904904, 0x0000000000904920, 0x0000000000904924, + 0x0000000000920000, 0x0000000000920004, 0x0000000000920020, 0x0000000000920024, 0x0000000000920100, 0x0000000000920104, 0x0000000000920120, 0x0000000000920124, + 0x0000000000920800, 0x0000000000920804, 0x0000000000920820, 0x0000000000920824, 0x0000000000920900, 0x0000000000920904, 0x0000000000920920, 0x0000000000920924, + 0x0000000000924000, 0x0000000000924004, 0x0000000000924020, 0x0000000000924024, 0x0000000000924100, 0x0000000000924104, 0x0000000000924120, 0x0000000000924124, + 0x0000000000924800, 0x0000000000924804, 0x0000000000924820, 0x0000000000924824, 0x0000000000924900, 0x0000000000924904, 0x0000000000924920, 0x0000000000924924 + }; - // LUT for Morton3D decode X - static const uint_fast8_t Morton3D_decode_x_512[512] = { + // 3D Decode preshifted LUTs (512 entries) + static const uint_fast8_t Morton3D_decode_preshifted_x_512_gen[512] = { 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, @@ -149,10 +256,10 @@ namespace libmorton { 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7 + }; - // LUT for Morton3D decode Y - static const uint_fast8_t Morton3D_decode_y_512[512] = { + static const uint_fast8_t Morton3D_decode_preshifted_y_512_gen[512] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, @@ -185,10 +292,10 @@ namespace libmorton { 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7 + }; - // LUT for Morton3D decode Z - static const uint_fast8_t Morton3D_decode_z_512[512] = { + static const uint_fast8_t Morton3D_decode_preshifted_z_512_gen[512] = { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, @@ -221,5 +328,116 @@ namespace libmorton { 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 7 + }; + + // 3D Decode LUTs (512 entries) + static const uint_fast8_t Morton3D_decode_x_512_gen[512] = { + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7 + + }; + + static const uint_fast8_t Morton3D_decode_y_512_gen[512] = { + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7 + + }; + + static const uint_fast8_t Morton3D_decode_z_512_gen[512] = { + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, + 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7 + + }; + } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e784254..0a63f5f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -62,4 +62,31 @@ target_link_libraries(libmorton-test-zen2 PRIVATE libmorton::libmorton ) -#add_test(libmorton-test-zen2 libmorton-test-zen2) \ No newline at end of file +#add_test(libmorton-test-zen2 libmorton-test-zen2) + +add_executable(generate_morton2D_LUTs + "generate_morton2D_LUTs.cpp" +) +target_compile_options(generate_morton2D_LUTs + PRIVATE + $<$,$>: # GCC and clang + -march=znver2 -Wall -Wextra -Wpedantic> + ) +target_link_libraries(generate_morton2D_LUTs + PRIVATE + libmorton::libmorton + ) + +add_executable(generate_morton3D_LUTs + "generate_morton3D_LUTs.cpp" +) + +target_compile_options(generate_morton3D_LUTs + PRIVATE + $<$,$>: # GCC and clang + -march=znver2 -Wall -Wextra -Wpedantic> + ) +target_link_libraries(generate_morton3D_LUTs + PRIVATE + libmorton::libmorton + ) \ No newline at end of file diff --git a/test/generate_morton2D_LUTs.cpp b/test/generate_morton2D_LUTs.cpp new file mode 100644 index 0000000..453866d --- /dev/null +++ b/test/generate_morton2D_LUTs.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +#include +#include "morton_LUT_generators.h" + +using namespace libmorton; + +template +void print_hex_array(const char* name, const T* arr, size_t n) { + unsigned int width = (sizeof(T) <= 4) ? 8 : 16; + std::cout << "static const "; + if (sizeof(T) <= 4) std::cout << "uint_fast32_t "; else std::cout << "uint_fast64_t "; + std::cout << name << "[" << n << "] = {\n"; + for (size_t i = 0; i < n; ++i) { + if (i % 8 == 0) std::cout << "\t"; + std::cout << "0x" << std::hex << std::setfill('0') << std::setw(width) << (unsigned long long)arr[i]; + if (i + 1 < n) std::cout << ", "; + if ((i + 1) % 8 == 0) std::cout << "\n"; + } + std::cout << std::dec << "\n};\n\n"; +} + +void print_decode_array(const char* name, const uint_fast8_t* arr, size_t n) { + std::cout << "static const uint_fast8_t " << name << "[" << n << "] = {\n"; + for (size_t i = 0; i < n; ++i) { + if (i % 16 == 0) std::cout << "\t"; + std::cout << (unsigned int)arr[i]; + if (i + 1 < n) std::cout << ", "; + if ((i + 1) % 16 == 0) std::cout << "\n"; + } + std::cout << "\n};\n\n"; +} + +int main() { + const size_t bits = 8; // 256 entries + const size_t total = 1 << bits; + + // 16-bit encode tables used in the project are uint_fast16_t for 2D + uint_fast32_t* x_enc_32 = (uint_fast32_t*)std::malloc(total * sizeof(uint_fast32_t)); + uint_fast32_t* y_enc_32 = (uint_fast32_t*)std::malloc(total * sizeof(uint_fast32_t)); + for (uint_fast32_t i = 0; i < total; ++i) { + x_enc_32[i] = (uint_fast32_t)m2D_e_magicbits(i, 0); + y_enc_32[i] = (uint_fast32_t)m2D_e_magicbits(0, i); + } + + uint_fast64_t* x_enc_64 = (uint_fast64_t*)std::malloc(total * sizeof(uint_fast64_t)); + uint_fast64_t* y_enc_64 = (uint_fast64_t*)std::malloc(total * sizeof(uint_fast64_t)); + for (uint_fast64_t i = 0; i < total; ++i) { + x_enc_64[i] = (uint_fast64_t)m2D_e_magicbits(i, 0); + y_enc_64[i] = (uint_fast64_t)m2D_e_magicbits(0, i); + } + + // decode tables for 2D + const size_t dtotal = 256; + uint_fast8_t* dx = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + uint_fast8_t* dy = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + for (size_t i = 0; i < dtotal; ++i) { + dx[i] = (uint_fast8_t)morton2D_GetSecondBits(i); + dy[i] = (uint_fast8_t)morton2D_GetSecondBits(i); + } + + uint_fast8_t* preshifted_dx = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + uint_fast8_t* preshifted_dy = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + for (size_t i = 0; i < dtotal; ++i) { + preshifted_dx[i] = (uint_fast8_t)morton2D_GetSecondBits(i); + preshifted_dy[i] = (uint_fast8_t)morton2D_GetSecondBits(i >> 1); + } + + std::cout << "// preshifted 2D Encode LUTs (32-bit)" << std::endl; + print_hex_array("Morton2D_encode_x_256_32", x_enc_32, total); + print_hex_array("Morton2D_encode_y_256_32", y_enc_32, total); + + std::cout << "// preshifted 2D Encode LUTs (64-bit)" << std::endl; + print_hex_array("Morton2D_encode_x_256_64", x_enc_64, total); + print_hex_array("Morton2D_encode_y_256_64", y_enc_64, total); + + std::cout << "// preshifted 2D Decode LUTs (256 entries)" << std::endl; + print_decode_array("Morton2D_decode_preshifted_x_256", preshifted_dx, dtotal); + print_decode_array("Morton2D_decode_preshifted_y_256", preshifted_dy, dtotal); + + std::cout << "// 2D Decode LUTs (256 entries)" << std::endl; + print_decode_array("Morton2D_decode_x_256", dx, dtotal); + print_decode_array("Morton2D_decode_y_256", dy, dtotal); + + return 0; +} diff --git a/test/generate_morton3D_LUTs.cpp b/test/generate_morton3D_LUTs.cpp new file mode 100644 index 0000000..0426450 --- /dev/null +++ b/test/generate_morton3D_LUTs.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#include +#include "morton_LUT_generators.h" + +using namespace libmorton; + +template +void print_hex_array(const char* name, const T* arr, size_t n) { + unsigned int width = (sizeof(T) <= 4) ? 8 : 16; + std::cout << "static const "; + if (sizeof(T) <= 4) std::cout << "uint_fast32_t "; else std::cout << "uint_fast64_t "; + std::cout << name << "[" << n << "] = {\n"; + for (size_t i = 0; i < n; ++i) { + if (i % 8 == 0) std::cout << "\t"; + std::cout << "0x" << std::hex << std::setfill('0') << std::setw(width) << (unsigned long long)arr[i]; + if (i + 1 < n) std::cout << ", "; + if ((i + 1) % 8 == 0) std::cout << "\n"; + } + std::cout << std::dec << "\n};\n\n"; +} + +void print_decode_array(const char* name, const uint_fast8_t* arr, size_t n) { + std::cout << "static const uint_fast8_t " << name << "[" << n << "] = {\n"; + for (size_t i = 0; i < n; ++i) { + if (i % 16 == 0) std::cout << "\t"; + std::cout << (unsigned int)arr[i]; + if (i + 1 < n) std::cout << ", "; + if ((i + 1) % 16 == 0) std::cout << "\n"; + } + std::cout << "\n};\n\n"; +} + +int main() { + const size_t bits = 8; // generate tables for 8-bit chunks => 256 entries + const size_t total = 1 << bits; + + // 32-bit encode tables + uint_fast32_t* x32 = (uint_fast32_t*)std::malloc(total * sizeof(uint_fast32_t)); + uint_fast32_t* y32 = (uint_fast32_t*)std::malloc(total * sizeof(uint_fast32_t)); + uint_fast32_t* z32 = (uint_fast32_t*)std::malloc(total * sizeof(uint_fast32_t)); + for (uint_fast32_t i = 0; i < total; ++i) { + x32[i] = (uint_fast32_t)m3D_e_magicbits(i, 0, 0); + y32[i] = (uint_fast32_t)m3D_e_magicbits(0, i, 0); + z32[i] = (uint_fast32_t)m3D_e_magicbits(0, 0, i); + } + + // 64-bit encode tables + uint_fast64_t* x64 = (uint_fast64_t*)std::malloc(total * sizeof(uint_fast64_t)); + uint_fast64_t* y64 = (uint_fast64_t*)std::malloc(total * sizeof(uint_fast64_t)); + uint_fast64_t* z64 = (uint_fast64_t*)std::malloc(total * sizeof(uint_fast64_t)); + for (uint_fast32_t i = 0; i < total; ++i) { + x64[i] = (uint_fast64_t)m3D_e_magicbits(i, 0, 0); + y64[i] = (uint_fast64_t)m3D_e_magicbits(0, i, 0); + z64[i] = (uint_fast64_t)m3D_e_magicbits(0, 0, i); + } + + // decode tables (512 entries) + const size_t dtotal = 512; + uint_fast8_t* dx = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + uint_fast8_t* dy = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + uint_fast8_t* dz = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + // Generate decode tables without pre-shifting (all use the same 9-bit window) + // This produces raw 3-bit values for each 9-bit pattern; callers should + // apply the runtime 3*i shift when assembling coordinates. + for (size_t i = 0; i < dtotal; ++i) { + dx[i] = (uint_fast8_t)morton3D_GetThirdBits(i); + dy[i] = (uint_fast8_t)morton3D_GetThirdBits(i); + dz[i] = (uint_fast8_t)morton3D_GetThirdBits(i); + } + + uint_fast8_t* preshifted_dx = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + uint_fast8_t* preshifted_dy = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + uint_fast8_t* preshifted_dz = (uint_fast8_t*)std::malloc(dtotal * sizeof(uint_fast8_t)); + // Generate decode tables with pre-shifting (all use the same 9-bit window) + // This produces raw 3-bit values for each 9-bit pattern; callers should + // apply the runtime 3*i shift when assembling coordinates. + for (size_t i = 0; i < dtotal; ++i) { + preshifted_dx[i] = (uint_fast8_t)morton3D_GetThirdBits(i); + preshifted_dy[i] = (uint_fast8_t)morton3D_GetThirdBits(i >> 1); + preshifted_dz[i] = (uint_fast8_t)morton3D_GetThirdBits(i >> 2); + } + + // print results + std::cout << "// 3D Encode LUTs (32-bit)" << std::endl; + print_hex_array("Morton3D_encode_x_256_32", x32, total); + print_hex_array("Morton3D_encode_y_256_32", y32, total); + print_hex_array("Morton3D_encode_z_256_32", z32, total); + + std::cout << "// 3D Encode LUTs (64-bit)" << std::endl; + print_hex_array("Morton3D_encode_x_256_64", x64, total); + print_hex_array("Morton3D_encode_y_256_64", y64, total); + print_hex_array("Morton3D_encode_z_256_64", z64, total); + + std::cout << "// 3D Decode preshifted LUTs (512 entries)" << std::endl; + print_decode_array("Morton3D_decode_preshifted_x_512_gen", preshifted_dx, dtotal); + print_decode_array("Morton3D_decode_preshifted_y_512_gen", preshifted_dy, dtotal); + print_decode_array("Morton3D_decode_preshifted_z_512_gen", preshifted_dz, dtotal); + + std::cout << "// 3D Decode LUTs (512 entries)" << std::endl; + print_decode_array("Morton3D_decode_x_512_gen", dx, dtotal); + print_decode_array("Morton3D_decode_y_512_gen", dy, dtotal); + print_decode_array("Morton3D_decode_z_512_gen", dz, dtotal); + + return 0; +} diff --git a/test/libmorton_test.cpp b/test/libmorton_test.cpp index 156e66d..a93c2c9 100644 --- a/test/libmorton_test.cpp +++ b/test/libmorton_test.cpp @@ -164,10 +164,10 @@ void registerFunctions() { } void printFunctionStats() { - printf("Registered 3D encoders: %ull (64-bit) %i (32-bit) \n", f3D_64_encode.size(), f3D_32_encode.size()); - printf("Registered 3D decoders: %ull (64-bit) %i (32-bit) \n", f3D_64_decode.size(), f3D_32_decode.size()); - printf("Registered 2D encoders: %ull (64-bit) %i (32-bit) \n", f2D_64_encode.size(), f2D_32_encode.size()); - printf("Registered 2D decoders: %ull (64-bit) %i (32-bit) \n", f2D_64_decode.size(), f2D_32_decode.size()); + printf("Registered 3D encoders: %zu (64-bit) %zu (32-bit) \n", f3D_64_encode.size(), f3D_32_encode.size()); + printf("Registered 3D decoders: %zu (64-bit) %zu (32-bit) \n", f3D_64_decode.size(), f3D_32_decode.size()); + printf("Registered 2D encoders: %zu (64-bit) %zu (32-bit) \n", f2D_64_encode.size(), f2D_32_encode.size()); + printf("Registered 2D decoders: %zu (64-bit) %zu (32-bit) \n", f2D_64_decode.size(), f2D_32_decode.size()); } int main(int argc, char *argv[]) {