Skip to content

Commit df963f8

Browse files
committed
feat(pr-x12): A1 — CTU carrier + quad-tree partition
Worker A1 of PR-X12 per .claude/knowledge/pr-x12-codec-x265-design.md § "Worker decomposition" line 195. Ships the structural foundation of the cognitive-cell codec — the carrier type, quad-tree partition with arena-backed children, leaf-CU mode taxonomy. Subsequent workers (A2-A8: mode tags, predict, transform, quantise, RDO, rANS, stream) consume only A1's `Ctu` type + `crate::hpc::linalg::*`. Surface (`crate::hpc::codec::*`, feature-gated): pub struct Ctu { block_row, block_col, tier, split_depth, arena } pub struct CtuArena { Vec<CtuPartition>, capacity 85 (= 1+4+16+64) } pub enum CtuPartition { Leaf(LeafCu), Split([NodeIdx; 4]) } pub struct LeafCu { mode, basin_idx, delta?, merge_dir?, escape_idx? } pub enum CellMode { Skip = 00, Merge = 01, Delta = 10, Escape = 11 } pub enum MergeDir { North, East, West, South } pub struct NodeIdx(pub u16); impl Ctu { pub fn new_skip(row, col, tier, basin) -> Self pub fn split(node, depth) -> Result<[NodeIdx;4], SplitError> pub fn merge(node) -> Result<(), MergeError> } Key design choices: - **Arena-allocated quad-tree** (`CtuArena` over `Vec<CtuPartition>` with `with_capacity(MAX_QUAD_TREE_NODES = 85)`) — matches the design doc's stack-arena pattern + PR-X10 invariant 1 (zero-cost abstractions, no `Box<dyn>` in hot paths). All node references are `NodeIdx(u16)`, never raw pointers. No further heap allocation can happen during split — the cap is structural (depth 3 × 4-way branching = 85 max). - **Repr-stable `CellMode` / `MergeDir`** — discriminants match the on-wire 2-bit codes the A7 rANS encoder will emit. Test pins this ABI (`cell_mode_discriminants_match_wire_codes`). - **Per-mode `Option<…>` fields on `LeafCu`** — clarity-first; the fixed per-mode bit budget collapse happens in A7 (out of scope). - **Constructor pattern** — `LeafCu::{skip, delta, merge, escape}` enforce "only the field for the current mode is `Some`" at the type level so consumers can't accidentally produce a `Skip` leaf carrying a stale `delta: Some(_)`. - **Split / merge** — split refuses non-leaves (`NotALeaf`) and depth beyond `MAX_SPLIT_DEPTH` (with cap returned in the error variant); merge refuses non-Splits (`NotASplit`), inner-Split children (`ChildNotLeaf`), and heterogeneous-mode children (`ChildrenDiverge`). Merge does NOT compact the arena — orphaned child nodes remain; a GC pass is out of scope for A1. 13 tests cover: new_skip_creates_root_leaf, split_root_yields_four_children, split_at_max_depth_rejects, split_already_split_node_rejects, merge_homogeneous_children_collapses, merge_heterogeneous_children_rejects, merge_split_child_rejects, merge_leaf_rejects, leaf_constructors_set_correct_fields, arena_capacity_bound_85 (depth-3 recursive split → exactly 85 nodes), cell_mode_discriminants_match_wire_codes, merge_dir_discriminants_match_wire_codes, node_idx_root_is_zero. Cargo.toml: new `codec = ["std"]` feature alongside `splat3d`. src/hpc/mod.rs: `#[cfg(feature = "codec")] pub mod codec;`. Verified locally: cargo test -p ndarray --features codec --lib hpc::codec 13 passed cargo check -p ndarray clean (no-codec build) cargo fmt --check clean cargo clippy -p ndarray --features codec -- -D warnings clean cargo clippy --features approx,serde,rayon -- -D warnings clean Out of scope (A2-A8 sprints): - A2 mode.rs — 2-bit mode bit-pack/unpack helpers - A3 predict.rs — intra/inter prediction - A4 transform.rs — optional DCT for delta residuals - A5 quantize.rs — 8-bit scalar quantiser - A6 rdo.rs — λ-RDO loop - A7 ans.rs — rANS entropy coder - A8 stream.rs — byte-stream pack/unpack
1 parent 94494bf commit df963f8

4 files changed

Lines changed: 666 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ ogit_bridge = []
247247
# `lance-graph/crates/jc/src/ewa_sandwich_3d.rs`.
248248
splat3d = ["std"]
249249

250+
# PR-X12 cognitive codec — x265-shaped skip/merge/delta/escape mode classes
251+
# over BlockedGrid CTUs. A1 (this crate) ships only the CTU carrier +
252+
# quad-tree partition; the entropy coder + RDO loop land in later workers.
253+
codec = ["std"]
254+
250255
# no_std polyfill for `static LazyLock` in `src/simd.rs` (sprint A12).
251256
# Pulls in `portable-atomic` with the `critical-section` impl plus the
252257
# `critical-section` runtime so we can build a once-cell-style cache for

0 commit comments

Comments
 (0)