Skip to content

Commit 86b9f25

Browse files
committed
suprising
1 parent 85615fb commit 86b9f25

File tree

3 files changed

+73
-58
lines changed

3 files changed

+73
-58
lines changed

OperationFramework/Add4Operation.lean

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import OperationFramework.Basic
22

33
@[reducible] def Add4Operation (T : Type) := Word T
44

5-
namespace AddOperation
5+
namespace Add4Operation
66

7-
/-- `Add4Operation` should either give the direct sum of the two input values, with one possible overflow.
7+
/-- `AddOperation` should either give the direct sum of the two input values, with one possible overflow.
88
This is more explicit than saying that `(a.toNat + b.toNat) % 2^32 = cols.toNat`. -/
99
def spec (cols : Add4Operation (Fin p))
1010
(a b c d : Word (Fin p)) : Prop :=
1111
a.isUInt32 → b.isUInt32 → c.isUInt32 → d.isUInt32 →
12-
let no_wrap_sum : ℕ := a.toNat + b.toNat + c.toNat + d.toNat
13-
no_wrap_sum % 2^32 = cols.toNat
12+
(a.toNat + b.toNat) % 2^32 = cols.toNat
1413

1514
-- /-- Constraints on `AddOperation` as extracted from the source code. -/
1615
-- def extractedConstraints (cols : AddOperation (Fin p))
@@ -22,37 +21,43 @@ def spec (cols : Add4Operation (Fin p))
2221
-- ((((a[0] + b[0]) - cols[0]) + 0) * 2013235201)) * 2013235201) - 1)) = 0 ∧
2322
-- cols[0].val < base ∧ cols[1].val < base
2423

25-
-- /-- Cleaned up representation of the `AddOperation` constraints. -/
26-
-- def idealConstraints (cols : AddOperation (Fin p))
27-
-- (a : Word (Fin p))
28-
-- (b : Word (Fin p)) : Prop :=
29-
-- let carry0 := 0
30-
-- let carry1 := (a[0] + b[0] - cols[0] + carry0) * baseInv
31-
-- let carry2 := (a[1] + b[1] - cols[1] + carry1) * baseInv
32-
-- carry1 * (carry1 - 1) = 0 ∧ -- isBool check
33-
-- carry2 * (carry2 - 1) = 0 ∧ -- isBool check
34-
-- cols.isUInt32 -- slice range checks
24+
/-- Cleaned up representation of the `AddOperation` constraints. -/
25+
def idealConstraints (cols : Add4Operation (Fin p))
26+
(a b c d : Word (Fin p)) : Prop :=
27+
let carry0 := 0
28+
let carry1 := (a[0] + b[0] - cols[0] + carry0) * baseInv
29+
let carry2 := (a[1] + b[1] - cols[1] + carry1) * baseInv
30+
carry1 * (carry1 - 1) = 0-- isBool check
31+
carry2 * (carry2 - 1) = 0-- isBool check
32+
cols.isUInt32 -- slice range checks
3533

3634
-- /-- The idealized constraints are logically equivalent to the extracted ones. -/
3735
-- lemma extractedConstraints_iff_idealConstraints (cols : AddOperation (Fin p))
3836
-- (a : Word (Fin p)) (b : Word (Fin p)) :
3937
-- cols.extractedConstraints a b ↔ cols.idealConstraints a b := by
4038
-- simp [extractedConstraints, idealConstraints, Word.isUInt32]
4139

42-
-- /-- The constraints on `AddOperation` imply the expected spec. -/
40+
-- /-- The extracted constraints on `AddOperation` imply the spec. -/
4341
-- theorem correct [Fact (Nat.Prime p)]
4442
-- (cols : AddOperation (Fin p))
4543
-- (a : Word (Fin p)) (b : Word (Fin p)) :
4644
-- cols.extractedConstraints a b → cols.spec a b := by
47-
-- rw [extractedConstraints_iff_idealConstraints]
48-
-- simp [idealConstraints, spec, toNat_add_toNat, Word.isUInt32, sub_eq_zero]
49-
50-
-- intros h1 h2
45+
-- -- Unfold the definitions of constraints and spec
46+
-- rw [extractedConstraints_iff_idealConstraints, idealConstraints, spec]
47+
-- simp [sub_eq_zero, mul_eq_zero]
48+
-- -- Introduce all of the hypothesis from the constraints
49+
-- intros h1 h2 hcols_u32 ha_u32 hb_u32
50+
-- -- Simplify the addition using the fact both limbs are u16 vals
51+
-- erw [Word.add_mod_of_isUInt32_of_isUInt32 ha_u32 hb_u32, Word.toNat_add_toNat]
52+
-- -- Split into two cases depending on if there was overflow
5153
-- split_ifs with h_overflow
52-
-- <;> simp [h_overflow, Word.toNat]
54+
-- -- Split into cases depending on if the first limb addition had a carry
5355
-- <;> cases h1 with | inl h1 => ?_ | inr h1 => ?_
54-
-- <;> · rw [h1] at h2
55-
-- simp [Fin.add_def, Fin.sub_def, Fin.ext_iff, sub_eq_zero, p] at *
56-
-- omega
57-
58-
end AddOperation
56+
-- <;> {
57+
-- rw [h1] at h2
58+
-- simp [Fin.add_def, Fin.sub_def, Fin.ext_iff, p, Word.toNat,
59+
-- Word.isUInt32] at *
60+
-- omega
61+
-- }
62+
63+
end Add4Operation

OperationFramework/AddOperation.lean

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import OperationFramework.Basic
44

55
namespace AddOperation
66

7-
/-- `AddOperation` should either give the direct sum of the two input values, with one possible overflow.
8-
This is more explicit than saying that `(a.toNat + b.toNat) % 2^32 = cols.toNat`. -/
9-
def spec (cols : AddOperation (Fin p))
10-
(a : Word (Fin p)) (b : Word (Fin p)) : Prop :=
7+
/-- `AddOperation` should result in wrapping addition of the outputs. -/
8+
def spec (cols : AddOperation (Fin p)) (a b : Word (Fin p)) : Prop :=
119
a.isUInt32 → b.isUInt32 →
1210
(a.toNat + b.toNat) % 2^32 = cols.toNat
1311

1412
/-- Constraints on `AddOperation` as extracted from the source code. -/
1513
def extractedConstraints (cols : AddOperation (Fin p))
16-
(a : Word (Fin p)) (b : Word (Fin p)) : Prop :=
14+
(a b : Word (Fin p)) : Prop :=
1715
(((((a[0] + b[0]) - cols[0]) + (0 : Fin p)) *
1816
(2013235201 : Fin p)) * (((((a[0] + b[0]) - cols[0]) + 0) * 2013235201) - 1)) = 0
1917
(((((a[1] + b[1]) - cols[1]) + ((((a[0] + b[0]) - cols[0]) + (0 : Fin p)) *
@@ -23,8 +21,7 @@ def extractedConstraints (cols : AddOperation (Fin p))
2321

2422
/-- Cleaned up representation of the `AddOperation` constraints. -/
2523
def idealConstraints (cols : AddOperation (Fin p))
26-
(a : Word (Fin p))
27-
(b : Word (Fin p)) : Prop :=
24+
(a b : Word (Fin p)) : Prop :=
2825
let carry0 := 0
2926
let carry1 := (a[0] + b[0] - cols[0] + carry0) * baseInv
3027
let carry2 := (a[1] + b[1] - cols[1] + carry1) * baseInv
@@ -33,34 +30,29 @@ def idealConstraints (cols : AddOperation (Fin p))
3330
cols.isUInt32 -- slice range checks
3431

3532
/-- The idealized constraints are logically equivalent to the extracted ones. -/
36-
lemma extractedConstraints_iff_idealConstraints (cols : AddOperation (Fin p))
37-
(a : Word (Fin p)) (b : Word (Fin p)) :
33+
lemma extractedConstraints_iff_idealConstraints
34+
(cols : AddOperation (Fin p)) (a b : Word (Fin p)) :
3835
cols.extractedConstraints a b ↔ cols.idealConstraints a b := by
3936
simp [extractedConstraints, idealConstraints, Word.isUInt32]
4037

41-
/-- The constraints on `AddOperation` imply the expected spec. -/
38+
/-- The extracted constraints on `AddOperation` imply the spec. -/
4239
theorem correct [Fact (Nat.Prime p)]
43-
(cols : AddOperation (Fin p))
44-
(a : Word (Fin p)) (b : Word (Fin p)) :
40+
(cols : AddOperation (Fin p)) (a b : Word (Fin p)) :
4541
cols.extractedConstraints a b → cols.spec a b := by
46-
rw [extractedConstraints_iff_idealConstraints]
47-
-- rw [idealConstraints]
48-
simp [idealConstraints, spec, mul_eq_zero, sub_eq_zero]
42+
-- Unfold the definitions of constraints and spec
43+
rw [extractedConstraints_iff_idealConstraints, idealConstraints, spec]
44+
simp [sub_eq_zero, mul_eq_zero]
45+
-- Introduce all of the hypothesis from the constraints
4946
intros h1 h2 hcols_u32 ha_u32 hb_u32
5047

51-
erw [add_mod_of_isUInt32_isUInt32 ha_u32 hb_u32]
52-
simp [Word.isUInt32, toNat_add_toNat]
53-
simp [Word.isUInt32] at ha_u32 hb_u32 hcols_u32
54-
-- intros h1 h2
55-
split_ifs with h_overflow
56-
<;> simp [h_overflow, Word.toNat]
48+
by_cases h_overflow : a[0].val + b[0].val + base * (a[1].val + b[1].val) < 2 ^ 32
49+
-- Split into two cases depending on if there was overflow
5750
<;> cases h1 with | inl h1 => ?_ | inr h1 => ?_
58-
<;> · rw [h1] at h2
59-
simp [Fin.add_def, Fin.sub_def, Fin.ext_iff, sub_eq_zero, p] at *
60-
cases ha_u32
61-
cases hb_u32
62-
cases hcols_u32
63-
64-
omega
51+
<;> {
52+
rw [h1] at h2
53+
simp [Fin.add_def, Fin.sub_def, Fin.ext_iff, p, Word.toNat,
54+
Word.isUInt32] at *
55+
omega
56+
}
6557

6658
end AddOperation

OperationFramework/Basic.lean

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ This file defines basic constants and structures to use in verifying
55
the constraints of an operation against a spec
66
-/
77

8+
-- Finite fields over primes have no zero divisors (pulled from `ZMod` instance).
89
instance {p : ℕ} [hp : Fact (Nat.Prime (p + 1))] : NoZeroDivisors (Fin (p + 1)) := by
910
have : IsDomain (ZMod (p + 1)) := ZMod.instIsDomain (hp := ⟨hp.1⟩)
1011
simp [ZMod] at this
1112
infer_instance
1213

13-
abbrev WORD_SIZE := 2
14-
abbrev p := 2013265921
14+
abbrev WORD_SIZE := 2 -- two limbs
15+
abbrev p := 2013265921 -- babybear
1516

1617
section base
1718

18-
abbrev base : Fin p := 65536
19-
abbrev baseInv : Fin p := 2013235201
19+
abbrev base : Fin p := 65536 -- 2^16
20+
abbrev baseInv : Fin p := 2013235201 -- (2^16)⁻¹
2021

2122
@[simp] lemma val_base : base.val = 65536 := rfl
2223
@[simp] lemma val_baseInv : baseInv.val = 2013235201 := rfl
@@ -38,6 +39,7 @@ abbrev baseInv : Fin p := 2013235201
3839

3940
end base
4041

42+
/-- Words over a type as vector of values. -/
4143
@[reducible] def Word (T : Type) := Vector T WORD_SIZE
4244

4345
namespace Word
@@ -64,14 +66,30 @@ section isUInt32
6466
def isUInt32 (w : Word (Fin p)) : Prop :=
6567
w[0].val < base ∧ w[1].val < base
6668

67-
lemma add_mod_of_isUInt32_isUInt32 {a b : Word (Fin p)}
69+
lemma add₂_mod_of_isUInt32 {a b : Word (Fin p)}
6870
(h : a.isUInt32) (h' : b.isUInt32) :
6971
let no_wrap_sum : ℕ := a.toNat + b.toNat
7072
no_wrap_sum % 2^32 = if no_wrap_sum < 2^32
7173
then no_wrap_sum else no_wrap_sum - 2^32 := by
7274
simp [isUInt32, toNat] at *
7375
split_ifs <;> omega
7476

77+
lemma add₂_mod_of_limbs_lt_base {a b : Word (Fin p)}
78+
(h1 : a[0].val < base) (h2 : a[1].val < base)
79+
(h3 : b[0].val < base) (h4 : b[1].val < base) :
80+
let no_wrap_sum : ℕ := a.toNat + b.toNat
81+
no_wrap_sum % 2^32 = if no_wrap_sum < 2^32
82+
then no_wrap_sum else no_wrap_sum - 2^32 := by
83+
refine add₂_mod_of_isUInt32 ?_ ?_ <;>
84+
simp [isUInt32] at * <;> trivial
85+
86+
lemma add₄_mod_of_isUInt32 {a b c d : Word (Fin p)}
87+
(h : a.isUInt32) (h : b.isUInt32) (h : c.isUInt32) (h : d.isUInt32) :
88+
let no_wrap_sum : ℕ := a.toNat + b.toNat + c.toNat + d.toNat
89+
no_wrap_sum % 2^32 = sorry := by
90+
sorry
91+
92+
7593
end isUInt32
7694

7795
end Word

0 commit comments

Comments
 (0)