Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit b769846

Browse files
committed
feat(tactic/norm_num): new all-lean norm_num (#2589)
This is a first draft of the lean replacement for `tactic.norm_num` in core. This isn't completely polished yet; the rest of `norm_num` can now be a little less "global-recursive" since the primitives for e.g. adding and multiplying natural numbers are exposed. I'm also trying out a new approach using functions like `match_neg` and `match_numeral` instead of directly pattern matching on exprs, because this generates smaller (and hopefully more efficient) code. (Without this, some of the matches were hitting the equation compiler depth limit.) I'm open to new feature suggestions as well here. `nat.succ` and coercions seem useful to support in the core part, and additional flexibility using `def_replacer` is also on the agenda.
1 parent 20c7418 commit b769846

File tree

5 files changed

+1225
-287
lines changed

5 files changed

+1225
-287
lines changed

src/analysis/specific_limits.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ begin
229229
convert has_sum.mul_left (a / 2) (has_sum_geometric
230230
(le_of_lt one_half_pos) one_half_lt_one),
231231
{ funext n, simp, refl, },
232-
{ norm_num, rw div_mul_cancel, norm_num }
232+
{ norm_num }
233233
end
234234

235235
lemma summable_geometric_two' (a : ℝ) : summable (λ n:ℕ, (a / 2) / 2 ^ n) :=

src/data/rat/meta_defs.lean

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Copyright (c) 2019 Robert Y. Lewis . All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Author: Robert Y. Lewis
55
-/
6-
import data.rat.basic
6+
import data.rat.basic tactic.core
77

88
/-!
99
# Meta operations on ℚ
@@ -55,8 +55,13 @@ end
5555
/-- Evaluates an expression as a rational number,
5656
if that expression represents a numeral or the quotient of two numerals. -/
5757
protected meta def expr.to_nonneg_rat : expr → option ℚ
58-
| `(%%e₁ / %%e₂) := do m ← e₁.to_nat, n ← e₂.to_nat, some (rat.mk m n)
59-
| e := do n ← e.to_nat, return (rat.of_int n)
58+
| `(%%e₁ / %%e₂) := do
59+
m ← e₁.to_nat,
60+
n ← e₂.to_nat,
61+
if c : m.coprime n then if h : 1 < n then
62+
return ⟨m, n, lt_trans zero_lt_one h, c⟩
63+
else none else none
64+
| e := do n ← e.to_nat, return (rat.of_int n)
6065

6166
/-- Evaluates an expression as a rational number,
6267
if that expression represents a numeral, the quotient of two numerals,
@@ -96,3 +101,26 @@ protected meta def expr.of_rat (α : expr) : ℚ → tactic expr
96101
e₂ ← expr.of_nat α d,
97102
tactic.mk_app ``has_div.div [e₁, e₂]),
98103
tactic.mk_app ``has_neg.neg [e]
104+
105+
namespace tactic
106+
namespace instance_cache
107+
108+
/-- `c.of_rat q` embeds `q` as a numeral expression inside the type `α`.
109+
Lean will try to infer the correct type classes on `c.α`, and the tactic will fail if it cannot.
110+
This function is similar to `rat.mk_numeral` but it takes fewer hypotheses and is tactic valued.
111+
-/
112+
protected meta def of_rat (c : instance_cache) : ℚ → tactic (instance_cache × expr)
113+
| ⟨(n:ℕ), d, _, _⟩ :=
114+
if d = 1 then c.of_nat n else do
115+
(c, e₁) ← c.of_nat n,
116+
(c, e₂) ← c.of_nat d,
117+
c.mk_app ``has_div.div [e₁, e₂]
118+
| ⟨-[1+n], d, _, _⟩ := do
119+
(c, e) ← (if d = 1 then c.of_nat (n+1) else do
120+
(c, e₁) ← c.of_nat (n+1),
121+
(c, e₂) ← c.of_nat d,
122+
c.mk_app ``has_div.div [e₁, e₂]),
123+
c.mk_app ``has_neg.neg [e]
124+
125+
end instance_cache
126+
end tactic

src/tactic/core.lean

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,26 @@ do d ← get_decl n,
529529
(c, l) ← append_typeclasses d.type.binding_body c l,
530530
return (c, (expr.const n [c.univ]).mk_app (c.α :: l))
531531

532+
/-- `c.of_nat n` creates the `c.α`-valued numeral expression corresponding to `n`. -/
533+
protected meta def of_nat (c : instance_cache) (n : ℕ) : tactic (instance_cache × expr) :=
534+
if n = 0 then c.mk_app ``has_zero.zero [] else do
535+
(c, ai) ← c.get ``has_add,
536+
(c, oi) ← c.get ``has_one,
537+
(c, one) ← c.mk_app ``has_one.one [],
538+
return (c, n.binary_rec one $ λ b n e,
539+
if n = 0 then one else
540+
cond b
541+
((expr.const ``bit1 [c.univ]).mk_app [c.α, oi, ai, e])
542+
((expr.const ``bit0 [c.univ]).mk_app [c.α, ai, e]))
543+
544+
/-- `c.of_int n` creates the `c.α`-valued numeral expression corresponding to `n`.
545+
The output is either a numeral or the negation of a numeral. -/
546+
protected meta def of_int (c : instance_cache) : ℤ → tactic (instance_cache × expr)
547+
| (n : ℕ) := c.of_nat n
548+
| -[1+ n] := do
549+
(c, e) ← c.of_nat (n+1),
550+
c.mk_app ``has_neg.neg [e]
551+
532552
end instance_cache
533553

534554
private meta def get_expl_pi_arity_aux : expr → tactic nat

0 commit comments

Comments
 (0)