@@ -905,56 +905,82 @@ section Tactics
905905/-!
906906## Tactic extensions for real powers
907907-/
908-
909-
910- -- namespace NormNum
911-
912- -- open Tactic
913-
914- -- theorem rpow_pos (a b : ℝ) (b' : ℕ) (c : ℝ) (hb : (b' : ℝ) = b) (h : a ^ b' = c) :
915- -- a ^ b = c := by
916- -- rw [← h, ← hb, Real.rpow_nat_cast]
917- -- #align norm_num.rpow_pos NormNum.rpow_pos
918-
919- -- theorem rpow_neg (a b : ℝ) (b' : ℕ) (c c' : ℝ) (a0 : 0 ≤ a) (hb : (b' : ℝ) = b) (h : a ^ b' = c)
920- -- (hc : c⁻¹ = c') : a ^ (-b) = c' := by
921- -- rw [← hc, ← h, ← hb, Real.rpow_neg a0, Real.rpow_nat_cast]
922- -- #align norm_num.rpow_neg NormNum.rpow_neg
923-
924- -- /-- Evaluate `Real.rpow a b` where `a` is a rational numeral and `b` is an integer.
925- -- (This cannot go via the generalized version `prove_rpow'` because `rpow_pos` has a
926- -- side condition; we do not attempt to evaluate `a ^ b` where `a` and `b` are both negative because
927- -- it comes out to some garbage.) -/
928- -- unsafe def prove_rpow (a b : expr) : tactic (expr × expr) := do
929- -- let na ← a.to_rat
930- -- let ic ← mk_instance_cache q(ℝ)
931- -- match match_sign b with
932- -- | Sum.inl b => do
933- -- let (ic, a0) ← guard (na ≥ 0) >> prove_nonneg ic a
934- -- let nc ← mk_instance_cache q(ℕ)
935- -- let (ic, nc, b', hb) ← prove_nat_uncast ic nc b
936- -- let (ic, c, h) ← prove_pow a na ic b'
937- -- let cr ← c
938- -- let (ic, c', hc) ← prove_inv ic c cr
939- -- pure (c', (expr.const `` rpow_neg []).mk_app [a, b, b', c, c', a0, hb, h, hc])
940- -- | Sum.inr ff => pure (q((1 : ℝ)), expr.const `` Real.rpow_zero [] a)
941- -- | Sum.inr tt => do
942- -- let nc ← mk_instance_cache q(ℕ)
943- -- let (ic, nc, b', hb) ← prove_nat_uncast ic nc b
944- -- let (ic, c, h) ← prove_pow a na ic b'
945- -- pure (c, (expr.const `` rpow_pos []).mk_app [a, b, b', c, hb, h])
946- -- #align norm_num.prove_rpow norm_num.prove_rpow
947-
948- -- /-- Evaluates expressions of the form `rpow a b` and `a ^ b` in the special case where
949- -- `b` is an integer and `a` is a positive rational (so it's really just a rational power). -/
950- -- @[ norm_num ]
951- -- unsafe def eval_rpow : expr → tactic (expr × expr)
952- -- | q(@Pow.pow _ _ Real.hasPow $(a) $(b)) => b.to_int >> prove_rpow a b
953- -- | q(Real.rpow $(a) $(b)) => b.to_int >> prove_rpow a b
954- -- | _ => tactic.failed
955- -- #align norm_num.eval_rpow norm_num.eval_rpow
956-
957- -- end NormNum
908+ namespace Mathlib.Meta.NormNum
909+
910+ open Lean.Meta Qq
911+
912+ theorem isNat_rpow_pos {a b : ℝ} {nb ne : ℕ}
913+ (pb : IsNat b nb) (pe' : IsNat (a ^ nb) ne) :
914+ IsNat (a ^ b) ne := by
915+ rwa [pb.out, rpow_nat_cast]
916+
917+ theorem isNat_rpow_neg {a b : ℝ} {nb ne : ℕ}
918+ (pb : IsInt b (Int.negOfNat nb)) (pe' : IsNat (a ^ (Int.negOfNat nb)) ne) :
919+ IsNat (a ^ b) ne := by
920+ rwa [pb.out, Real.rpow_int_cast]
921+
922+ theorem isInt_rpow_pos {a b : ℝ} {nb ne : ℕ}
923+ (pb : IsNat b nb) (pe' : IsInt (a ^ nb) (Int.negOfNat ne)) :
924+ IsInt (a ^ b) (Int.negOfNat ne) := by
925+ rwa [pb.out, rpow_nat_cast]
926+
927+ theorem isInt_rpow_neg {a b : ℝ} {nb ne : ℕ}
928+ (pb : IsInt b (Int.negOfNat nb)) (pe' : IsInt (a ^ (Int.negOfNat nb)) (Int.negOfNat ne)) :
929+ IsInt (a ^ b) (Int.negOfNat ne) := by
930+ rwa [pb.out, Real.rpow_int_cast]
931+
932+ theorem isRat_rpow_pos {a b : ℝ} {nb : ℕ}
933+ {num : ℤ} {den : ℕ}
934+ (pb : IsNat b nb) (pe' : IsRat (a^nb) num den) :
935+ IsRat (a^b) num den := by
936+ rwa [pb.out, rpow_nat_cast]
937+
938+ theorem isRat_rpow_neg {a b : ℝ} {nb : ℕ}
939+ {num : ℤ} {den : ℕ}
940+ (pb : IsInt b (Int.negOfNat nb)) (pe' : IsRat (a^(Int.negOfNat nb)) num den) :
941+ IsRat (a^b) num den := by
942+ rwa [pb.out, Real.rpow_int_cast]
943+
944+ /-- Evaluates expressions of the form `a ^ b` when `a` and `b` are both reals.-/
945+ @[norm_num (_ : ℝ) ^ (_ : ℝ)]
946+ def evalRPow : NormNumExt where eval {u α} e := do
947+ let .app (.app f (a : Q(ℝ))) (b : Q(ℝ)) ← Lean.Meta.whnfR e | failure
948+ guard <|← withNewMCtxDepth <| isDefEq f q(HPow.hPow (α := ℝ) (β := ℝ))
949+ haveI' : u =QL 0 := ⟨⟩
950+ haveI' : $α =Q ℝ := ⟨⟩
951+ haveI' h : $e =Q $a ^ $b := ⟨⟩
952+ h.check
953+ let (rb : Result b) ← derive (α := q(ℝ)) b
954+ match rb with
955+ | .isBool .. | .isRat _ .. => failure
956+ | .isNat sβ nb pb =>
957+ match ← derive q($a ^ $nb) with
958+ | .isBool .. => failure
959+ | .isNat sα' ne' pe' =>
960+ assumeInstancesCommute
961+ haveI' : $sα' =Q AddGroupWithOne.toAddMonoidWithOne := ⟨⟩
962+ return .isNat sα' ne' q(isNat_rpow_pos $pb $pe')
963+ | .isNegNat sα' ne' pe' =>
964+ assumeInstancesCommute
965+ return .isNegNat sα' ne' q(isInt_rpow_pos $pb $pe')
966+ | .isRat sα' qe' nume' dene' pe' =>
967+ assumeInstancesCommute
968+ return .isRat sα' qe' nume' dene' q(isRat_rpow_pos $pb $pe')
969+ | .isNegNat sβ nb pb =>
970+ match ← derive q($a ^ (-($nb : ℤ))) with
971+ | .isBool .. => failure
972+ | .isNat sα' ne' pe' =>
973+ assumeInstancesCommute
974+ return .isNat sα' ne' q(isNat_rpow_neg $pb $pe')
975+ | .isNegNat sα' ne' pe' =>
976+ let _ := q(instRingReal)
977+ assumeInstancesCommute
978+ return .isNegNat sα' ne' q(isInt_rpow_neg $pb $pe')
979+ | .isRat sα' qe' nume' dene' pe' =>
980+ assumeInstancesCommute
981+ return .isRat sα' qe' nume' dene' q(isRat_rpow_neg $pb $pe')
982+
983+ end Mathlib.Meta.NormNum
958984
959985end Tactics
960986
0 commit comments