File: Mathlib/Tactic/ReduceModChar.lean

full_name: Tactic.ReduceModChar.CharP.intCast_eq_mod
code: lemma CharP.intCast_eq_mod (R : Type _) [Ring R] (p : ℕ) [CharP R p] (k : ℤ) :
    (k : R) = (k % p : ℤ) 
goal: ↑k = ↑(k % ↑p)

full_name: Tactic.ReduceModChar.CharP.isInt_of_mod
code: lemma CharP.isInt_of_mod {e' r : ℤ} {α : Type _} [Ring α] {n n' : ℕ} (inst : CharP α n) {e : α}
    (he : IsInt e e') (hn : IsNat n n') (h₂ : IsInt (e' % n') r) : IsInt e r 
goal: Mathlib.Meta.NormNum.IsInt e r

full_name: Tactic.ReduceModChar.normIntNumeral
code: /-- Given an integral expression `e : t` such that `t` is a ring of characteristic `n`,
reduce `e` modulo `n`. -/
partial def normIntNumeral {α : Q(Type u)} (n : Q(ℕ)) (e : Q($α)) (instRing : Q(Ring $α))
    (instCharP : Q(CharP $α $n)) : MetaM (Result e) 
goal: Lean.MetaM (Mathlib.Meta.NormNum.Result e)

full_name: Tactic.ReduceModChar.CharP.neg_eq_sub_one_mul
code: lemma CharP.neg_eq_sub_one_mul {α : Type _} [Ring α] (n : ℕ) (inst : CharP α n) (b : α)
    (a : ℕ) (a' : α) (p : IsNat (n - 1 : α) a) (pa : a = a') :
    -b = a' * b 
goal: -b = a' * b

full_name: Tactic.ReduceModChar.normNeg
code: /-- Given an expression `(-e) : t` such that `t` is a ring of characteristic `n`,
simplify this to `(n - 1) * e`.

This should be called only when `normIntNumeral` fails, because `normIntNumeral` would otherwise
be more useful by evaluating `-e` mod `n` to an actual numeral.
-/
@[nolint unusedHavesSuffices] -- the `=Q` is necessary for type checking
partial def normNeg {α : Q(Type u)} (n : Q(ℕ)) (e : Q($α)) (_instRing : Q(Ring $α))
    (instCharP : Q(CharP $α $n)) :
    MetaM Simp.Result 
goal: Lean.MetaM Lean.Meta.Simp.Result

full_name: Tactic.ReduceModChar.CharP.neg_mul_eq_sub_one_mul
code: lemma CharP.neg_mul_eq_sub_one_mul {α : Type _} [Ring α] (n : ℕ) (inst : CharP α n) (a b : α)
    (na : ℕ) (na' : α) (p : IsNat ((n - 1) * a : α) na) (pa : na = na') :
    -(a * b) = na' * b 
goal: -(a * b) = na' * b

full_name: Tactic.ReduceModChar.normNegCoeffMul
code: /-- Given an expression `-(a * b) : t` such that `t` is a ring of characteristic `n`,
and `a` is a numeral, simplify this to `((n - 1) * a) * b`. -/
@[nolint unusedHavesSuffices] -- the `=Q` is necessary for type checking
partial def normNegCoeffMul {α : Q(Type u)} (n : Q(ℕ)) (e : Q($α)) (_instRing : Q(Ring $α))
    (instCharP : Q(CharP $α $n)) :
    MetaM Simp.Result 
goal: Lean.MetaM Lean.Meta.Simp.Result

full_name: Tactic.ReduceModChar.TypeToCharPResult
code: /-- A `TypeToCharPResult α` indicates if `α` can be determined to be a ring of characteristic `p`.
-/
inductive TypeToCharPResult (α : Q(Type u))
  | intLike (n : Q(ℕ)) (instRing : Q(Ring $α)) (instCharP : Q(CharP $α $n))
  | failure
goal: Type

full_name: Tactic.ReduceModChar.TypeToCharPResult.failure
code: /-- A `TypeToCharPResult α` indicates if `α` can be determined to be a ring of characteristic `p`.
-/
inductive TypeToCharPResult (α : Q(Type u))
  | intLike (n : Q(ℕ)) (instRing : Q(Ring $α)) (instCharP : Q(CharP $α $n))
  | failure
goal: Tactic.ReduceModChar.TypeToCharPResult α

full_name: Tactic.ReduceModChar.TypeToCharPResult.intLike
code: /-- A `TypeToCharPResult α` indicates if `α` can be determined to be a ring of characteristic `p`.
-/
inductive TypeToCharPResult (α : Q(Type u))
  | intLike (n : Q(ℕ)) (instRing : Q(Ring $α)) (instCharP : Q(CharP $α $n))
  | failure
goal: Tactic.ReduceModChar.TypeToCharPResult α

full_name: Tactic.ReduceModChar.instInhabitedTypeToCharPResult
code: instance {α : Q(Type u)} : Inhabited (TypeToCharPResult α) 
goal: Inhabited (Tactic.ReduceModChar.TypeToCharPResult α)

full_name: Tactic.ReduceModChar.typeToCharP
code: /-- Determine the characteristic of a ring from the type.
This should be fast, so this pattern-matches on the type, rather than searching for a
`CharP` instance.
Use `typeToCharP (expensive := true)` to do more work in finding the characteristic,
in particular it will search for a `CharP` instance in the context. -/
partial def typeToCharP (expensive := false) (t : Q(Type u)) : MetaM (TypeToCharPResult t) 
goal: Lean.MetaM (Tactic.ReduceModChar.TypeToCharPResult t)

full_name: Tactic.ReduceModChar.matchAndNorm
code: /-- Given an expression `e`, determine whether it is a numeric expression in characteristic `n`,
and if so, reduce `e` modulo `n`.

This is not a `norm_num` plugin because it does not match on the syntax of `e`,
rather it matches on the type of `e`.

Use `matchAndNorm (expensive := true)` to do more work in finding the characteristic of
the type of `e`.
-/
partial def matchAndNorm (expensive := false) (e : Expr) : MetaM Simp.Result 
goal: Lean.MetaM Lean.Meta.Simp.Result

full_name: Tactic.ReduceModChar.derive
code: /-- Reduce all numeric subexpressions of `e` modulo their characteristic.

Use `derive (expensive := true)` to do more work in finding the characteristic of
the type of `e`.
-/
partial def derive (expensive := false) (e : Expr) : MetaM Simp.Result 
goal: Lean.MetaM Lean.Meta.Simp.Result

full_name: Tactic.ReduceModChar.reduceModCharTarget
code: /-- Reduce all numeric subexpressions of the goal modulo their characteristic. -/
partial def reduceModCharTarget (expensive := false) : TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Tactic.ReduceModChar.reduceModCharHyp
code: /-- Reduce all numeric subexpressions of the given hypothesis modulo their characteristic. -/
partial def reduceModCharHyp (expensive := false) (fvarId : FVarId) : TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Tactic.ReduceModChar.reduce_mod_char
code: /--
The tactic `reduce_mod_char` looks for numeric expressions in characteristic `p`
and reduces these to lie between `0` and `p`.

For example:
```
example : (5 : ZMod 4) = 1 := by reduce_mod_char
example : (X ^ 2 - 3 * X + 4 : (ZMod 4)[X]) = X ^ 2 + X := by reduce_mod_char
```

It also handles negation, turning it into multiplication by `p - 1`,
and similarly subtraction.

This tactic uses the type of the subexpression to figure out if it is indeed of positive
characteristic, for improved performance compared to trying to synthesise a `CharP` instance.
The variant `reduce_mod_char!` also tries to use `CharP R n` hypotheses in the context.
(Limitations of the typeclass system mean the tactic can't search for a `CharP R n` instance if
`n` is not yet known; use `have : CharP R n := inferInstance; reduce_mod_char!` as a workaround.)
-/
syntax (name := reduce_mod_char) "reduce_mod_char" (location)? : tactic
goal: Lean.ParserDescr

full_name: Tactic.ReduceModChar.reduce_mod_char!
code: @[inherit_doc reduce_mod_char]
syntax (name := reduce_mod_char!) "reduce_mod_char!" (location)? : tactic
goal: Lean.ParserDescr

full_name: Tactic.ReduceModChar._aux_Mathlib_Tactic_ReduceModChar___elabRules_Tactic_ReduceModChar_reduce_mod_char!_1
code: elab_rules : tactic
| `(tactic| reduce_mod_char $[$loc]?) => unsafe do
  match expandOptLocation (Lean.mkOptionalNode loc) with
  | Location.targets hyps target => do
    (← getFVarIds hyps).forM reduceModCharHyp
    if target then reduceModCharTarget
  | Location.wildcard => do
    (← (← getMainGoal).getNondepPropHyps).forM reduceModCharHyp
    reduceModCharTarget
| `(tactic| reduce_mod_char! $[$loc]?) => unsafe do
  match expandOptLocation (Lean.mkOptionalNode loc) with
  | Location.targets hyps target => do
    (← getFVarIds hyps).forM (reduceModCharHyp (expensive := true))
    if target then reduceModCharTarget (expensive := true)
  | Location.wildcard => do
    (← (← getMainGoal).getNondepPropHyps).forM (reduceModCharHyp (expensive := true))
    reduceModCharTarget (expensive := true)
goal: Lean.Elab.Tactic.Tactic

full_name: Tactic.ReduceModChar._aux_Mathlib_Tactic_ReduceModChar___elabRules_Tactic_ReduceModChar_reduce_mod_char_1
code: elab_rules : tactic
| `(tactic| reduce_mod_char $[$loc]?) => unsafe do
  match expandOptLocation (Lean.mkOptionalNode loc) with
  | Location.targets hyps target => do
    (← getFVarIds hyps).forM reduceModCharHyp
    if target then reduceModCharTarget
  | Location.wildcard => do
    (← (← getMainGoal).getNondepPropHyps).forM reduceModCharHyp
    reduceModCharTarget
| `(tactic| reduce_mod_char! $[$loc]?) => unsafe do
  match expandOptLocation (Lean.mkOptionalNode loc) with
  | Location.targets hyps target => do
    (← getFVarIds hyps).forM (reduceModCharHyp (expensive := true))
    if target then reduceModCharTarget (expensive := true)
  | Location.wildcard => do
    (← (← getMainGoal).getNondepPropHyps).forM (reduceModCharHyp (expensive := true))
    reduceModCharTarget (expensive := true)
goal: Lean.Elab.Tactic.Tactic