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

Commit 4fa54b3

Browse files
committed
chore(analysis/special_functions/pow): move around rpow/cpow tactics (#19022)
This PR splits up the code that implements `norm_num` and `positivity` for real / complex powers, and puts it into the files where those operations are defined, for easier discoverability.
1 parent 0b9eaaa commit 4fa54b3

File tree

11 files changed

+220
-220
lines changed

11 files changed

+220
-220
lines changed

src/analysis/fourier/poisson_summation.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import analysis.fourier.add_circle
77
import analysis.fourier.fourier_transform
88
import analysis.p_series
99
import analysis.schwartz_space
10-
import analysis.special_functions.pow.tactic
1110

1211
/-!
1312
# Poisson's summation formula

src/analysis/special_functions/japanese_bracket.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ Authors: Moritz Doll
55
-/
66
import measure_theory.measure.haar_lebesgue
77
import measure_theory.integral.layercake
8-
import analysis.special_functions.pow.tactic
98

109
/-!
1110
# Japanese Bracket

src/analysis/special_functions/pow/complex.lean

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,55 @@ lemma cpow_conj (x : ℂ) (n : ℂ) (hx : x.arg ≠ π) : x ^ conj n = conj (con
177177
by rw [conj_cpow _ _ hx, conj_conj]
178178

179179
end complex
180+
181+
section tactics
182+
/-!
183+
## Tactic extensions for complex powers
184+
-/
185+
186+
namespace norm_num
187+
188+
theorem cpow_pos (a b : ℂ) (b' : ℕ) (c : ℂ) (hb : b = b') (h : a ^ b' = c) : a ^ b = c :=
189+
by rw [← h, hb, complex.cpow_nat_cast]
190+
191+
theorem cpow_neg (a b : ℂ) (b' : ℕ) (c c' : ℂ)
192+
(hb : b = b') (h : a ^ b' = c) (hc : c⁻¹ = c') : a ^ -b = c' :=
193+
by rw [← hc, ← h, hb, complex.cpow_neg, complex.cpow_nat_cast]
194+
195+
open tactic
196+
197+
/-- Generalized version of `prove_cpow`, `prove_nnrpow`, `prove_ennrpow`. -/
198+
meta def prove_rpow' (pos neg zero : name) (α β one a b : expr) : tactic (expr × expr) := do
199+
na ← a.to_rat,
200+
icα ← mk_instance_cache α,
201+
icβ ← mk_instance_cache β,
202+
match match_sign b with
203+
| sum.inl b := do
204+
nc ← mk_instance_cache `(ℕ),
205+
(icβ, nc, b', hb) ← prove_nat_uncast icβ nc b,
206+
(icα, c, h) ← prove_pow a na icα b',
207+
cr ← c.to_rat,
208+
(icα, c', hc) ← prove_inv icα c cr,
209+
pure (c', (expr.const neg []).mk_app [a, b, b', c, c', hb, h, hc])
210+
| sum.inr ff := pure (one, expr.const zero [] a)
211+
| sum.inr tt := do
212+
nc ← mk_instance_cache `(ℕ),
213+
(icβ, nc, b', hb) ← prove_nat_uncast icβ nc b,
214+
(icα, c, h) ← prove_pow a na icα b',
215+
pure (c, (expr.const pos []).mk_app [a, b, b', c, hb, h])
216+
end
217+
218+
/-- Evaluate `complex.cpow a b` where `a` is a rational numeral and `b` is an integer. -/
219+
meta def prove_cpow : expr → expr → tactic (expr × expr) :=
220+
prove_rpow' ``cpow_pos ``cpow_neg ``complex.cpow_zero `(ℂ) `(ℂ) `(1:ℂ)
221+
222+
/-- Evaluates expressions of the form `cpow a b` and `a ^ b` in the special case where
223+
`b` is an integer and `a` is a positive rational (so it's really just a rational power). -/
224+
@[norm_num] meta def eval_cpow : expr → tactic (expr × expr)
225+
| `(@has_pow.pow _ _ complex.has_pow %%a %%b) := b.to_int >> prove_cpow a b
226+
| `(complex.cpow %%a %%b) := b.to_int >> prove_cpow a b
227+
| _ := tactic.failed
228+
229+
end norm_num
230+
231+
end tactics

src/analysis/special_functions/pow/nnreal.lean

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,3 +691,92 @@ lemma rpow_left_bijective {x : ℝ} (hx : x ≠ 0) :
691691
⟨rpow_left_injective hx, rpow_left_surjective hx⟩
692692

693693
end ennreal
694+
695+
section tactics
696+
/-!
697+
## Tactic extensions for powers on `ℝ≥0` and `ℝ≥0∞`
698+
-/
699+
700+
namespace norm_num
701+
702+
theorem nnrpow_pos (a : ℝ≥0) (b : ℝ) (b' : ℕ) (c : ℝ≥0)
703+
(hb : b = b') (h : a ^ b' = c) : a ^ b = c :=
704+
by rw [← h, hb, nnreal.rpow_nat_cast]
705+
706+
theorem nnrpow_neg (a : ℝ≥0) (b : ℝ) (b' : ℕ) (c c' : ℝ≥0)
707+
(hb : b = b') (h : a ^ b' = c) (hc : c⁻¹ = c') : a ^ -b = c' :=
708+
by rw [← hc, ← h, hb, nnreal.rpow_neg, nnreal.rpow_nat_cast]
709+
710+
theorem ennrpow_pos (a : ℝ≥0∞) (b : ℝ) (b' : ℕ) (c : ℝ≥0∞)
711+
(hb : b = b') (h : a ^ b' = c) : a ^ b = c :=
712+
by rw [← h, hb, ennreal.rpow_nat_cast]
713+
714+
theorem ennrpow_neg (a : ℝ≥0∞) (b : ℝ) (b' : ℕ) (c c' : ℝ≥0∞)
715+
(hb : b = b') (h : a ^ b' = c) (hc : c⁻¹ = c') : a ^ -b = c' :=
716+
by rw [← hc, ← h, hb, ennreal.rpow_neg, ennreal.rpow_nat_cast]
717+
718+
/-- Evaluate `nnreal.rpow a b` where `a` is a rational numeral and `b` is an integer. -/
719+
meta def prove_nnrpow : expr → expr → tactic (expr × expr) :=
720+
prove_rpow' ``nnrpow_pos ``nnrpow_neg ``nnreal.rpow_zero `(ℝ≥0) `(ℝ) `(1:ℝ≥0)
721+
722+
/-- Evaluate `ennreal.rpow a b` where `a` is a rational numeral and `b` is an integer. -/
723+
meta def prove_ennrpow : expr → expr → tactic (expr × expr) :=
724+
prove_rpow' ``ennrpow_pos ``ennrpow_neg ``ennreal.rpow_zero `(ℝ≥0∞) `(ℝ) `(1:ℝ≥0∞)
725+
726+
/-- Evaluates expressions of the form `rpow a b` and `a ^ b` in the special case where
727+
`b` is an integer and `a` is a positive rational (so it's really just a rational power). -/
728+
@[norm_num] meta def eval_nnrpow_ennrpow : expr → tactic (expr × expr)
729+
| `(@has_pow.pow _ _ nnreal.real.has_pow %%a %%b) := b.to_int >> prove_nnrpow a b
730+
| `(nnreal.rpow %%a %%b) := b.to_int >> prove_nnrpow a b
731+
| `(@has_pow.pow _ _ ennreal.real.has_pow %%a %%b) := b.to_int >> prove_ennrpow a b
732+
| `(ennreal.rpow %%a %%b) := b.to_int >> prove_ennrpow a b
733+
| _ := tactic.failed
734+
735+
end norm_num
736+
737+
namespace tactic
738+
namespace positivity
739+
740+
private lemma nnrpow_pos {a : ℝ≥0} (ha : 0 < a) (b : ℝ) : 0 < a ^ b := nnreal.rpow_pos ha
741+
742+
/-- Auxiliary definition for the `positivity` tactic to handle real powers of nonnegative reals. -/
743+
meta def prove_nnrpow (a b : expr) : tactic strictness :=
744+
do
745+
strictness_a ← core a,
746+
match strictness_a with
747+
| positive p := positive <$> mk_app ``nnrpow_pos [p, b]
748+
| _ := failed -- We already know `0 ≤ x` for all `x : ℝ≥0`
749+
end
750+
751+
private lemma ennrpow_pos {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 < b) : 0 < a ^ b :=
752+
ennreal.rpow_pos_of_nonneg ha hb.le
753+
754+
/-- Auxiliary definition for the `positivity` tactic to handle real powers of extended nonnegative
755+
reals. -/
756+
meta def prove_ennrpow (a b : expr) : tactic strictness :=
757+
do
758+
strictness_a ← core a,
759+
strictness_b ← core b,
760+
match strictness_a, strictness_b with
761+
| positive pa, positive pb := positive <$> mk_app ``ennrpow_pos [pa, pb]
762+
| positive pa, nonnegative pb := positive <$> mk_app ``ennreal.rpow_pos_of_nonneg [pa, pb]
763+
| _, _ := failed -- We already know `0 ≤ x` for all `x : ℝ≥0∞`
764+
end
765+
766+
end positivity
767+
768+
open positivity
769+
770+
/-- Extension for the `positivity` tactic: exponentiation by a real number is nonnegative when the
771+
base is nonnegative and positive when the base is positive. -/
772+
@[positivity]
773+
meta def positivity_nnrpow_ennrpow : expr → tactic strictness
774+
| `(@has_pow.pow _ _ nnreal.real.has_pow %%a %%b) := prove_nnrpow a b
775+
| `(nnreal.rpow %%a %%b) := prove_nnrpow a b
776+
| `(@has_pow.pow _ _ ennreal.real.has_pow %%a %%b) := prove_ennrpow a b
777+
| `(ennreal.rpow %%a %%b) := prove_ennrpow a b
778+
| _ := failed
779+
780+
end tactic
781+
782+
end tactics

src/analysis/special_functions/pow/real.lean

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,3 +639,79 @@ begin
639639
end
640640

641641
end real
642+
643+
section tactics
644+
/-!
645+
## Tactic extensions for real powers
646+
-/
647+
648+
namespace norm_num
649+
open tactic
650+
651+
theorem rpow_pos (a b : ℝ) (b' : ℕ) (c : ℝ) (hb : (b':ℝ) = b) (h : a ^ b' = c) : a ^ b = c :=
652+
by rw [← h, ← hb, real.rpow_nat_cast]
653+
654+
theorem rpow_neg (a b : ℝ) (b' : ℕ) (c c' : ℝ)
655+
(a0 : 0 ≤ a) (hb : (b':ℝ) = b) (h : a ^ b' = c) (hc : c⁻¹ = c') : a ^ -b = c' :=
656+
by rw [← hc, ← h, ← hb, real.rpow_neg a0, real.rpow_nat_cast]
657+
658+
/-- Evaluate `real.rpow a b` where `a` is a rational numeral and `b` is an integer.
659+
(This cannot go via the generalized version `prove_rpow'` because `rpow_pos` has a side condition;
660+
we do not attempt to evaluate `a ^ b` where `a` and `b` are both negative because it comes
661+
out to some garbage.) -/
662+
meta def prove_rpow (a b : expr) : tactic (expr × expr) := do
663+
na ← a.to_rat,
664+
ic ← mk_instance_cache `(ℝ),
665+
match match_sign b with
666+
| sum.inl b := do
667+
(ic, a0) ← guard (na ≥ 0) >> prove_nonneg ic a,
668+
nc ← mk_instance_cache `(ℕ),
669+
(ic, nc, b', hb) ← prove_nat_uncast ic nc b,
670+
(ic, c, h) ← prove_pow a na ic b',
671+
cr ← c.to_rat,
672+
(ic, c', hc) ← prove_inv ic c cr,
673+
pure (c', (expr.const ``rpow_neg []).mk_app [a, b, b', c, c', a0, hb, h, hc])
674+
| sum.inr ff := pure (`(1:ℝ), expr.const ``real.rpow_zero [] a)
675+
| sum.inr tt := do
676+
nc ← mk_instance_cache `(ℕ),
677+
(ic, nc, b', hb) ← prove_nat_uncast ic nc b,
678+
(ic, c, h) ← prove_pow a na ic b',
679+
pure (c, (expr.const ``rpow_pos []).mk_app [a, b, b', c, hb, h])
680+
end
681+
682+
/-- Evaluates expressions of the form `rpow a b` and `a ^ b` in the special case where
683+
`b` is an integer and `a` is a positive rational (so it's really just a rational power). -/
684+
@[norm_num] meta def eval_rpow : expr → tactic (expr × expr)
685+
| `(@has_pow.pow _ _ real.has_pow %%a %%b) := b.to_int >> prove_rpow a b
686+
| `(real.rpow %%a %%b) := b.to_int >> prove_rpow a b
687+
| _ := tactic.failed
688+
end norm_num
689+
690+
namespace tactic
691+
namespace positivity
692+
693+
/-- Auxiliary definition for the `positivity` tactic to handle real powers of reals. -/
694+
meta def prove_rpow (a b : expr) : tactic strictness :=
695+
do
696+
strictness_a ← core a,
697+
match strictness_a with
698+
| nonnegative p := nonnegative <$> mk_app ``real.rpow_nonneg_of_nonneg [p, b]
699+
| positive p := positive <$> mk_app ``real.rpow_pos_of_pos [p, b]
700+
| _ := failed
701+
end
702+
703+
end positivity
704+
705+
open positivity
706+
707+
/-- Extension for the `positivity` tactic: exponentiation by a real number is nonnegative when the
708+
base is nonnegative and positive when the base is positive. -/
709+
@[positivity]
710+
meta def positivity_rpow : expr → tactic strictness
711+
| `(@has_pow.pow _ _ real.has_pow %%a %%b) := prove_rpow a b
712+
| `(real.rpow %%a %%b) := prove_rpow a b
713+
| _ := failed
714+
715+
end tactic
716+
717+
end tactics

0 commit comments

Comments
 (0)