Algorithm Search⌘K

Proofs: de Bruijn bit scan

These are the human proofs of de Bruijn bit scan, at full length.

The de Bruijn bit scan returns the index of the lowest 1-bit full

This proof shows: correctness.

Fix n≥1n \ge 1 and the word size w=2nw = 2^n. Words are integers in [0,2w)[0, 2^w), bit tt of a word aa is ⌊a/2t⌋ mod 2\lfloor a / 2^t \rfloor \bmod 2, and −a-a means (2w−a) mod 2w(2^w - a) \bmod 2^w. For x≠0x \ne 0 let ρ(x)\rho(x) be the least tt with bit tt of xx equal to 1.

Lemma 1 (isolation). For 0<x<2w0 < x < 2^w with k=ρ(x)k = \rho(x), x∧(−x)=2kx \wedge (-x) = 2^k.

Proof. Write x=h⋅2k+1+2kx = h \cdot 2^{k+1} + 2^k with 0≤h<2w−k−10 \le h < 2^{w-k-1}; this is possible because bits 00 to k−1k-1 of xx are 0 and bit kk is 1. Then x‾=(2w−1)−x\overline{x} = (2^w - 1) - x has bits 00 to k−1k - 1 equal to 1, bit kk equal to 0, and bits above kk equal to the complements of those of xx. Adding 1 to x‾\overline{x} turns its kk low 1-bits into 0-bits with a carry into bit kk, which becomes 1, and the carry stops there. So −x=x‾+1 mod 2w-x = \overline{x} + 1 \bmod 2^w has bits 00 to k−1k - 1 equal to 0, bit kk equal to 1, and each bit above kk the complement of the same bit of xx. In x∧(−x)x \wedge (-x) the bits below kk are 0, bit kk is 1, and each bit above kk is a∧a‾=0a \wedge \overline{a} = 0. So x∧(−x)=2kx \wedge (-x) = 2^k. □\square

Windows. For a word DD and 0≤k<w0 \le k < w, let wink(D)=((2kD) mod 2w)≫(w−n)\mathrm{win}_k(D) = ((2^k D) \bmod 2^w) \gg (w - n), an integer in [0,2n)[0, 2^n). Write d0d1…dw−1d_0 d_1 \dots d_{w-1} for the bits of DD read from the top, so djd_j is bit w−1−jw - 1 - j of DD. Extend the indices cyclically: dj=dj mod wd_j = d_{j \bmod w}.

Lemma 2 (window). For 0≤k<w0 \le k < w, the nn bits of wink(D)\mathrm{win}_k(D), from the top, are ck,ck+1,…,ck+n−1c_k, c_{k+1}, \dots, c_{k+n-1}, where cj=djc_j = d_j for j<wj < w and cj=0c_j = 0 for j≥wj \ge w.

Proof. Multiplying by 2k2^k moves bit tt of DD to bit t+kt + k, and the reduction modulo 2w2^w deletes the bits that reach position ww or more; positions 00 to k−1k - 1 become 0. The shift by w−nw - n keeps positions w−1w - 1 down to w−nw - n of the product, as the top nn bits of the result in the same order. Position w−1−mw - 1 - m of the product, for 0≤m<n0 \le m < n, holds bit w−1−m−kw - 1 - m - k of DD if w−1−m−k≥0w - 1 - m - k \ge 0, which is dk+md_{k+m}, and holds 0 otherwise, that is when k+m≥wk + m \ge w. So the bit at place mm from the top of wink(D)\mathrm{win}_k(D) is ck+mc_{k+m}. □\square

Lemma 3 (distinct windows). Let the cyclic sequence d0…dw−1d_0 \dots d_{w-1} be a binary de Bruijn sequence of order nn, that is, the ww cyclic windows (dk,dk+1,…,dk+n−1)(d_k, d_{k+1}, \dots, d_{k+n-1}) for 0≤k<w0 \le k < w are the 2n2^n binary words of length nn, each once. Suppose also d0=d1=⋯=dn−1=0d_0 = d_1 = \dots = d_{n-1} = 0. Then win0(D),…,winw−1(D)\mathrm{win}_0(D), \dots, \mathrm{win}_{w-1}(D) are pairwise distinct.

Proof. By Lemma 2, wink(D)\mathrm{win}_k(D) has bits ck,…,ck+n−1c_k, \dots, c_{k+n-1}. For an index j=k+mj = k + m with k<wk < w and m<nm < n, if j<wj < w then cj=djc_j = d_j, and if j≥wj \ge w then j−w<nj - w < n, so dj=dj−w=0=cjd_j = d_{j - w} = 0 = c_j by the hypothesis on the top nn bits. Hence cj=djc_j = d_j for every index used, and wink(D)\mathrm{win}_k(D) is the kk-th cyclic window of the de Bruijn sequence. These ww windows are pairwise distinct by definition. □\square

The hypothesis can always be met: a de Bruijn sequence contains the window 0n0^n once, and its rotation that starts there has nn leading zeros and is again a de Bruijn sequence.

Table. Under the condition of Lemma 3 the map k↦wink(D)k \mapsto \mathrm{win}_k(D) is injective from {0,…,w−1}\{0, \dots, w - 1\} into {0,…,2n−1}\{0, \dots, 2^n - 1\}, a set with 2n=w2^n = w elements, so it is a bijection. The table filled by T[wink(D)]←kT[\mathrm{win}_k(D)] \gets k for k=0,…,w−1k = 0, \dots, w - 1 therefore writes each entry exactly once and satisfies T[wink(D)]=kT[\mathrm{win}_k(D)] = k for every kk.

Theorem. Let DD and TT be as above and 0<x<2w0 < x < 2^w. Then DE-BRUIJN-SCAN(x)(x) returns ρ(x)\rho(x).

Proof. Let k=ρ(x)k = \rho(x). By Lemma 1, line L1 sets b=2kb = 2^k. Line L2 sets p=(2kD) mod 2wp = (2^k D) \bmod 2^w, and line L3 sets i=p≫(w−n)=wink(D)i = p \gg (w - n) = \mathrm{win}_k(D). Line L4 returns T[wink(D)]=kT[\mathrm{win}_k(D)] = k by the property of the table. □\square

Remark (zero). For x=0x = 0, x∧(−x)=0x \wedge (-x) = 0, so i=0i = 0 and the procedure returns T[0]=T[win0(D)]=0T[0] = T[\mathrm{win}_0(D)] = 0, which is ρ(1)\rho(1). The precondition x≠0x \ne 0 is needed.

Termination. The procedure has four lines and no loop, and the table is built by a loop of ww iterations, so both stop. ■\blacksquare

Back to de Bruijn bit scan