GGraziadei commented on PR #17774:
URL: https://github.com/apache/iceberg/pull/17774#issuecomment-5382755566

   # Numerical example with 3 columns
   
   A worked example of the table-based interleaving, with every intermediate 
value.
   
   ## 1. Input data
   
   Three 1-byte columns, one bit set each, so it is easy to follow where each 
bit lands:
   
   | Column | Name | Hex | Binary (MSB→LSB) |
   |--------|------|-----|------------------|
   | 0 | A | `0x80` | `1000 0000` |
   | 1 | B | `0x40` | `0100 0000` |
   | 2 | C | `0x20` | `0010 0000` |
   
   `N = 3` columns, each contributes 1 byte → output = `N × 1 = 3 bytes` = 24 
bits.
   
   ## 2. What Z-order must produce (conceptual definition)
   
   Interleaving takes one bit at a time, rotating across the columns, from the 
MSB down to the LSB:
   
   ```
   A7 B7 C7  A6 B6 C6  A5 B5 C5  A4 B4 C4  ...
   ```
   
   Substituting the values (A has only bit7, B only bit6, C only bit5):
   
   ```
   A7 B7 C7  A6 B6 C6  A5 B5 C5  ... rest 0
    1  0  0   0  1  0   0  0  1   0 0 0 ...
   ```
   
   Grouping into 8-bit bytes:
   
   ```
   bits 1..8 :  1000 1000  = 0x88
   bits 9..16:  1000 0000  = 0x80
   bits 17..24: 0000 0000  = 0x00
   ```
   
   **Expected result: `[0x88, 0x80, 0x00]`.** This is what the old bit-by-bit 
loop produced.
   
   ## 3. The SPREAD table
   
   Every group of `N=3` output bits holds one bit from A, one from B, one from 
C, so a bit sits `N` positions away from the next one. `SPREAD[N][b]` spreads 
the 8 bits of byte `b` that far apart. From `buildSpreadTables`:
   
   ```
   if bit 'bit' of b is set (bit=0 is the MSB):
       spread |= 1 << (8*N - 1 - bit*N)
   ```
   
   With `N=3` the target position is `24 - 1 - 3*bit = 23 - 3*bit`:
   
   - **A = `0x80`** → only `bit=0`. Position `23` → `SPREAD[3][0x80] = 1 << 23 
= 0x800000`
   - **B = `0x40`** → only `bit=1`. Position `20` → `SPREAD[3][0x40] = 1 << 20 
= 0x100000`
   - **C = `0x20`** → only `bit=2`. Position `17` → `SPREAD[3][0x20] = 1 << 17 
= 0x020000`
   
   SPREAD positions the bits as if every column were column 0 (highest slot of 
each triple).
   
   ## 4. Combining the columns: `interleaveGroup`
   
   Each column is placed into its slot with a right shift equal to its index:
   
   ```
   group |= SPREAD[column] >>> column_index
   ```
   
   | Column | SPREAD | shift | Contribution |
   |--------|--------|-------|--------------|
   | 0 (A) | `0x800000` | `>>> 0` | `0x800000` |
   | 1 (B) | `0x100000` | `>>> 1` | `0x080000` |
   | 2 (C) | `0x020000` | `>>> 2` | `0x008000` |
   
   ```
     0x800000   = 1000 0000 0000 0000 0000 0000
   | 0x080000   = 0000 1000 0000 0000 0000 0000
   | 0x008000   = 0000 0000 1000 0000 0000 0000
   -----------------------------------------------
     0x888000   = 1000 1000 1000 0000 0000 0000
   ```
   
   `group = 0x888000`. A (col 0) stays at bit 23, B (col 1) drops to bit 19, C 
(col 2) drops to bit 15 — exactly `A B C` within their triples, non-overlapping.
   
   ## 5. Extracting the output bytes
   
   `group` sits in the low 3 bytes of a `long`. The loop writes MSB-byte first 
(`groupByte` from `N-1=2` down to `0`):
   
   | groupByte | `group >>> (8*groupByte)` | byte |
   |-----------|---------------------------|------|
   | 2 | `0x888000 >>> 16 = 0x88` | `0x88` |
   | 1 | `0x888000 >>> 8  → (byte) 0x80` | `0x80` |
   | 0 | `0x888000 >>> 0  → (byte) 0x00` | `0x00` |
   
   **Output: `[0x88, 0x80, 0x00]`** ✓ — identical to the bit-by-bit result in 
step 2.
   
   ## 6. Why it is faster
   
   - The old method did `8 × interleavedSize` iterations (192 for 3 output 
bytes), moving one bit at a time, with a next-column search at every step that 
the CPU cannot pipeline.
   - The table version processes one source byte at a time: `N` lookups + `N` 
ORs per byte offset, then writes `N` bytes. No per-row allocation; only the 
`SPREAD[N]` row in use (~2 KB) is touched.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to