rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 70219079ed1cdc9305f219b46257014fb63374e7
parent b97e5bba8c71261b6cb85479a0224b5b15161715
Author: vaplv <vaplv@free.fr>
Date:   Mon, 15 Feb 2021 12:28:10 +0100

Add and test the 2D morton encoding/decoding

Diffstat:
Msrc/morton.h | 39+++++++++++++++++++++++++++++++++++++++
Msrc/test_morton.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/src/morton.h b/src/morton.h @@ -18,6 +18,28 @@ #include "rsys.h" +static FINLINE uint32_t +morton2D_encode_u16(const uint16_t u16) +{ + uint32_t u32 = u16; + u32 = (u32 | (u32 << 8)) & 0x00FF00FF; + u32 = (u32 | (u32 << 4)) & 0X0F0F0F0F; + u32 = (u32 | (u32 << 2)) & 0x33333333; + u32 = (u32 | (u32 << 1)) & 0x55555555; + return u32; +} + +static FINLINE uint16_t +morton2D_decode_u16(const uint32_t u32) +{ + uint32_t x = u32 & 0x55555555; + x = (x | (x >> 1)) & 0x33333333; + x = (x | (x >> 2)) & 0x0F0F0F0F; + x = (x | (x >> 4)) & 0x00FF00FF; + x = (x | (x >> 8)) & 0x0000FFFF; + return (uint16_t)x; +} + static INLINE uint64_t morton3D_encode_u21(const uint32_t u21) { @@ -44,9 +66,26 @@ morton3D_decode_u21(const uint64_t u64) return (uint32_t)tmp; } +static INLINE uint32_t +morton_xy_encode_u16(const uint16_t xy[2]) +{ + ASSERT(xy); + return (morton2D_encode_u16(xy[0]) << 1) + | (morton2D_encode_u16(xy[1]) << 0); +} + +static INLINE void +morton_xy_decode_u16(const uint32_t code, uint16_t xy[2]) +{ + ASSERT(xy); + xy[0] = (uint16_t)morton2D_decode_u16(code >> 1); + xy[1] = (uint16_t)morton2D_decode_u16(code >> 0); +} + static INLINE uint64_t morton_xyz_encode_u21(const uint32_t xyz[3]) { + ASSERT(xyz); return (morton3D_encode_u21(xyz[0]) << 2) | (morton3D_encode_u21(xyz[1]) << 1) | (morton3D_encode_u21(xyz[2]) << 0); diff --git a/src/test_morton.c b/src/test_morton.c @@ -18,6 +18,12 @@ #include <stdlib.h> +static INLINE uint16_t +rand_u16() +{ + return (uint16_t)(rand() & (BIT(16)-1)); +} + static INLINE uint32_t rand_u21() { @@ -28,22 +34,74 @@ static INLINE uint64_t encode_u21(uint32_t u21) { uint64_t mcode = 0; + uint64_t i; + for(i = (uint64_t)round_up_pow2(u21); i != 0; i >>= 1) { + if(i <= (uint64_t)u21) { + mcode |= morton3D_encode_u21((uint32_t)i); + u21 -= (uint32_t)i; + } + } + return mcode; +} + +static INLINE uint32_t +encode_u16(uint32_t u16) +{ + uint32_t mcode = 0; uint32_t i; - for(i = (uint32_t)round_up_pow2(u21); i != 0; i >>= 1) { - if(i <= u21) { - mcode |= morton3D_encode_u21(i); - u21 -= i; + for(i = (uint32_t)round_up_pow2(u16); i != 0; i >>= 1) { + if(i <= (uint32_t)u16) { + mcode |= morton2D_encode_u16((uint16_t)i); + u16 -= (uint16_t)i; } } return mcode; } -int -main(int argc, char** argv) +static void +test_morton2D(void) +{ + int bit = 0; + int i = 0; + + FOR_EACH(bit, 0, 16) { + CHK(morton2D_encode_u16(BIT_U16(bit)) == BIT_U32(2*bit)); + CHK(morton2D_decode_u16(BIT_U32(2*bit)) == BIT_U16(bit)); + } + + FOR_EACH(i, 0, 10000) { + const uint16_t u16 = rand_u16(); + const uint32_t u32 = morton2D_encode_u16(u16); + CHK(u32 == encode_u16(u16)); + CHK(u16 == morton2D_decode_u16(u32)); + } + + FOR_EACH(i, 0, 10000) { + uint16_t xy[2]; + uint16_t xy2[2]; + uint32_t xy_mcode[2]; + uint32_t mcode; + + xy[0] = rand_u16(); + xy[1] = rand_u16(); + mcode = morton_xy_encode_u16(xy); + + xy_mcode[0] = morton2D_encode_u16(xy[0]); + xy_mcode[1] = morton2D_encode_u16(xy[1]); + CHK(mcode == ((xy_mcode[0]<<1) | (xy_mcode[1]<<0))); + + morton_xy_decode_u16(mcode, xy2); + CHK(xy[0] == xy2[0]); + CHK(xy[1] == xy2[1]); + } + +} + +static void +test_morton3D(void) { int bit = 0; int i = 0; - (void)argc, (void)argv; FOR_EACH(bit, 0, 21) { CHK(morton3D_encode_u21(BIT_U32(bit)) == BIT_U64(3*bit)); @@ -74,10 +132,17 @@ main(int argc, char** argv) CHK(mcode == ((xyz_mcode[0]<<2) | (xyz_mcode[1]<<1) | (xyz_mcode[2]<<0))); morton_xyz_decode_u21(mcode, xyz2); - CHK(xyz[0] = xyz2[0]); - CHK(xyz[1] = xyz2[1]); - CHK(xyz[2] = xyz2[2]); + CHK(xyz[0] == xyz2[0]); + CHK(xyz[1] == xyz2[1]); + CHK(xyz[2] == xyz2[2]); } +} +int +main(int argc, char** argv) +{ + (void)argc, (void)argv; + test_morton2D(); + test_morton3D(); return 0; }