@@ -32,9 +32,12 @@ def largestPrimeFactor (n : Nat) : Nat := Id.run do
3232 let mut m : { m : Nat // 0 < m } := ⟨n, hn⟩
3333 let mut mostRecentFactor := 1
3434 for hd : d in 2 ...=n do
35- if d ∣ m.val then
36- mostRecentFactor := d
37- m := dividePower m d (by grind [Rcc.mem_iff])
35+ if d * d ≤ m then
36+ if d ∣ m.val then
37+ mostRecentFactor := d
38+ m := dividePower m d (by grind [Rcc.mem_iff])
39+ else
40+ return max mostRecentFactor m
3841 return mostRecentFactor
3942 else
4043 return 1
@@ -87,7 +90,7 @@ theorem largestPrimeFactor_dvd :
8790 apply Id.of_wp_run_eq hwp
8891 mvcgen
8992 invariants
90- · ⇓⟨ cur, m, factor⟩ => ⌜factor ∣ n ∧ m.val ∣ n⌝
93+ · .withEarlyReturn ( fun cur ⟨ m, factor⟩ => ⌜factor ∣ n ∧ m.val ∣ n⌝) ( fun ret ⟨m, factor⟩ => ⌜ret ∣ n⌝)
9194 with grind [dividePower_dvd, Nat.dvd_trans, Nat.dvd_refl]
9295
9396theorem dvd_or_dvd_of_dvd_self_div_dividePower {e : Nat} (h : m.val ∣ n)
@@ -123,30 +126,34 @@ theorem isPrime_largestPrimeFactor (h : 1 < n) :
123126 apply Id.of_wp_run_eq hwp
124127 mvcgen
125128 invariants
126- · ⇓⟨cur, m, factor⟩ =>
129+ · .withEarlyReturn
130+ (fun cur ⟨m, factor⟩ =>
127131 ⌜let i := cur.pos + 2 ;
128132 factor < i ∧
129133 m.val ∣ n ∧
130134 (if m.val = n then factor = 1 else IsPrime factor ∧ ∀ e : Nat, e ∣ n / m → IsPrime e → e ≤ factor) ∧
131- ∀ e : Nat, e ∣ m → e = 1 ∨ i ≤ e⌝
132- case vc1 pref cur suf _ _ m _ _ ih =>
133- refine ⟨?_, ?_, ?_, ?_⟩
135+ ∀ e : Nat, e ∣ m → e = 1 ∨ i ≤ e⌝)
136+ (fun ret ⟨m, factor⟩ => ⌜IsPrime ret ∧ ∀ d : Nat, d ∣ n → IsPrime d → d ≤ ret⌝)
137+ case vc1 pref cur suf _ _ _ m _ _ _ ih =>
138+ simp only [reduceCtorEq, false_and, exists_false, or_false]
139+ refine ⟨?_, ?_, ?_, ?_, ?_⟩
140+ · grind
134141 · grind
135142 · grind [dividePower_dvd, Nat.dvd_trans]
136143 · simp at *
137144 have : (dividePower m cur (by grind)).val < m.val := dividePower_lt (by grind)
138- have : m.val ≤ n := Nat.le_of_dvd ‹0 < n› ih.2 .1
145+ have : m.val ≤ n := Nat.le_of_dvd ‹0 < n› ih.2 .2 . 1
139146 rw [if_neg (by grind)]
140147 constructor
141148 · rw [IsPrime]
142149 constructor
143150 · grind
144151 · intro d hd
145- have := ih.2 .2 .2 d (by grind [Nat.dvd_trans])
152+ have := ih.2 .2 .2 . 2 d (by grind [Nat.dvd_trans])
146153 have : d ≤ cur := Nat.le_of_dvd (by grind) hd
147154 grind
148155 · intro e he hep
149- have := ih.2 .2 .1
156+ have := ih.2 .2 .2 . 1
150157 replace he := dvd_or_dvd_of_dvd_self_div_dividePower (by grind) he hep
151158 split at this
152159 · have : m = ⟨n, ‹_›⟩ := by grind
@@ -159,20 +166,24 @@ theorem isPrime_largestPrimeFactor (h : 1 < n) :
159166 cases he
160167 · grind
161168 · exact Nat.le_of_dvd (by grind) ‹_›
162- · intro e he
169+ · simp at *
170+ intro e he
163171 have : e ≠ cur := by grind [not_dvd_dividePower]
164- replace ih := ih.2 .2 .2 e
172+ replace ih := ih.2 .2 .2 . 2 e
165173 grind [dividePower_dvd, Nat.dvd_trans]
166- case vc2 pref cur suf _ _ _ _ _ ih =>
174+ case vc2 pref cur suf _ _ _ _ _ _ _ ih =>
175+ simp only [List.Cursor.pos_mk, true_and, reduceCtorEq, false_and, exists_const, or_false]
176+ simp only [List.Cursor.pos_mk, reduceCtorEq, false_and, and_false, exists_const, or_false] at ih
167177 refine ⟨?_, ?_, ?_, ?_⟩
168178 · grind
169179 · grind
170180 · grind
171181 · intro e he
172182 have : e ≠ cur := by grind
173- replace ih := ih.2 .2 .2 e
183+ replace ih := ih.2 .2 .2 . 2 e
174184 grind
175- case vc3 =>
185+ case vc4 =>
186+ simp only [List.Cursor.pos_mk, true_and, reduceCtorEq, false_and, exists_const, or_false]
176187 refine ⟨?_, ?_, ?_, ?_⟩
177188 · grind
178189 · grind [Nat.dvd_refl]
@@ -181,15 +192,58 @@ theorem isPrime_largestPrimeFactor (h : 1 < n) :
181192 intro e he
182193 have : 0 < e := Nat.pos_of_dvd_of_pos he ‹0 < n›
183194 grind
184- case vc4 r ih =>
195+ case vc5 r _ ih =>
185196 simp at *
197+ simp_all
186198 have := ih.2 .2 .2 _ (Nat.dvd_refl _)
187- have : r.fst .val ≤ n := Nat.le_of_dvd ‹0 < n› ih.2 .1
188- have : r.fst .val = 1 := by grind
199+ have : r.2 . 1 .val ≤ n := Nat.le_of_dvd ‹0 < n› ih.2 .1
200+ have : r.2 . 1 .val = 1 := by grind
189201 have := ih.2 .2 .1
190202 rw [if_neg (by grind)] at this
191203 simpa [*] using this
192- case vc5 => grind
204+ case vc7 => grind
205+ -- Early return verification conditions:
206+ case vc3 pref cur suff _ _ _ m _ hlt ih =>
207+ simp_all
208+ rw [max_eq_if]
209+ split
210+ · constructor
211+ · grind
212+ · intro d hd hdp
213+ rw [if_neg (by grind)] at ih
214+ rw [← show n / m.val * m.val = n from Nat.div_mul_cancel (by grind)] at hd
215+ rw [hdp.dvd_mul_iff] at hd
216+ cases hd
217+ · grind
218+ · have := ih.2 .2 .2 .2 d ‹_›
219+ cases this
220+ · grind
221+ · have : cur ≤ d := by grind
222+ have : m.val / d ∣ m.val := Nat.div_dvd_of_dvd ‹_›
223+ have : m.val / d < cur := by
224+ rw [Nat.div_lt_iff_lt_mul (by grind)]
225+ exact Nat.lt_of_lt_of_le hlt (Nat.mul_le_mul_left cur ‹_›)
226+ have := ih.2 .2 .2 .2 (m.val / d) ‹_›
227+ cases this
228+ · rename_i h
229+ rw [Nat.div_eq_iff_eq_mul_left (by grind) (by grind)] at h
230+ grind
231+ · grind
232+ · constructor
233+ · rw [isPrime_iff_mul_self]
234+ constructor
235+ · grind [IsPrime]
236+ · intro e he he'
237+ refine Nat.lt_of_lt_of_le hlt ?_
238+ have := ih.2 .2 .2 .2 e he'
239+ exact Nat.mul_self_le_mul_self (by grind)
240+ · intro d hd hdp
241+ rw [← show n / m.val * m.val = n from Nat.div_mul_cancel (by grind)] at hd
242+ rw [hdp.dvd_mul_iff] at hd
243+ cases hd
244+ · grind [Nat.div_self, Nat.dvd_one]
245+ · exact Nat.le_of_dvd (by grind) ‹_›
246+ case vc6 => grind
193247
194248/-!
195249## Prompt
0 commit comments