@@ -27,13 +27,17 @@ protected meta def to_pos_rat : expr → option ℚ
27
27
| `(%%e₁ / %%e₂) := do m ← e₁.to_nat, n ← e₂.to_nat, some (rat.mk m n)
28
28
| e := do n ← e.to_nat, return (rat.of_int n)
29
29
30
+ protected meta def to_int : expr → option ℤ
31
+ | `(has_neg.neg %%e) := do n ← e.to_nat, some (-n)
32
+ | e := do n ← e.to_nat, return n
33
+
30
34
protected meta def to_rat : expr → option ℚ
31
35
| `(has_neg.neg %%e) := do q ← e.to_pos_rat, some (-q)
32
36
| e := e.to_pos_rat
33
37
34
38
protected meta def of_nat (α : expr) : ℕ → tactic expr :=
35
39
nat.binary_rec
36
- (tactic.mk_app ``has_zero .zero [α ])
40
+ (tactic.mk_mapp ``has_zero .zero [some α, none ])
37
41
(λ b n tac, if n = 0 then mk_mapp ``has_one .one [some α, none] else
38
42
do e ← tac, tactic.mk_app (cond b ``bit1 ``bit0 ) [e])
39
43
@@ -91,6 +95,14 @@ lemma lt_add_of_pos_helper [ordered_cancel_comm_monoid α]
91
95
(a b c : α) (h : a + b = c) (h₂ : 0 < b) : a < c :=
92
96
h ▸ (lt_add_iff_pos_right _).2 h₂
93
97
98
+ lemma nat_div_helper (a b q r : ℕ) (h : r + q * b = a) (h₂ : r < b) : a / b = q :=
99
+ by rw [← h, nat.add_mul_div_right _ _ (lt_of_le_of_lt (nat.zero_le _) h₂),
100
+ nat.div_eq_of_lt h₂, zero_add]
101
+
102
+ lemma int_div_helper (a b q r : ℤ) (h : r + q * b = a) (h₁ : 0 ≤ r) (h₂ : r < b) : a / b = q :=
103
+ by rw [← h, int.add_mul_div_right _ _ (ne_of_gt (lt_of_le_of_lt h₁ h₂)),
104
+ int.div_eq_zero_of_lt h₁ h₂, zero_add]
105
+
94
106
meta structure instance_cache :=
95
107
(α : expr)
96
108
(univ : level)
@@ -123,17 +135,6 @@ do d ← get_decl n,
123
135
124
136
end instance_cache
125
137
126
- meta def eval_inv (simp : expr → tactic (expr × expr)) : expr → tactic (expr × expr)
127
- | `(has_inv.inv %%e) := do
128
- c ← infer_type e >>= mk_instance_cache,
129
- (c, p₁) ← c.mk_app ``inv_eq_one_div [e],
130
- (c, o) ← c.mk_app ``has_one .one [],
131
- (c, e') ← c.mk_app ``has_div .div [o, e],
132
- (do (e'', p₂) ← simp e',
133
- p ← mk_eq_trans p₁ p₂,
134
- return (e'', p)) <|> return (e', p₁)
135
- | _ := failed
136
-
137
138
meta def eval_pow (simp : expr → tactic (expr × expr)) : expr → tactic (expr × expr)
138
139
| `(monoid.pow %%e₁ 0 ) := do
139
140
p ← mk_app ``pow_zero [e₁],
@@ -247,9 +248,62 @@ meta def eval_ineq (simp : expr → tactic (expr × expr)) : expr → tactic (ex
247
248
| `(%%e₁ ≠ %%e₂) := do e ← mk_app ``eq [e₁, e₂], mk_app ``not [e] >>= simp
248
249
| _ := failed
249
250
251
+ meta def eval_div_ext (simp : expr → tactic (expr × expr)) : expr → tactic (expr × expr)
252
+ | `(has_inv.inv %%e) := do
253
+ c ← infer_type e >>= mk_instance_cache,
254
+ (c, p₁) ← c.mk_app ``inv_eq_one_div [e],
255
+ (c, o) ← c.mk_app ``has_one .one [],
256
+ (c, e') ← c.mk_app ``has_div .div [o, e],
257
+ (do (e'', p₂) ← simp e',
258
+ p ← mk_eq_trans p₁ p₂,
259
+ return (e'', p)) <|> return (e', p₁)
260
+ | `(%%e₁ / %%e₂) := do
261
+ α ← infer_type e₁,
262
+ c ← mk_instance_cache α,
263
+ match α with
264
+ | `(nat) := do
265
+ n₁ ← e₁.to_nat, n₂ ← e₂.to_nat,
266
+ q ← expr.of_nat α (n₁ / n₂),
267
+ r ← expr.of_nat α (n₁ % n₂),
268
+ (c, e₃) ← c.mk_app ``has_mul .mul [q, e₂],
269
+ (c, e₃) ← c.mk_app ``has_add .add [r, e₃],
270
+ (e₁', p) ← norm_num e₃,
271
+ guard (e₁' =ₐ e₁),
272
+ (c, p') ← prove_lt simp c r e₂,
273
+ p ← mk_app ``norm_num .nat_div_helper [e₁, e₂, q, r, p, p'],
274
+ return (q, p)
275
+ | `(int) := match e₂ with
276
+ | `(- %%e₂') := do
277
+ (c, p₁) ← c.mk_app ``int .div_neg [e₁, e₂'],
278
+ (c, e) ← c.mk_app ``has_div .div [e₁, e₂'],
279
+ (c, e) ← c.mk_app ``has_neg .neg [e],
280
+ (e', p₂) ← simp e,
281
+ p ← mk_eq_trans p₁ p₂,
282
+ return (e', p)
283
+ | _ := do
284
+ n₁ ← e₁.to_int,
285
+ n₂ ← e₂.to_int,
286
+ q ← expr.of_rat α $ rat.of_int (n₁ / n₂),
287
+ r ← expr.of_rat α $ rat.of_int (n₁ % n₂),
288
+ (c, e₃) ← c.mk_app ``has_mul .mul [q, e₂],
289
+ (c, e₃) ← c.mk_app ``has_add .add [r, e₃],
290
+ (e₁', p) ← norm_num e₃,
291
+ guard (e₁' =ₐ e₁),
292
+ (c, r0) ← c.mk_app ``has_zero .zero [],
293
+ (c, r0) ← c.mk_app ``has_le .le [r0, r],
294
+ (_, p₁) ← simp r0,
295
+ p₁ ← mk_app ``of_eq_true [p₁],
296
+ (c, p₂) ← prove_lt simp c r e₂,
297
+ p ← mk_app ``norm_num .int_div_helper [e₁, e₂, q, r, p, p₁, p₂],
298
+ return (q, p)
299
+ end
300
+ | _ := failed
301
+ end
302
+ | _ := failed
303
+
250
304
meta def derive1 (simp : expr → tactic (expr × expr)) (e : expr) :
251
305
tactic (expr × expr) :=
252
- norm_num e <|> eval_inv simp e <|> eval_pow simp e <|> eval_ineq simp e
306
+ norm_num e <|> eval_div_ext simp e <|> eval_pow simp e <|> eval_ineq simp e
253
307
254
308
meta def derive : expr → tactic (expr × expr) | e :=
255
309
do (_, e', pr) ←
0 commit comments