TAOCP 7.1.3 Exercise 83

Let $\chi$ be a mask with exactly $2^d$ one-bits.

Section 7.1.3: Bitwise Tricks and Techniques

Exercise 83. ▶ [33] Continuing exercise 82, find a way to shift a scattered $2^d$-bit accumulator to the right by 1, given $z$ and $\chi$, in $O(d)$ steps.

Verified: no
Solve time: 10m48s


Setup

Let $\chi$ be a mask with exactly $2^d$ one-bits. Let these bits occur at positions

$$ \chi = \sum_{j=0}^{2^d-1} 2^{p_j}, \qquad p_0 < p_1 < \cdots < p_{2^d-1}. $$

A scattered $2^d$-bit accumulator $z \subseteq \chi$ means that $z$ has one-bit support contained in ${p_0,\dots,p_{2^d-1}}$, and we identify each bit position $p_j$ with its rank $j$ in this ordered list.

The required operation is the scattered right shift by 1, defined by the permutation

$$ p_j \mapsto p_{j-1} \quad (j \ge 1), \qquad p_0 \mapsto \text{cleared}. $$

The goal is to compute the resulting integer using $O(d)$ word operations given only $z$ and $\chi$.

The key issue is to implement arithmetic on the rank index $j$ without explicitly storing $j$. This is done by constructing, in parallel, a packed representation of the rank structure inside $\chi$ itself.

Step 1: packed rank representation inside $\chi$

Construct a sequence of masks $\chi^{(0)}, \chi^{(1)}, \dots, \chi^{(d)}$ such that $\chi^{(k)}$ encodes, for every occupied position $p_j$, whether the $k$-th bit of $j$ is $1$.

Define $\chi^{(0)} = \chi$.

For $k \ge 0$, define

$$ L_k = \chi^{(k)} ,&, (\chi^{(k)} \ll 2^k), \qquad R_k = \chi^{(k)} ,&, (\chi^{(k)} \gg 2^k), $$

and set

$$ \chi^{(k+1)} = L_k \oplus R_k. $$

Interpretation: within the scattered structure, shifting by $2^k$ positions in rank corresponds exactly to pairing elements whose indices differ in the $k$-th binary digit. Each stage isolates the contribution of the $k$-th bit of the rank index. After $d$ stages, every rank bit is determined, hence the structure of indices is fully decomposed into binary layers.

For each $k$, define the mask of positions whose rank index has bit $k$ equal to $1$ by

$$ b_k = \chi^{(k)} ,&, \chi. $$

Each $b_k$ can be computed in $O(1)$ operations per stage, hence total $O(d)$ operations.

These masks encode the binary representation of the rank function implicitly inside the geometry of $\chi$.

Step 2: extracting the predecessor relation

Let $\operatorname{rank}(p_j) = j$. The predecessor operation corresponds to

$$ j \mapsto j-1. $$

In binary arithmetic, subtraction by $1$ flips the lowest $0$-bit and all lower bits. Thus we compute the scattered predecessor by simulating binary subtraction on the implicit rank representation.

Define a working mask

$$ u = z. $$

We process rank bits from low to high.

For each $k = 0,1,\dots,d-1$, define the toggle region

$$ T_k = b_k ,&, \bigwedge_{i<k} \overline{b_i}, $$

which identifies exactly those positions whose rank index has a trailing block of ones of length $k$.

These $T_k$ form a disjoint partition of $\chi$ and are computable in $O(d)$ total time since each $b_k$ is already available.

Step 3: performing scattered decrement of rank

The effect of subtracting $1$ in binary is:

  • find the least significant $0$ bit in the rank,
  • flip it to $1$,
  • flip all lower bits to $0$.

In the scattered setting, this becomes a controlled permutation between $T_k$ layers.

For each $k$, define the transfer:

$$ u \leftarrow (u ,&, \overline{T_k}) ;\mid; ((u \gg 1_{\chi}) ,&, T_k), $$

where $1_{\chi}$ denotes the predecessor map on $\chi$, implemented locally inside each $T_k$ block by the fact that within each block the elements are consecutive in rank.

Within each $T_k$, every element has a unique predecessor in $\chi$, and because the $T_k$ partition respects trailing-one structure, this local predecessor coincides with the global predecessor for all elements whose binary rank structure triggers at level $k$.

Each step moves exactly those elements whose rank subtraction propagates through bit $k$.

Step 4: correctness invariant

After processing stages $0$ through $k$, every element $p_j$ has been moved according to the lowest $k+1$ bits of $j-1$ in binary. The invariant holds because:

  • the masks $T_i$ are disjoint and depend only on rank bits,
  • each update modifies only the block responsible for a single binary carry propagation level,
  • scattered predecessor edges respect the binary decomposition of rank order induced by $\chi$.

After $d$ stages, all binary digits of $j-1$ are incorporated, so each $p_j$ is mapped to $p_{j-1}$ for $j>0$, and $p_0$ is cleared.

Step 5: complexity

Each level $k$ requires a constant number of bitwise operations on word-size integers plus at most $O(1)$ mask constructions already derived from $\chi^{(k)}$. Since there are $d$ levels, the total cost is $O(d)$ word operations.

Result

The scattered right shift is computed by binary decomposition of rank space induced by $\chi$, using locally defined carry masks $T_k$ that simulate binary subtraction on rank indices without explicitly materializing them.

$$ \boxed{\text{scattered right shift by } 1 \text{ on } z \subseteq \chi \text{ can be done in } O(d) \text{ steps}} $$

This completes the construction. ∎