Algorithm Search⌘K

Proofs: Morton encoding

These are the human proofs of Morton encoding, at full length.

The magic-mask stages spread and compact the bits of a coordinate full

This proof shows: correctness.

All words are 64-bit unsigned. For a word vv we write vpv_p for bit pp of vv. Let 0≤x<2320 \le x < 2^{32} with bits x0,…,x31x_0, \ldots, x_{31}. Number the stages of SPREAD by j=4,3,2,1,0j = 4, 3, 2, 1, 0, so that the stage jj computes v←(v∣(v≪2j))&Mjv \leftarrow (v \mathbin{|} (v \ll 2^j)) \mathbin{\&} M_j, where MjM_j is the 64-bit mask whose bit pp is 1 exactly when p mod 2j+1<2jp \bmod 2^{j+1} < 2^j. The masks of lines L1 to L5 are M4,M3,M2,M1,M0M_4, M_3, M_2, M_1, M_0: for example M4=0x0000FFFF0000FFFFM_4 = \mathtt{0x0000FFFF0000FFFF} and M0=0x5555555555555555M_0 = \mathtt{0x5555555555555555}.

Position map. For 0≤j≤50 \le j \le 5 and 0≤i<320 \le i < 32 let

pj(i)=i+2j⌊i/2j⌋.p_j(i) = i + 2^j \left\lfloor i / 2^j \right\rfloor .

Write i=q⋅2j+ri = q \cdot 2^j + r with 0≤r<2j0 \le r < 2^j; then pj(i)=q⋅2j+1+rp_j(i) = q \cdot 2^{j+1} + r. So pj(i) mod 2j+1=r<2jp_j(i) \bmod 2^{j+1} = r < 2^j, and pjp_j is injective, since qq and rr can be read back from pj(i)p_j(i). Also p5(i)=ip_5(i) = i for i<32i < 32, and p0(i)=2ip_0(i) = 2i.

Invariant. Let v(j)v^{(j)} be the word after the stage jj, and let v(5)=xv^{(5)} = x be the word before line L1. Then for each jj from 5 down to 0:

v(j)=∑i=031xi 2pj(i).v^{(j)} = \sum_{i=0}^{31} x_i \, 2^{p_j(i)} .

In words, bit ii of xx is at position pj(i)p_j(i), and every other bit of the word is 0.

Base. For j=5j = 5, p5(i)=ip_5(i) = i, so the claim is v(5)=xv^{(5)} = x.

Step. Assume the claim for j+1j + 1, with 0≤j≤40 \le j \le 4. Take a bit ii and write i=q⋅2j+1+h⋅2j+ri = q \cdot 2^{j+1} + h \cdot 2^j + r with h∈{0,1}h \in \{0, 1\} and 0≤r<2j0 \le r < 2^j. Then ⌊i/2j+1⌋=q\lfloor i / 2^{j+1} \rfloor = q, so by the claim for j+1j + 1 the bit xix_i is at position P=i+2j+1q=q⋅2j+2+h⋅2j+rP = i + 2^{j+1} q = q \cdot 2^{j+2} + h \cdot 2^j + r of v(j+1)v^{(j+1)}. All positions pj(i)p_j(i) and pj+1(i)p_{j+1}(i) are at most p0(31)=62p_0(31) = 62, so the kept copies below are inside the word; a copy that the shift moves past bit 63 is one that the mask would clear. The word u=v(j+1)∣(v(j+1)≪2j)u = v^{(j+1)} \mathbin{|} (v^{(j+1)} \ll 2^j) has a copy of xix_i at PP and at P+2jP + 2^j, and the AND with MjM_j keeps a position pp only when p mod 2j+1<2jp \bmod 2^{j+1} < 2^j.

  • If h=0h = 0, then P mod 2j+1=r<2jP \bmod 2^{j+1} = r < 2^j, so the copy at PP is kept, and (P+2j) mod 2j+1=r+2j≥2j(P + 2^j) \bmod 2^{j+1} = r + 2^j \ge 2^j, so the copy at P+2jP + 2^j is cleared. The kept position is q⋅2j+2+rq \cdot 2^{j+2} + r.
  • If h=1h = 1, then P mod 2j+1=2j+r≥2jP \bmod 2^{j+1} = 2^j + r \ge 2^j, so the copy at PP is cleared, and P+2j=q⋅2j+2+2j+1+rP + 2^j = q \cdot 2^{j+2} + 2^{j+1} + r has remainder r<2jr < 2^j modulo 2j+12^{j+1}, so it is kept.

In both cases the kept position is q⋅2j+2+h⋅2j+1+r=i+2j(2q+h)=i+2j⌊i/2j⌋=pj(i)q \cdot 2^{j+2} + h \cdot 2^{j+1} + r = i + 2^j (2q + h) = i + 2^j \lfloor i / 2^j \rfloor = p_j(i).

It remains to show that the OR does not merge two different bits, and that no other one-bits survive. Every one-bit of uu is a copy of some xix_i, at PP or at P+2jP + 2^j. Suppose that a position pp kept by the mask holds a copy of xix_i and a copy of xi′x_{i'}. By the case analysis, the kept copy of each bit is at pj(i)p_j(i) and at pj(i′)p_j(i') respectively, and the cleared copies are not kept; so pj(i)=p=pj(i′)p_j(i) = p = p_j(i'), and i=i′i = i' because pjp_j is injective. Hence position pj(i)p_j(i) of v(j)=u&Mjv^{(j)} = u \mathbin{\&} M_j holds exactly xix_i, and every position that is not of the form pj(i)p_j(i) is 0. This proves the claim for jj.

SPREAD. For j=0j = 0 the invariant gives SPREAD⁡(x)=∑ixi22i\operatorname{SPREAD}(x) = \sum_i x_i 2^{2i}. Line L7 then returns ∑ixi22i+∑iyi22i+1\sum_i x_i 2^{2i} + \sum_i y_i 2^{2i+1}, since the two terms have their ones at even and at odd positions and so the OR is a sum. This is Z(x,y)Z(x, y), and it is below 2642^{64}.

COMPACT. Number the stages of COMPACT by j=0,1,2,3,4j = 0, 1, 2, 3, 4, with shift 2j2^j and the mask Mj+1M_{j+1}, where M5=0x00000000FFFFFFFFM_5 = \mathtt{0x00000000FFFFFFFF} is the mask of the positions with p mod 64<32p \bmod 64 < 32. Let zz be a word whose odd bits are 0 after line D1, so z=∑ixi2p0(i)z = \sum_i x_i 2^{p_0(i)} for the bits xi=z2ix_i = z_{2i}. We claim that after the stage jj the word is ∑ixi2pj+1(i)\sum_i x_i 2^{p_{j+1}(i)}. Assume that before the stage the word is v=∑ixi2pj(i)v = \sum_i x_i 2^{p_j(i)}. Write i=q⋅2j+1+h⋅2j+ri = q \cdot 2^{j+1} + h \cdot 2^j + r as before; then pj(i)=q⋅2j+2+h⋅2j+1+rp_j(i) = q \cdot 2^{j+2} + h \cdot 2^{j+1} + r and pj+1(i)=q⋅2j+2+h⋅2j+rp_{j+1}(i) = q \cdot 2^{j+2} + h \cdot 2^j + r. The word v⊕(v≫2j)v \oplus (v \gg 2^j) has, at each position pp, the XOR of vpv_p and vp+2jv_{p + 2^j}. Take a position pp that Mj+1M_{j+1} keeps, so p=Q⋅2j+2+sp = Q \cdot 2^{j+2} + s with 0≤s<2j+10 \le s < 2^{j+1}. Write s=H⋅2j+Rs = H \cdot 2^j + R with H∈{0,1}H \in \{0, 1\} and 0≤R<2j0 \le R < 2^j. Every one-bit of vv is at a position whose remainder modulo 2j+12^{j+1} is below 2j2^j.

  • If H=0H = 0, then p+2jp + 2^j has remainder 2j+R≥2j2^j + R \ge 2^j modulo 2j+12^{j+1}, so vp+2j=0v_{p + 2^j} = 0, and the result at pp is vpv_p, which is xix_i for the ii with q=Qq = Q, h=0h = 0, r=Rr = R, if that ii is below 32, and 0 otherwise.
  • If H=1H = 1, then pp has remainder 2j+R≥2j2^j + R \ge 2^j modulo 2j+12^{j+1}, so vp=0v_p = 0, and p+2j=Q⋅2j+2+2j+1+Rp + 2^j = Q \cdot 2^{j+2} + 2^{j+1} + R, so the result is xix_i for q=Qq = Q, h=1h = 1, r=Rr = R, or 0 if that ii is not below 32.

In both cases position pp of the result holds xix_i for the unique ii with pj+1(i)=pp_{j+1}(i) = p, and the positions with no such ii hold 0. The positions that Mj+1M_{j+1} clears hold 0 by definition. This proves the claim. After the stage j=4j = 4 the word is ∑ixi2p5(i)=∑ixi2i\sum_i x_i 2^{p_5(i)} = \sum_i x_i 2^i, so COMPACT returns the even bits of zz, packed. Line D8 applies it to zz and to z≫1z \gg 1, which gives the xx bits and the yy bits of the code. Hence MORTON-DECODE inverts MORTON-ENCODE, and since both maps are between sets of 2642^{64} elements, encoding is a bijection. ■\blacksquare

Back to Morton encoding