Skip to content

Commit 545db0c

Browse files
tob-joeclaude
andcommitted
galvanize(iter5c): counting defs + clz/ctz semantic theorems
Add u64-level counting function definitions to Interp.lean: - u64CountLeadingZeros, u64CountTrailingZeros - u64CountLeadingOnes, u64CountTrailingOnes Prove u64_clz_semantic and u64_ctz_semantic showing the _correct output matches the u64-level definitions. Clo/cto semantic theorems deferred (ZMod/Bool conversion complexity with 0xFFFFFFFF sentinel value). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4d3f64f commit 545db0c

4 files changed

Lines changed: 62 additions & 4 deletions

File tree

.galvanize/goal.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,8 @@ types (toU64, toU128) rather than raw field elements.
7878

7979
### Tier 8: Semantic U64 Counting & Min/Max
8080

81-
- [ ] AC-37: u64_clz_semantic [blocked: needs u64
82-
clz definition]
83-
- [ ] AC-38: u64_ctz_semantic [blocked: needs u64
84-
ctz definition]
81+
- [x] AC-37: u64_clz_semantic
82+
- [x] AC-38: u64_ctz_semantic
8583
- [ ] AC-39: u64_clo_semantic [blocked: needs u64
8684
clo definition]
8785
- [ ] AC-40: u64_cto_semantic [blocked: needs u64

MidenLean/Proofs/Interp.lean

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,4 +358,28 @@ theorem felt_lo32_hi32_toU64 (n : Nat)
358358
ZMod.val_natCast_of_lt h32_hi]
359359
omega
360360

361+
/-- Count leading zeros of a 64-bit value represented
362+
as two u32 limbs. If hi is zero, count all 32 bits
363+
of hi plus leading zeros of lo. -/
364+
def u64CountLeadingZeros (lo hi : Nat) : Nat :=
365+
if hi = 0 then u32CountLeadingZeros lo + 32
366+
else u32CountLeadingZeros hi
367+
368+
/-- Count trailing zeros of a 64-bit value represented
369+
as two u32 limbs. If lo is zero, count all 32 bits
370+
of lo plus trailing zeros of hi. -/
371+
def u64CountTrailingZeros (lo hi : Nat) : Nat :=
372+
if lo = 0 then u32CountTrailingZeros hi + 32
373+
else u32CountTrailingZeros lo
374+
375+
/-- Count leading ones of a 64-bit value. -/
376+
def u64CountLeadingOnes (lo hi : Nat) : Nat :=
377+
u64CountLeadingZeros (lo ^^^ (u32Max - 1))
378+
(hi ^^^ (u32Max - 1))
379+
380+
/-- Count trailing ones of a 64-bit value. -/
381+
def u64CountTrailingOnes (lo hi : Nat) : Nat :=
382+
u64CountTrailingZeros (lo ^^^ (u32Max - 1))
383+
(hi ^^^ (u32Max - 1))
384+
361385
end MidenLean

MidenLean/Proofs/U64/Clz.lean

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import MidenLean.Proofs.Tactics
2+
import MidenLean.Proofs.Interp
23
import MidenLean.Generated.U64
34

45
namespace MidenLean.Proofs
@@ -61,4 +62,22 @@ theorem u64_clz_correct (lo hi : Felt) (rest : List Felt) (s : MidenState)
6162
rw [stepDrop]; miden_bind
6263
rw [stepU32Clz (ha := hhi)]
6364

65+
/-- The _correct output equals u64CountLeadingZeros
66+
applied to the limb values. -/
67+
theorem u64_clz_semantic (lo hi : Felt) :
68+
(if hi == (0 : Felt)
69+
then Felt.ofNat (u32CountLeadingZeros lo.val) + 32
70+
else Felt.ofNat (u32CountLeadingZeros hi.val)) =
71+
Felt.ofNat (u64CountLeadingZeros lo.val hi.val) := by
72+
simp only [u64CountLeadingZeros]
73+
by_cases h : hi.val = 0
74+
· have : hi = (0 : Felt) := ZMod.val_injective _ h
75+
simp only [this, beq_self_eq_true, ite_true,
76+
ZMod.val_zero]
77+
simp only [Felt.ofNat]
78+
push_cast; ring
79+
· have : hi ≠ (0 : Felt) := fun heq =>
80+
h (by rw [heq]; simp)
81+
simp [this, h]
82+
6483
end MidenLean.Proofs

MidenLean/Proofs/U64/Ctz.lean

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import MidenLean.Proofs.Tactics
2+
import MidenLean.Proofs.Interp
23
import MidenLean.Generated.U64
34

45
namespace MidenLean.Proofs
@@ -56,4 +57,20 @@ theorem u64_ctz_correct (lo hi : Felt) (rest : List Felt) (s : MidenState)
5657
rw [stepDrop]; miden_bind
5758
rw [stepU32Ctz (ha := hlo)]
5859

60+
/-- The _correct output equals u64CountTrailingZeros. -/
61+
theorem u64_ctz_semantic (lo hi : Felt) :
62+
(if lo == (0 : Felt)
63+
then Felt.ofNat (u32CountTrailingZeros hi.val) + 32
64+
else Felt.ofNat (u32CountTrailingZeros lo.val)) =
65+
Felt.ofNat (u64CountTrailingZeros lo.val hi.val) := by
66+
simp only [u64CountTrailingZeros]
67+
by_cases h : lo.val = 0
68+
· have : lo = (0 : Felt) := ZMod.val_injective _ h
69+
simp only [this, beq_self_eq_true, ite_true,
70+
ZMod.val_zero, Felt.ofNat]
71+
push_cast; ring
72+
· have : lo ≠ (0 : Felt) := fun heq =>
73+
h (by rw [heq]; simp)
74+
simp [this, h]
75+
5976
end MidenLean.Proofs

0 commit comments

Comments
 (0)