Morton: Bit Interleaving in C/C++
github.com
github.com
1. https://www.forceflow.be/2013/10/07/morton-encodingdecoding-...
2. https://www.forceflow.be/2016/01/18/libmorton-a-library-for-...
3. https://github.com/Forceflow/libmorton
I used it to accelerate nearest neighbor detection for collision processing in particle-laden flow for modeling complicated domains in 3d (for biological fluids simulation). I was using it as a locality sensitive hashing to put particles near each other in the same bucket in an hash map. I came across the ideas of BIGMIN (big minimum) and LITMAX (little maximum) for range search in a morton encoded data that I found to be cool.
https://reversedns.space/ (a map of the Internet) - Morton curve is used as a visualization tool;
https://adsb.exposed/ (a visualizer of air traffic) - Morton curve is used as a database index;
Both projects are open-source, so you can find how exactly it is applied: https://github.com/ClickHouse/adsb.exposed/blob/main/setup.s...
Intel microarchitectures added fast ALU instructions (PDEP/PEXT) that can directly effect this as long ago as Haswell (2013) but AMD only very recently added comparable instruction implementations so portability of these instructions is an issue. Also, depending on the dimensionality and bit length of the code, there may be a few cases where the optimal shift/mask version will be about as fast without the portability concerns.
For all practical purposes, you had to write performance code like AMD did not support PDEP/PEXT.
If I remember, the main advantage is that you can use a sorted multimap, insert item by converting 2D coordinates to 1D with some function. Multimaps are already implemented and fast.
The result is that your data is packed, and "sorted" by 2D location, so when you query items in an area, it's supposed to be very fast because of cache friendliness, I think. The interesting trick is when you query a rectangle, you calculate 2 corner bounds, and use them to query the multimap.
Of course, this is a simple way to index 2D data, and R trees are still faster, but no engineers will enjoy implementing an R-tree. BSP or Kd-trees are also much harder to implement than a Z-order curve.
I am not good at those subjects, but I feel like a Z order curve is the "best" way to index 2D, since it's a very good trade-off between simplicity and performance, which is if one wants to write lean software, like for a video game for example. Feel free to correct me.
Although I think there are things around Z order curves that are still under patent.
E.g. if you have a 128x32 then you don't want to interleave the y bits once they are exhausted (only need 5 bits of y, but 7 bits of x to fully address this).
The posted implementation would produce
y6,x6,y5,x5,y4,x4,y3,x3,y2,x2,y1,x1,y0,x0
but really we want: x6,x5,y4,x4,y3,x3,y2,x2,y1,x1,y0,x0On the other hand, if you intend to store and compare compact codes of 12 bits you only need a few shift, OR and AND operations (or possibly dedicated fancy instructions) to knock out the known zero bits and place the significant digits contiguously.
See for example https://fgiesen.wordpress.com/2011/01/17/texture-tiling-and-... (search "Morton" in the page)
There are probably other use-cases that I'm unaware of.
If you don't interleave the bits and have large textures (think 4096 pixels wide) where each pixel is 4bytes big, that means there is a distance of 16kb between a pixel and the pixel below it.
This is super bad for caches (really important for the TLB in the MMU which is usually way smaller than data caches).
In GPU literature you'll see this called "tiling" (again like azornathogron said it's not always pure morton order), Intel document their tiling layout, here's an older layout doc:
I wrote a routine that was the fastest I could manage to encode/decode them, I wonder how it compares nowadays to this implementation. This was back when Ryzen CPUs still implemented PDEP in microcode, so lookup table and bit twiddling was much faster than PDEP.