A strict drop at position p after agreement below it decides the
lexicographic comparison downward.
A strict rise at position p after agreement below it decides the
lexicographic comparison upward.
The lazily threaded code comparison state, relative to the current
path's codes cs (levels 1 .. cs.length) and the incumbent's codes
bs (levels 1 .. bs.length, sentinel beyond).
The code store always has
nn + 2slots.canonlevelcounts the incumbent's codes.The incumbent's leaf is at a real level.
- blt (b : Nat) : b ∈ bs → b < codeSentinel
Stored incumbent codes are real codes.
- clt (c : Nat) : c ∈ cs → c < codeSentinel
Path codes are real codes.
- tri : (compCanon = 0 ∧ eqlevCanon = Int.ofNat cs.length ∧ cs.length ≤ bs.length ∧ ∀ (i : Nat), 1 ≤ i → i ≤ cs.length → cs[i - 1]! = bcode bs i) ∨ ∃ (j : Nat), 1 ≤ j ∧ j ≤ cs.length ∧ j ≤ bs.length + 1 ∧ eqlevCanon = Int.ofNat (j - 1) ∧ (∀ (i : Nat), 1 ≤ i → i < j → cs[i - 1]! = bcode bs i) ∧ (compCanon = -1 ∧ cs[j - 1]! < bcode bs j ∨ compCanon = 1 ∧ j ≤ bs.length ∧ bcode bs j < cs[j - 1]!)
The comparison trichotomy: full agreement, or a frozen divergence at level
jwith matched prefix below it. - content (i : Nat) : 1 ≤ i → i ≤ bs.length + 1 → (compCanon = 1 → i ≤ eqlevCanon.toNat ∨ cs.length < i) → canoncode[i]! = bcode bs i
Outside the upward-divergence overwrite window, the store holds the incumbent's codes (sentinel at
bs.length + 1). - over : compCanon = 1 → ∀ (i : Nat), eqlevCanon.toNat < i → i ≤ cs.length → canoncode[i]! = cs[i - 1]!
Inside the overwrite window, the store holds the path's codes.
Instances For
With compCanon = -1, every leaf below the node compares below
the incumbent on codes, whatever the deeper codes are.
With compCanon = 1, every leaf below the node compares above
the incumbent on codes, whatever the deeper codes are.
The key-level form of codeInv_listCmp_lt.
The key-level form of codeInv_listCmp_gt.
With compCanon = 0 and the path at the incumbent's depth, the
code lists are equal outright: the tied-leaf case hands the key
comparison to the rows (keyCmp_codes_eq).
One otherNodePrep step at level cs.length + 1 with fresh code
code extends the comparison invariant by one level.
recover under a live (non-overwriting) comparison: unwinding to
lvl truncates the path and restores full agreement when the match
reached lvl.
recover after a leaf event that repurposed compCanon for the
row comparison: the pre-leaf state matched through the whole path
(compCanon = 0 invariant), so unwinding to any lvl within the
path resets to full agreement whatever compCanon currently holds.
firstterminal seeds the comparison invariant: the first leaf's
codes become the incumbent with full agreement recorded.
Installing the current path as the new incumbent (the pure part
of the code-3 arm): after a non-downward comparison, the store
already holds the path's codes, so recording the path as incumbent
with the sentinel stamped re-seeds the invariant at full
agreement.
The first-path comparison state: the current path's codes cs
agree with the first leaf's codes fs through level eqlevFirst,
and firstcode stores fs with the sentinel stamped above.
The code store always has
nn + 2slots.The first leaf is at a real level.
- flt (f : Nat) : f ∈ fs → f < codeSentinel
First-path codes are real codes.
The store holds the first leaf's codes.
The sentinel is stamped above the first leaf's codes.
The agreement depth is within the current path.
The agreement depth is within the first path.
Recorded agreement is code-prefix agreement.
Instances For
Lowering the agreement depth preserves the invariant: the clause
for othernode's target-cell demotion and any other clamp.
Truncating the path above the agreement depth preserves the
invariant: the clause for recover's unwind together with its
clamp.
With the agreement depth at the full length of both paths, the
code lists are equal outright: the code-1 leaf case.
The first-path store decides where the first leaf sits: every position within the first path holds a real code, so the sentinel appearing just above the current path forces the two paths to end at the same level.
This is what the length premise of firstCodeInv_eq_of_tied reduces
to. It cannot be read off the refinement codes: mash masks its
accumulator to fifteen bits, so agreeing codes do not determine the
partition, let alone its cell count. The store's sentinel position
does determine it.
The sentinel hypothesis above cannot be dropped. Where the
first-path comparison is still live and the path is strictly shorter
than the first path, the current leaf's key strictly exceeds the first
leaf's, because the sentinel outranks every real code, so the code-1
skip would discard a candidate above the incumbent.
The code-1 leaf case in the form the induction applies: where
the first-path comparison is still live and the first-path store shows
the sentinel just above the current level, the two code paths are
equal outright.
One otherNodePrep step at level cs.length + 1 with fresh code
code extends the first-path agreement by one level exactly when the
depth had reached the path and the code matches the first path's next
code.
recover clamps the agreement depth to the unwind level.