@@ -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.
88This is more explicit than saying that `(a.toNat + b.toNat) % 2^32 = cols.toNat`. -/
99def 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
0 commit comments