File: Mathlib/Tactic/Ring/Basic.lean

full_name: Mathlib.Tactic.Ring.instCommSemiringNat
code: /-- A shortcut instance for `CommSemiring ℕ` used by ring. -/
def instCommSemiringNat : CommSemiring ℕ 
goal: CommSemiring ℕ

full_name: Mathlib.Tactic.Ring.sℕ
code: /--
A typed expression of type `CommSemiring ℕ` used when we are working on
ring subexpressions of type `ℕ`.
-/
def sℕ : Q(CommSemiring ℕ) 
goal: Q(CommSemiring ℕ)

full_name: Mathlib.Tactic.Ring.instInhabitedSigmaQuotedExBase
code: instance : Inhabited (Σ e, (ExBase sα) e) 
goal: Inhabited ((e : Q(«$arg»)) × Mathlib.Tactic.Ring.ExBase sα e)

full_name: Mathlib.Tactic.Ring.instInhabitedSigmaQuotedExSum
code: instance : Inhabited (Σ e, (ExSum sα) e) 
goal: Inhabited ((e : Q(«$arg»)) × Mathlib.Tactic.Ring.ExSum sα e)

full_name: Mathlib.Tactic.Ring.instInhabitedSigmaQuotedExProd
code: instance : Inhabited (Σ e, (ExProd sα) e) 
goal: Inhabited ((e : Q(«$arg»)) × Mathlib.Tactic.Ring.ExProd sα e)

full_name: Mathlib.Tactic.Ring.Result.val
code: /--
The result of evaluating an (unnormalized) expression `e` into the type family `E`
(one of `ExSum`, `ExProd`, `ExBase`) is a (normalized) element `e'`
and a representation `E e'` for it, and a proof of `e = e'`.
-/
structure Result {α : Q(Type u)} (E : Q($α) → Type) (e : Q($α)) where
  /-- The normalized result. -/
  expr : Q($α)
  /-- The data associated to the normalization. -/
  val : E expr
  /-- A proof that the original expression is equal to the normalized result. -/
  proof : Q($e = $expr)
goal: E self.expr

full_name: Mathlib.Tactic.Ring.Result.proof
code: /--
The result of evaluating an (unnormalized) expression `e` into the type family `E`
(one of `ExSum`, `ExProd`, `ExBase`) is a (normalized) element `e'`
and a representation `E e'` for it, and a proof of `e = e'`.
-/
structure Result {α : Q(Type u)} (E : Q($α) → Type) (e : Q($α)) where
  /-- The normalized result. -/
  expr : Q($α)
  /-- The data associated to the normalization. -/
  val : E expr
  /-- A proof that the original expression is equal to the normalized result. -/
  proof : Q($e = $expr)
goal: Q(«$e» = unknown_1)

full_name: Mathlib.Tactic.Ring.Result
code: /--
The result of evaluating an (unnormalized) expression `e` into the type family `E`
(one of `ExSum`, `ExProd`, `ExBase`) is a (normalized) element `e'`
and a representation `E e'` for it, and a proof of `e = e'`.
-/
structure Result {α : Q(Type u)} (E : Q($α) → Type) (e : Q($α)) where
  /-- The normalized result. -/
  expr : Q($α)
  /-- The data associated to the normalization. -/
  val : E expr
  /-- A proof that the original expression is equal to the normalized result. -/
  proof : Q($e = $expr)
goal: Type

full_name: Mathlib.Tactic.Ring.Result.expr
code: /--
The result of evaluating an (unnormalized) expression `e` into the type family `E`
(one of `ExSum`, `ExProd`, `ExBase`) is a (normalized) element `e'`
and a representation `E e'` for it, and a proof of `e = e'`.
-/
structure Result {α : Q(Type u)} (E : Q($α) → Type) (e : Q($α)) where
  /-- The normalized result. -/
  expr : Q($α)
  /-- The data associated to the normalization. -/
  val : E expr
  /-- A proof that the original expression is equal to the normalized result. -/
  proof : Q($e = $expr)
goal: Q(«$α»)

full_name: Mathlib.Tactic.Ring.instInhabitedResultOfSigmaQuoted
code: instance {α : Q(Type u)} {E : Q($α) → Type} {e : Q($α)} [Inhabited (Σ e, E e)] :
    Inhabited (Result E e) 
goal: Inhabited (Mathlib.Tactic.Ring.Result E e)

full_name: Mathlib.Tactic.Ring.ExProd.mkNat
code: /--
Constructs the expression corresponding to `.const n`.
(The `.const` constructor does not check that the expression is correct.)
-/
def ExProd.mkNat (n : ℕ) : (e : Q($α)) × ExProd sα e 
goal: (e : Q(«$α»)) × Mathlib.Tactic.Ring.ExProd sα e

full_name: Mathlib.Tactic.Ring.ExProd.mkNegNat
code: /--
Constructs the expression corresponding to `.const (-n)`.
(The `.const` constructor does not check that the expression is correct.)
-/
def ExProd.mkNegNat (_ : Q(Ring $α)) (n : ℕ) : (e : Q($α)) × ExProd sα e 
goal: Q(Ring «$α») → ℕ → (e : Q(«$α»)) × Mathlib.Tactic.Ring.ExProd sα e

full_name: Mathlib.Tactic.Ring.ExProd.mkRat
code: /--
Constructs the expression corresponding to `.const (-n)`.
(The `.const` constructor does not check that the expression is correct.)
-/
def ExProd.mkRat (_ : Q(DivisionRing $α)) (q : ℚ) (n : Q(ℤ)) (d : Q(ℕ)) (h : Expr) :
    (e : Q($α)) × ExProd sα e 
goal: Q(DivisionRing «$α») → ℚ → Q(ℤ) → Q(ℕ) → Lean.Expr → (e : Q(«$α»)) × Mathlib.Tactic.Ring.ExProd sα e

full_name: Mathlib.Tactic.Ring.ExBase.toProd
code: /-- Embed an exponent (an `ExBase, ExProd` pair) as an `ExProd` by multiplying by 1. -/
def ExBase.toProd {α : Q(Type u)} {sα : Q(CommSemiring $α)} {a : Q($α)} {b : Q(ℕ)}
    (va : ExBase sα a) (vb : ExProd sℕ b) :
    ExProd sα q($a ^ $b * (nat_lit 1).rawCast) 
goal: Mathlib.Tactic.Ring.ExProd sα q(«$a» ^ «$b» * Nat.rawCast 1)

full_name: Mathlib.Tactic.Ring.ExProd.toSum
code: /-- Embed `ExProd` in `ExSum` by adding 0. -/
def ExProd.toSum {sα : Q(CommSemiring $α)} {e : Q($α)} (v : ExProd sα e) : ExSum sα q($e + 0) 
goal: Mathlib.Tactic.Ring.ExSum sα q(«$e» + 0)

full_name: Mathlib.Tactic.Ring.ExProd.coeff
code: /-- Get the leading coefficient of an `ExProd`. -/
def ExProd.coeff {sα : Q(CommSemiring $α)} {e : Q($α)} : ExProd sα e → ℚ
  
goal: Mathlib.Tactic.Ring.ExProd sα e → ℚ

full_name: Mathlib.Tactic.Ring.Overlap
code: /--
Two monomials are said to "overlap" if they differ by a constant factor, in which case the
constants just add. When this happens, the constant may be either zero (if the monomials cancel)
or nonzero (if they add up); the zero case is handled specially.
-/
inductive Overlap (e : Q($α)) where
  /-- The expression `e` (the sum of monomials) is equal to `0`. -/
  | zero (_ : Q(IsNat $e (nat_lit 0)))
  /-- The expression `e` (the sum of monomials) is equal to another monomial
  (with nonzero leading coefficient). -/
  | nonzero (_ : Result (ExProd sα) e)
goal: Type

full_name: Mathlib.Tactic.Ring.Overlap.nonzero
code: /--
Two monomials are said to "overlap" if they differ by a constant factor, in which case the
constants just add. When this happens, the constant may be either zero (if the monomials cancel)
or nonzero (if they add up); the zero case is handled specially.
-/
inductive Overlap (e : Q($α)) where
  /-- The expression `e` (the sum of monomials) is equal to `0`. -/
  | zero (_ : Q(IsNat $e (nat_lit 0)))
  /-- The expression `e` (the sum of monomials) is equal to another monomial
  (with nonzero leading coefficient). -/
  | nonzero (_ : Result (ExProd sα) e)
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) e → Mathlib.Tactic.Ring.Overlap sα e

full_name: Mathlib.Tactic.Ring.Overlap.zero
code: /--
Two monomials are said to "overlap" if they differ by a constant factor, in which case the
constants just add. When this happens, the constant may be either zero (if the monomials cancel)
or nonzero (if they add up); the zero case is handled specially.
-/
inductive Overlap (e : Q($α)) where
  /-- The expression `e` (the sum of monomials) is equal to `0`. -/
  | zero (_ : Q(IsNat $e (nat_lit 0)))
  /-- The expression `e` (the sum of monomials) is equal to another monomial
  (with nonzero leading coefficient). -/
  | nonzero (_ : Result (ExProd sα) e)
goal: Q(Mathlib.Meta.NormNum.IsNat «$e» 0) → Mathlib.Tactic.Ring.Overlap sα e

full_name: Mathlib.Tactic.Ring.add_overlap_pf
code: theorem add_overlap_pf (x : R) (e) (pq_pf : a + b = c) :
    x ^ e * a + x ^ e * b = x ^ e * c 
goal: x ^ e * a + x ^ e * b = x ^ e * c

full_name: Mathlib.Tactic.Ring.add_overlap_pf_zero
code: theorem add_overlap_pf_zero (x : R) (e) :
    IsNat (a + b) (nat_lit 0) → IsNat (x ^ e * a + x ^ e * b) (nat_lit 0)
  
goal: Mathlib.Meta.NormNum.IsNat (a + b) 0 → Mathlib.Meta.NormNum.IsNat (x ^ e * a + x ^ e * b) 0

full_name: Mathlib.Tactic.Ring.evalAddOverlap
code: /--
Given monomials `va, vb`, attempts to add them together to get another monomial.
If the monomials are not compatible, returns `none`.
For example, `xy + 2xy = 3xy` is a `.nonzero` overlap, while `xy + xz` returns `none`
and `xy + -xy = 0` is a `.zero` overlap.
-/
def evalAddOverlap {a b : Q($α)} (va : ExProd sα a) (vb : ExProd sα b) :
    Option (Overlap sα q($a + $b)) 
goal: Option (Mathlib.Tactic.Ring.Overlap sα q(«$a» + «$b»))

full_name: Mathlib.Tactic.Ring.add_pf_zero_add
code: theorem add_pf_zero_add (b : R) : 0 + b = b 
goal: 0 + b = b

full_name: Mathlib.Tactic.Ring.add_pf_add_zero
code: theorem add_pf_add_zero (a : R) : a + 0 = a 
goal: a + 0 = a

full_name: Mathlib.Tactic.Ring.add_pf_add_overlap
code: theorem add_pf_add_overlap
    (_ : a₁ + b₁ = c₁) (_ : a₂ + b₂ = c₂) : (a₁ + a₂ : R) + (b₁ + b₂) = c₁ + c₂ 
goal: a₁ + b₁ = c₁ → a₂ + b₂ = c₂ → a₁ + a₂ + (b₁ + b₂) = c₁ + c₂

full_name: Mathlib.Tactic.Ring.add_pf_add_overlap_zero
code: theorem add_pf_add_overlap_zero
    (h : IsNat (a₁ + b₁) (nat_lit 0)) (h₄ : a₂ + b₂ = c) : (a₁ + a₂ : R) + (b₁ + b₂) = c 
goal: a₁ + a₂ + (b₁ + b₂) = c

full_name: Mathlib.Tactic.Ring.add_pf_add_lt
code: theorem add_pf_add_lt (a₁ : R) (_ : a₂ + b = c) : (a₁ + a₂) + b = a₁ + c 
goal: a₂ + b = c → a₁ + a₂ + b = a₁ + c

full_name: Mathlib.Tactic.Ring.add_pf_add_gt
code: theorem add_pf_add_gt (b₁ : R) (_ : a + b₂ = c) : a + (b₁ + b₂) = b₁ + c 
goal: a + b₂ = c → a + (b₁ + b₂) = b₁ + c

full_name: Mathlib.Tactic.Ring.evalAdd
code: /-- Adds two polynomials `va, vb` together to get a normalized result polynomial.

* `0 + b = b`
* `a + 0 = a`
* `a * x + a * y = a * (x + y)` (for `x`, `y` coefficients; uses `evalAddOverlap`)
* `(a₁ + a₂) + (b₁ + b₂) = a₁ + (a₂ + (b₁ + b₂))` (if `a₁.lt b₁`)
* `(a₁ + a₂) + (b₁ + b₂) = b₁ + ((a₁ + a₂) + b₂)` (if not `a₁.lt b₁`)
-/
partial def evalAdd {a b : Q($α)} (va : ExSum sα a) (vb : ExSum sα b) :
    Result (ExSum sα) q($a + $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» + «$b»)

full_name: Mathlib.Tactic.Ring.one_mul
code: theorem one_mul (a : R) : (nat_lit 1).rawCast * a = a 
goal: Nat.rawCast 1 * a = a

full_name: Mathlib.Tactic.Ring.mul_one
code: theorem mul_one (a : R) : a * (nat_lit 1).rawCast = a 
goal: a * Nat.rawCast 1 = a

full_name: Mathlib.Tactic.Ring.mul_pf_left
code: theorem mul_pf_left (a₁ : R) (a₂) (_ : a₃ * b = c) :
    (a₁ ^ a₂ * a₃ : R) * b = a₁ ^ a₂ * c 
goal: a₃ * b = c → a₁ ^ a₂ * a₃ * b = a₁ ^ a₂ * c

full_name: Mathlib.Tactic.Ring.mul_pf_right
code: theorem mul_pf_right (b₁ : R) (b₂) (_ : a * b₃ = c) :
    a * (b₁ ^ b₂ * b₃) = b₁ ^ b₂ * c 
goal: a * b₃ = c → a * (b₁ ^ b₂ * b₃) = b₁ ^ b₂ * c

full_name: Mathlib.Tactic.Ring.mul_pp_pf_overlap
code: theorem mul_pp_pf_overlap {ea eb e : ℕ} (x : R) (_ : ea + eb = e) (_ : a₂ * b₂ = c) :
    (x ^ ea * a₂ : R) * (x ^ eb * b₂) = x ^ e * c 
goal: ea + eb = e → a₂ * b₂ = c → x ^ ea * a₂ * (x ^ eb * b₂) = x ^ e * c

full_name: Mathlib.Tactic.Ring.evalMulProd
code: /-- Multiplies two monomials `va, vb` together to get a normalized result monomial.

* `x * y = (x * y)` (for `x`, `y` coefficients)
* `x * (b₁ * b₂) = b₁ * (b₂ * x)` (for `x` coefficient)
* `(a₁ * a₂) * y = a₁ * (a₂ * y)` (for `y` coefficient)
* `(x ^ ea * a₂) * (x ^ eb * b₂) = x ^ (ea + eb) * (a₂ * b₂)`
    (if `ea` and `eb` are identical except coefficient)
* `(a₁ * a₂) * (b₁ * b₂) = a₁ * (a₂ * (b₁ * b₂))` (if `a₁.lt b₁`)
* `(a₁ * a₂) * (b₁ * b₂) = b₁ * ((a₁ * a₂) * b₂)` (if not `a₁.lt b₁`)
-/
partial def evalMulProd {a b : Q($α)} (va : ExProd sα a) (vb : ExProd sα b) :
    Result (ExProd sα) q($a * $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) q(«$a» * «$b»)

full_name: Mathlib.Tactic.Ring.mul_zero
code: theorem mul_zero (a : R) : a * 0 = 0 
goal: a * 0 = 0

full_name: Mathlib.Tactic.Ring.mul_add
code: theorem mul_add {d : R} (_ : (a : R) * b₁ = c₁) (_ : a * b₂ = c₂) (_ : c₁ + 0 + c₂ = d) :
    a * (b₁ + b₂) = d 
goal: a * b₁ = c₁ → a * b₂ = c₂ → c₁ + 0 + c₂ = d → a * (b₁ + b₂) = d

full_name: Mathlib.Tactic.Ring.evalMul₁
code: /-- Multiplies a monomial `va` to a polynomial `vb` to get a normalized result polynomial.

* `a * 0 = 0`
* `a * (b₁ + b₂) = (a * b₁) + (a * b₂)`
-/
def evalMul₁ {a b : Q($α)} (va : ExProd sα a) (vb : ExSum sα b) : Result (ExSum sα) q($a * $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» * «$b»)

full_name: Mathlib.Tactic.Ring.zero_mul
code: theorem zero_mul (b : R) : 0 * b = 0 
goal: 0 * b = 0

full_name: Mathlib.Tactic.Ring.add_mul
code: theorem add_mul {d : R} (_ : (a₁ : R) * b = c₁) (_ : a₂ * b = c₂) (_ : c₁ + c₂ = d) :
    (a₁ + a₂) * b = d 
goal: a₁ * b = c₁ → a₂ * b = c₂ → c₁ + c₂ = d → (a₁ + a₂) * b = d

full_name: Mathlib.Tactic.Ring.evalMul
code: /-- Multiplies two polynomials `va, vb` together to get a normalized result polynomial.

* `0 * b = 0`
* `(a₁ + a₂) * b = (a₁ * b) + (a₂ * b)`
-/
def evalMul {a b : Q($α)} (va : ExSum sα a) (vb : ExSum sα b) : Result (ExSum sα) q($a * $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» * «$b»)

full_name: Mathlib.Tactic.Ring.natCast_nat
code: theorem natCast_nat (n) : ((Nat.rawCast n : ℕ) : R) = Nat.rawCast n 
goal: ↑n.rawCast = n.rawCast

full_name: Mathlib.Tactic.Ring.natCast_mul
code: theorem natCast_mul {a₁ a₃ : ℕ} (a₂) (_ : ((a₁ : ℕ) : R) = b₁)
    (_ : ((a₃ : ℕ) : R) = b₃) : ((a₁ ^ a₂ * a₃ : ℕ) : R) = b₁ ^ a₂ * b₃ 
goal: ↑a₁ = b₁ → ↑a₃ = b₃ → ↑(a₁ ^ a₂ * a₃) = b₁ ^ a₂ * b₃

full_name: Mathlib.Tactic.Ring.natCast_zero
code: theorem natCast_zero : ((0 : ℕ) : R) = 0 
goal: ↑0 = 0

full_name: Mathlib.Tactic.Ring.natCast_add
code: theorem natCast_add {a₁ a₂ : ℕ}
    (_ : ((a₁ : ℕ) : R) = b₁) (_ : ((a₂ : ℕ) : R) = b₂) : ((a₁ + a₂ : ℕ) : R) = b₁ + b₂ 
goal: ↑a₁ = b₁ → ↑a₂ = b₂ → ↑(a₁ + a₂) = b₁ + b₂

full_name: Mathlib.Tactic.Ring.smul_nat
code: theorem smul_nat {a b c : ℕ} (_ : (a * b : ℕ) = c) : a • b = c 
goal: a * b = c → a • b = c

full_name: Mathlib.Tactic.Ring.smul_eq_cast
code: theorem smul_eq_cast {a : ℕ} (_ : ((a : ℕ) : R) = a') (_ : a' * b = c) : a • b = c 
goal: ↑a = a' → a' * b = c → a • b = c

full_name: Mathlib.Tactic.Ring.evalNSMul
code: /-- Constructs the scalar multiplication `n • a`, where both `n : ℕ` and `a : α` are normalized
polynomial expressions.

* `a • b = a * b` if `α = ℕ`
* `a • b = ↑a * b` otherwise
-/
def evalNSMul {a : Q(ℕ)} {b : Q($α)} (va : ExSum sℕ a) (vb : ExSum sα b) :
    AtomM (Result (ExSum sα) q($a • $b)) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» • «$b»))

full_name: Mathlib.Tactic.Ring.neg_one_mul
code: theorem neg_one_mul {R} [Ring R] {a b : R} (_ : (Int.negOfNat (nat_lit 1)).rawCast * a = b) :
    -a = b 
goal: (Int.negOfNat 1).rawCast * a = b → -a = b

full_name: Mathlib.Tactic.Ring.neg_mul
code: theorem neg_mul {R} [Ring R] (a₁ : R) (a₂) {a₃ b : R}
    (_ : -a₃ = b) : -(a₁ ^ a₂ * a₃) = a₁ ^ a₂ * b 
goal: -a₃ = b → -(a₁ ^ a₂ * a₃) = a₁ ^ a₂ * b

full_name: Mathlib.Tactic.Ring.evalNegProd
code: /-- Negates a monomial `va` to get another monomial.

* `-c = (-c)` (for `c` coefficient)
* `-(a₁ * a₂) = a₁ * -a₂`
-/
def evalNegProd {a : Q($α)} (rα : Q(Ring $α)) (va : ExProd sα a) : Result (ExProd sα) q(-$a) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) q(-«$a»)

full_name: Mathlib.Tactic.Ring.neg_zero
code: theorem neg_zero {R} [Ring R] : -(0 : R) = 0 
goal: -0 = 0

full_name: Mathlib.Tactic.Ring.neg_add
code: theorem neg_add {R} [Ring R] {a₁ a₂ b₁ b₂ : R}
    (_ : -a₁ = b₁) (_ : -a₂ = b₂) : -(a₁ + a₂) = b₁ + b₂ 
goal: -a₁ = b₁ → -a₂ = b₂ → -(a₁ + a₂) = b₁ + b₂

full_name: Mathlib.Tactic.Ring.evalNeg
code: /-- Negates a polynomial `va` to get another polynomial.

* `-0 = 0` (for `c` coefficient)
* `-(a₁ + a₂) = -a₁ + -a₂`
-/
def evalNeg {a : Q($α)} (rα : Q(Ring $α)) (va : ExSum sα a) : Result (ExSum sα) q(-$a) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(-«$a»)

full_name: Mathlib.Tactic.Ring.sub_pf
code: theorem sub_pf {R} [Ring R] {a b c d : R}
    (_ : -b = c) (_ : a + c = d) : a - b = d 
goal: -b = c → a + c = d → a - b = d

full_name: Mathlib.Tactic.Ring.evalSub
code: /-- Subtracts two polynomials `va, vb` to get a normalized result polynomial.

* `a - b = a + -b`
-/
def evalSub {α : Q(Type u)} (sα : Q(CommSemiring $α)) {a b : Q($α)}
    (rα : Q(Ring $α)) (va : ExSum sα a) (vb : ExSum sα b) : Result (ExSum sα) q($a - $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» - «$b»)

full_name: Mathlib.Tactic.Ring.pow_prod_atom
code: theorem pow_prod_atom (a : R) (b) : a ^ b = (a + 0) ^ b * (nat_lit 1).rawCast 
goal: a ^ b = (a + 0) ^ b * Nat.rawCast 1

full_name: Mathlib.Tactic.Ring.evalPowProdAtom
code: /--
The fallback case for exponentiating polynomials is to use `ExBase.toProd` to just build an
exponent expression. (This has a slightly different normalization than `evalPowAtom` because
the input types are different.)

* `x ^ e = (x + 0) ^ e * 1`
-/
def evalPowProdAtom {a : Q($α)} {b : Q(ℕ)} (va : ExProd sα a) (vb : ExProd sℕ b) :
    Result (ExProd sα) q($a ^ $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) q(«$a» ^ «$b»)

full_name: Mathlib.Tactic.Ring.pow_atom
code: theorem pow_atom (a : R) (b) : a ^ b = a ^ b * (nat_lit 1).rawCast + 0 
goal: a ^ b = a ^ b * Nat.rawCast 1 + 0

full_name: Mathlib.Tactic.Ring.evalPowAtom
code: /--
The fallback case for exponentiating polynomials is to use `ExBase.toProd` to just build an
exponent expression.

* `x ^ e = x ^ e * 1 + 0`
-/
def evalPowAtom {a : Q($α)} {b : Q(ℕ)} (va : ExBase sα a) (vb : ExProd sℕ b) :
    Result (ExSum sα) q($a ^ $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» ^ «$b»)

full_name: Mathlib.Tactic.Ring.const_pos
code: theorem const_pos (n : ℕ) (h : Nat.ble 1 n = true) : 0 < (n.rawCast : ℕ) 
goal: 0 < n.rawCast

full_name: Mathlib.Tactic.Ring.mul_exp_pos
code: theorem mul_exp_pos {a₁ a₂ : ℕ} (n) (h₁ : 0 < a₁) (h₂ : 0 < a₂) : 0 < a₁ ^ n * a₂ 
goal: 0 < a₁ ^ n * a₂

full_name: Mathlib.Tactic.Ring.add_pos_left
code: theorem add_pos_left {a₁ : ℕ} (a₂) (h : 0 < a₁) : 0 < a₁ + a₂ 
goal: 0 < a₁ + a₂

full_name: Mathlib.Tactic.Ring.add_pos_right
code: theorem add_pos_right {a₂ : ℕ} (a₁) (h : 0 < a₂) : 0 < a₁ + a₂ 
goal: 0 < a₁ + a₂

full_name: Mathlib.Tactic.Ring.pow_one
code: theorem pow_one (a : R) : a ^ nat_lit 1 = a 
goal: a ^ 1 = a

full_name: Mathlib.Tactic.Ring.pow_bit0
code: theorem pow_bit0 {k : ℕ} (_ : (a : R) ^ k = b) (_ : b * b = c) :
    a ^ (Nat.mul (nat_lit 2) k) = c 
goal: a ^ k = b → b * b = c → a ^ Nat.mul 2 k = c

full_name: Mathlib.Tactic.Ring.pow_bit1
code: theorem pow_bit1 {k : ℕ} {d : R} (_ : (a : R) ^ k = b) (_ : b * b = c) (_ : c * a = d) :
    a ^ (Nat.add (Nat.mul (nat_lit 2) k) (nat_lit 1)) = d 
goal: a ^ k = b → b * b = c → c * a = d → a ^ (Nat.mul 2 k).add 1 = d

full_name: Mathlib.Tactic.Ring.evalPowNat
code: /--
The main case of exponentiation of ring expressions is when `va` is a polynomial and `n` is a
nonzero literal expression, like `(x + y)^5`. In this case we work out the polynomial completely
into a sum of monomials.

* `x ^ 1 = x`
* `x ^ (2*n) = x ^ n * x ^ n`
* `x ^ (2*n+1) = x ^ n * x ^ n * x`
-/
partial def evalPowNat {a : Q($α)} (va : ExSum sα a) (n : Q(ℕ)) : Result (ExSum sα) q($a ^ $n) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» ^ «$n»)

full_name: Mathlib.Tactic.Ring.one_pow
code: theorem one_pow (b : ℕ) : ((nat_lit 1).rawCast : R) ^ b = (nat_lit 1).rawCast 
goal: Nat.rawCast 1 ^ b = Nat.rawCast 1

full_name: Mathlib.Tactic.Ring.mul_pow
code: theorem mul_pow {ea₁ b c₁ : ℕ} {xa₁ : R}
    (_ : ea₁ * b = c₁) (_ : a₂ ^ b = c₂) : (xa₁ ^ ea₁ * a₂ : R) ^ b = xa₁ ^ c₁ * c₂ 
goal: ea₁ * b = c₁ → a₂ ^ b = c₂ → (xa₁ ^ ea₁ * a₂) ^ b = xa₁ ^ c₁ * c₂

full_name: Mathlib.Tactic.Ring.evalPowProd
code: /-- There are several special cases when exponentiating monomials:

* `1 ^ n = 1`
* `x ^ y = (x ^ y)` when `x` and `y` are constants
* `(a * b) ^ e = a ^ e * b ^ e`

In all other cases we use `evalPowProdAtom`.
-/
def evalPowProd {a : Q($α)} {b : Q(ℕ)} (va : ExProd sα a) (vb : ExProd sℕ b) :
    Result (ExProd sα) q($a ^ $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) q(«$a» ^ «$b»)

full_name: Mathlib.Tactic.Ring.ExtractCoeff
code: /--
The result of `extractCoeff` is a numeral and a proof that the original expression
factors by this numeral.
-/
structure ExtractCoeff (e : Q(ℕ)) where
  /-- A raw natural number literal. -/
  k : Q(ℕ)
  /-- The result of extracting the coefficient is a monic monomial. -/
  e' : Q(ℕ)
  /-- `e'` is a monomial. -/
  ve' : ExProd sℕ e'
  /-- The proof that `e` splits into the coefficient `k` and the monic monomial `e'`. -/
  p : Q($e = $e' * $k)
goal: Type

full_name: Mathlib.Tactic.Ring.ExtractCoeff.k
code: /--
The result of `extractCoeff` is a numeral and a proof that the original expression
factors by this numeral.
-/
structure ExtractCoeff (e : Q(ℕ)) where
  /-- A raw natural number literal. -/
  k : Q(ℕ)
  /-- The result of extracting the coefficient is a monic monomial. -/
  e' : Q(ℕ)
  /-- `e'` is a monomial. -/
  ve' : ExProd sℕ e'
  /-- The proof that `e` splits into the coefficient `k` and the monic monomial `e'`. -/
  p : Q($e = $e' * $k)
goal: Q(ℕ)

full_name: Mathlib.Tactic.Ring.ExtractCoeff.p
code: /--
The result of `extractCoeff` is a numeral and a proof that the original expression
factors by this numeral.
-/
structure ExtractCoeff (e : Q(ℕ)) where
  /-- A raw natural number literal. -/
  k : Q(ℕ)
  /-- The result of extracting the coefficient is a monic monomial. -/
  e' : Q(ℕ)
  /-- `e'` is a monomial. -/
  ve' : ExProd sℕ e'
  /-- The proof that `e` splits into the coefficient `k` and the monic monomial `e'`. -/
  p : Q($e = $e' * $k)
goal: Q(«$e» = unknown_1 * unknown_2)

full_name: Mathlib.Tactic.Ring.ExtractCoeff.ve'
code: /--
The result of `extractCoeff` is a numeral and a proof that the original expression
factors by this numeral.
-/
structure ExtractCoeff (e : Q(ℕ)) where
  /-- A raw natural number literal. -/
  k : Q(ℕ)
  /-- The result of extracting the coefficient is a monic monomial. -/
  e' : Q(ℕ)
  /-- `e'` is a monomial. -/
  ve' : ExProd sℕ e'
  /-- The proof that `e` splits into the coefficient `k` and the monic monomial `e'`. -/
  p : Q($e = $e' * $k)
goal: Mathlib.Tactic.Ring.ExProd Mathlib.Tactic.Ring.sℕ self.e'

full_name: Mathlib.Tactic.Ring.ExtractCoeff.e'
code: /--
The result of `extractCoeff` is a numeral and a proof that the original expression
factors by this numeral.
-/
structure ExtractCoeff (e : Q(ℕ)) where
  /-- A raw natural number literal. -/
  k : Q(ℕ)
  /-- The result of extracting the coefficient is a monic monomial. -/
  e' : Q(ℕ)
  /-- `e'` is a monomial. -/
  ve' : ExProd sℕ e'
  /-- The proof that `e` splits into the coefficient `k` and the monic monomial `e'`. -/
  p : Q($e = $e' * $k)
goal: Q(ℕ)

full_name: Mathlib.Tactic.Ring.coeff_one
code: theorem coeff_one (k : ℕ) : k.rawCast = (nat_lit 1).rawCast * k 
goal: k.rawCast = Nat.rawCast 1 * k

full_name: Mathlib.Tactic.Ring.coeff_mul
code: theorem coeff_mul {a₃ c₂ k : ℕ}
    (a₁ a₂ : ℕ) (_ : a₃ = c₂ * k) : a₁ ^ a₂ * a₃ = (a₁ ^ a₂ * c₂) * k 
goal: a₃ = c₂ * k → a₁ ^ a₂ * a₃ = a₁ ^ a₂ * c₂ * k

full_name: Mathlib.Tactic.Ring.extractCoeff
code: /-- Given a monomial expression `va`, splits off the leading coefficient `k` and the remainder
`e'`, stored in the `ExtractCoeff` structure.

* `c = 1 * c` (if `c` is a constant)
* `a * b = (a * b') * k` if `b = b' * k`
-/
def extractCoeff {a : Q(ℕ)} (va : ExProd sℕ a) : ExtractCoeff a 
goal: Mathlib.Tactic.Ring.ExtractCoeff a

full_name: Mathlib.Tactic.Ring.pow_one_cast
code: theorem pow_one_cast (a : R) : a ^ (nat_lit 1).rawCast = a 
goal: a ^ Nat.rawCast 1 = a

full_name: Mathlib.Tactic.Ring.zero_pow
code: theorem zero_pow {b : ℕ} (_ : 0 < b) : (0 : R) ^ b = 0 
goal: 0 < b → 0 ^ b = 0

full_name: Mathlib.Tactic.Ring.single_pow
code: theorem single_pow {b : ℕ} (_ : (a : R) ^ b = c) : (a + 0) ^ b = c + 0 
goal: a ^ b = c → (a + 0) ^ b = c + 0

full_name: Mathlib.Tactic.Ring.pow_nat
code: theorem pow_nat {b c k : ℕ} {d e : R} (_ : b = c * k) (_ : a ^ c = d) (_ : d ^ k = e) :
    (a : R) ^ b = e 
goal: b = c * k → a ^ c = d → d ^ k = e → a ^ b = e

full_name: Mathlib.Tactic.Ring.evalPow₁
code: /-- Exponentiates a polynomial `va` by a monomial `vb`, including several special cases.

* `a ^ 1 = a`
* `0 ^ e = 0` if `0 < e`
* `(a + 0) ^ b = a ^ b` computed using `evalPowProd`
* `a ^ b = (a ^ b') ^ k` if `b = b' * k` and `k > 1`

Otherwise `a ^ b` is just encoded as `a ^ b * 1 + 0` using `evalPowAtom`.
-/
partial def evalPow₁ {a : Q($α)} {b : Q(ℕ)} (va : ExSum sα a) (vb : ExProd sℕ b) :
    Result (ExSum sα) q($a ^ $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» ^ «$b»)

full_name: Mathlib.Tactic.Ring.pow_zero
code: theorem pow_zero (a : R) : a ^ 0 = (nat_lit 1).rawCast + 0 
goal: a ^ 0 = Nat.rawCast 1 + 0

full_name: Mathlib.Tactic.Ring.pow_add
code: theorem pow_add {b₁ b₂ : ℕ} {d : R}
    (_ : a ^ b₁ = c₁) (_ : a ^ b₂ = c₂) (_ : c₁ * c₂ = d) : (a : R) ^ (b₁ + b₂) = d 
goal: a ^ b₁ = c₁ → a ^ b₂ = c₂ → c₁ * c₂ = d → a ^ (b₁ + b₂) = d

full_name: Mathlib.Tactic.Ring.evalPow
code: /-- Exponentiates two polynomials `va, vb`.

* `a ^ 0 = 1`
* `a ^ (b₁ + b₂) = a ^ b₁ * a ^ b₂`
-/
def evalPow {a : Q($α)} {b : Q(ℕ)} (va : ExSum sα a) (vb : ExSum sℕ b) :
    Result (ExSum sα) q($a ^ $b) 
goal: Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» ^ «$b»)

full_name: Mathlib.Tactic.Ring.Cache.dα
code: /-- This cache contains data required by the `ring` tactic during execution. -/
structure Cache {α : Q(Type u)} (sα : Q(CommSemiring $α)) :=
  /-- A ring instance on `α`, if available. -/
  rα : Option Q(Ring $α)
  /-- A division ring instance on `α`, if available. -/
  dα : Option Q(DivisionRing $α)
  /-- A characteristic zero ring instance on `α`, if available. -/
  czα : Option Q(CharZero $α)
goal: Option Q(DivisionRing «$α»)

full_name: Mathlib.Tactic.Ring.Cache
code: /-- This cache contains data required by the `ring` tactic during execution. -/
structure Cache {α : Q(Type u)} (sα : Q(CommSemiring $α)) :=
  /-- A ring instance on `α`, if available. -/
  rα : Option Q(Ring $α)
  /-- A division ring instance on `α`, if available. -/
  dα : Option Q(DivisionRing $α)
  /-- A characteristic zero ring instance on `α`, if available. -/
  czα : Option Q(CharZero $α)
goal: Type

full_name: Mathlib.Tactic.Ring.Cache.czα
code: /-- This cache contains data required by the `ring` tactic during execution. -/
structure Cache {α : Q(Type u)} (sα : Q(CommSemiring $α)) :=
  /-- A ring instance on `α`, if available. -/
  rα : Option Q(Ring $α)
  /-- A division ring instance on `α`, if available. -/
  dα : Option Q(DivisionRing $α)
  /-- A characteristic zero ring instance on `α`, if available. -/
  czα : Option Q(CharZero $α)
goal: Option Q(CharZero «$α»)

full_name: Mathlib.Tactic.Ring.Cache.rα
code: /-- This cache contains data required by the `ring` tactic during execution. -/
structure Cache {α : Q(Type u)} (sα : Q(CommSemiring $α)) :=
  /-- A ring instance on `α`, if available. -/
  rα : Option Q(Ring $α)
  /-- A division ring instance on `α`, if available. -/
  dα : Option Q(DivisionRing $α)
  /-- A characteristic zero ring instance on `α`, if available. -/
  czα : Option Q(CharZero $α)
goal: Option Q(Ring «$α»)

full_name: Mathlib.Tactic.Ring.mkCache
code: /-- Create a new cache for `α` by doing the necessary instance searches. -/
def mkCache {α : Q(Type u)} (sα : Q(CommSemiring $α)) : MetaM (Cache sα) 
goal: Lean.MetaM (Mathlib.Tactic.Ring.Cache sα)

full_name: Mathlib.Tactic.Ring.cast_pos
code: theorem cast_pos {n : ℕ} : IsNat (a : R) n → a = n.rawCast + 0
  
goal: Mathlib.Meta.NormNum.IsNat a n → a = n.rawCast + 0

full_name: Mathlib.Tactic.Ring.cast_zero
code: theorem cast_zero : IsNat (a : R) (nat_lit 0) → a = 0
  
goal: Mathlib.Meta.NormNum.IsNat a 0 → a = 0

full_name: Mathlib.Tactic.Ring.cast_neg
code: theorem cast_neg {n : ℕ} {R} [Ring R] {a : R} :
    IsInt a (.negOfNat n) → a = (Int.negOfNat n).rawCast + 0
  
goal: Mathlib.Meta.NormNum.IsInt a (Int.negOfNat n) → a = (Int.negOfNat n).rawCast + 0

full_name: Mathlib.Tactic.Ring.cast_rat
code: theorem cast_rat {n : ℤ} {d : ℕ} {R} [DivisionRing R] {a : R} :
    IsRat a n d → a = Rat.rawCast n d + 0
  
goal: Mathlib.Meta.NormNum.IsRat a n d → a = Rat.rawCast n d + 0

full_name: Mathlib.Tactic.Ring.evalCast
code: /-- Converts a proof by `norm_num` that `e` is a numeral, into a normalization as a monomial:

* `e = 0` if `norm_num` returns `IsNat e 0`
* `e = Nat.rawCast n + 0` if `norm_num` returns `IsNat e n`
* `e = Int.rawCast n + 0` if `norm_num` returns `IsInt e n`
* `e = Rat.rawCast n d + 0` if `norm_num` returns `IsRat e n d`
-/
def evalCast {α : Q(Type u)} (sα : Q(CommSemiring $α)) {e : Q($α)} :
    NormNum.Result e → Option (Result (ExSum sα) e)
  
goal: Mathlib.Meta.NormNum.Result e → Option (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) e)

full_name: Mathlib.Tactic.Ring.toProd_pf
code: theorem toProd_pf (p : (a : R) = a') :
    a = a' ^ (nat_lit 1).rawCast * (nat_lit 1).rawCast 
goal: a = a' ^ Nat.rawCast 1 * Nat.rawCast 1

full_name: Mathlib.Tactic.Ring.atom_pf
code: theorem atom_pf (a : R) : a = a ^ (nat_lit 1).rawCast * (nat_lit 1).rawCast + 0 
goal: a = a ^ Nat.rawCast 1 * Nat.rawCast 1 + 0

full_name: Mathlib.Tactic.Ring.atom_pf'
code: theorem atom_pf' (p : (a : R) = a') :
    a = a' ^ (nat_lit 1).rawCast * (nat_lit 1).rawCast + 0 
goal: a = a' ^ Nat.rawCast 1 * Nat.rawCast 1 + 0

full_name: Mathlib.Tactic.Ring.evalAtom
code: /--
Evaluates an atom, an expression where `ring` can find no additional structure.

* `a = a ^ 1 * 1 + 0`
-/
def evalAtom (e : Q($α)) : AtomM (Result (ExSum sα) e) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) e)

full_name: Mathlib.Tactic.Ring.inv_mul
code: theorem inv_mul {R} [DivisionRing R] {a₁ a₂ a₃ b₁ b₃ c}
    (_ : (a₁⁻¹ : R) = b₁) (_ : (a₃⁻¹ : R) = b₃)
    (_ : b₃ * (b₁ ^ a₂ * (nat_lit 1).rawCast) = c) :
    (a₁ ^ a₂ * a₃ : R)⁻¹ = c 
goal: a₁⁻¹ = b₁ → a₃⁻¹ = b₃ → b₃ * (b₁ ^ a₂ * Nat.rawCast 1) = c → (a₁ ^ a₂ * a₃)⁻¹ = c

full_name: Mathlib.Tactic.Ring.inv_zero
code: nonrec theorem inv_zero {R} [DivisionRing R] : (0 : R)⁻¹ = 0 
goal: 0⁻¹ = 0

full_name: Mathlib.Tactic.Ring.inv_single
code: theorem inv_single {R} [DivisionRing R] {a b : R}
    (_ : (a : R)⁻¹ = b) : (a + 0)⁻¹ = b + 0 
goal: a⁻¹ = b → (a + 0)⁻¹ = b + 0

full_name: Mathlib.Tactic.Ring.inv_add
code: theorem inv_add {a₁ a₂ : ℕ} (_ : ((a₁ : ℕ) : R) = b₁) (_ : ((a₂ : ℕ) : R) = b₂) :
    ((a₁ + a₂ : ℕ) : R) = b₁ + b₂ 
goal: ↑a₁ = b₁ → ↑a₂ = b₂ → ↑(a₁ + a₂) = b₁ + b₂

full_name: Mathlib.Tactic.Ring.evalInvAtom
code: /-- Applies `⁻¹` to a polynomial to get an atom. -/
def evalInvAtom (a : Q($α)) : AtomM (Result (ExBase sα) q($a⁻¹)) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExBase sα) q(«$a»⁻¹))

full_name: Mathlib.Tactic.Ring.ExProd.evalInv
code: /-- Inverts a polynomial `va` to get a normalized result polynomial.

* `c⁻¹ = (c⁻¹)` if `c` is a constant
* `(a ^ b * c)⁻¹ = a⁻¹ ^ b * c⁻¹`
-/
def ExProd.evalInv {a : Q($α)} (czα : Option Q(CharZero $α)) (va : ExProd sα a) :
    AtomM (Result (ExProd sα) q($a⁻¹)) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) q(«$a»⁻¹))

full_name: Mathlib.Tactic.Ring.ExSum.evalInv
code: /-- Inverts a polynomial `va` to get a normalized result polynomial.

* `0⁻¹ = 0`
* `a⁻¹ = (a⁻¹)` if `a` is a nontrivial sum
-/
def ExSum.evalInv {a : Q($α)} (czα : Option Q(CharZero $α)) (va : ExSum sα a) :
    AtomM (Result (ExSum sα) q($a⁻¹)) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a»⁻¹))

full_name: Mathlib.Tactic.Ring.div_pf
code: theorem div_pf {R} [DivisionRing R] {a b c d : R} (_ : b⁻¹ = c) (_ : a * c = d) : a / b = d 
goal: b⁻¹ = c → a * c = d → a / b = d

full_name: Mathlib.Tactic.Ring.evalDiv
code: /-- Divides two polynomials `va, vb` to get a normalized result polynomial.

* `a / b = a * b⁻¹`
-/
def evalDiv {a b : Q($α)} (rα : Q(DivisionRing $α)) (czα : Option Q(CharZero $α)) (va : ExSum sα a)
    (vb : ExSum sα b) : AtomM (Result (ExSum sα) q($a / $b)) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) q(«$a» / «$b»))

full_name: Mathlib.Tactic.Ring.add_congr
code: theorem add_congr (_ : a = a') (_ : b = b') (_ : a' + b' = c) : (a + b : R) = c 
goal: a = a' → b = b' → a' + b' = c → a + b = c

full_name: Mathlib.Tactic.Ring.mul_congr
code: theorem mul_congr (_ : a = a') (_ : b = b') (_ : a' * b' = c) : (a * b : R) = c 
goal: a = a' → b = b' → a' * b' = c → a * b = c

full_name: Mathlib.Tactic.Ring.nsmul_congr
code: theorem nsmul_congr {a a' : ℕ} (_ : (a : ℕ) = a') (_ : b = b') (_ : a' • b' = c) :
    (a • (b : R)) = c 
goal: a = a' → b = b' → a' • b' = c → a • b = c

full_name: Mathlib.Tactic.Ring.pow_congr
code: theorem pow_congr {b b' : ℕ} (_ : a = a') (_ : b = b')
    (_ : a' ^ b' = c) : (a ^ b : R) = c 
goal: a = a' → b = b' → a' ^ b' = c → a ^ b = c

full_name: Mathlib.Tactic.Ring.neg_congr
code: theorem neg_congr {R} [Ring R] {a a' b : R} (_ : a = a')
    (_ : -a' = b) : (-a : R) = b 
goal: a = a' → -a' = b → -a = b

full_name: Mathlib.Tactic.Ring.sub_congr
code: theorem sub_congr {R} [Ring R] {a a' b b' c : R} (_ : a = a') (_ : b = b')
    (_ : a' - b' = c) : (a - b : R) = c 
goal: a = a' → b = b' → a' - b' = c → a - b = c

full_name: Mathlib.Tactic.Ring.inv_congr
code: theorem inv_congr {R} [DivisionRing R] {a a' b : R} (_ : a = a')
    (_ : a'⁻¹ = b) : (a⁻¹ : R) = b 
goal: a = a' → a'⁻¹ = b → a⁻¹ = b

full_name: Mathlib.Tactic.Ring.div_congr
code: theorem div_congr {R} [DivisionRing R] {a a' b b' c : R} (_ : a = a') (_ : b = b')
    (_ : a' / b' = c) : (a / b : R) = c 
goal: a = a' → b = b' → a' / b' = c → a / b = c

full_name: Mathlib.Tactic.Ring.Cache.nat
code: /-- A precomputed `Cache` for `ℕ`. -/
def Cache.nat : Cache sℕ 
goal: Mathlib.Tactic.Ring.Cache Mathlib.Tactic.Ring.sℕ

full_name: Mathlib.Tactic.Ring.isAtomOrDerivable
code: /-- Checks whether `e` would be processed by `eval` as a ring expression,
or otherwise if it is an atom or something simplifiable via `norm_num`.

We use this in `ring_nf` to avoid rewriting atoms unnecessarily.

Returns:
* `none` if `eval` would process `e` as an algebraic ring expression
* `some none` if `eval` would treat `e` as an atom.
* `some (some r)` if `eval` would not process `e` as an algebraic ring expression,
  but `NormNum.derive` can nevertheless simplify `e`, with result `r`.
-/
-- Note this is not the same as whether the result of `eval` is an atom. (e.g. consider `x + 0`.)
def isAtomOrDerivable {u} {α : Q(Type u)} (sα : Q(CommSemiring $α))
    (c : Cache sα) (e : Q($α)) : AtomM (Option (Option (Result (ExSum sα) e))) 
goal: Mathlib.Tactic.AtomM (Option (Option (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) e)))

full_name: Mathlib.Tactic.Ring.eval
code: /--
Evaluates expression `e` of type `α` into a normalized representation as a polynomial.
This is the main driver of `ring`, which calls out to `evalAdd`, `evalMul` etc.
-/
partial def eval {u : Lean.Level} {α : Q(Type u)} (sα : Q(CommSemiring $α))
    (c : Cache sα) (e : Q($α)) : AtomM (Result (ExSum sα) e) 
goal: Mathlib.Tactic.AtomM (Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExSum sα) e)

full_name: Mathlib.Tactic.Ring.CSLift
code: /-- `CSLift α β` is a typeclass used by `ring` for lifting operations from `α`
(which is not a commutative semiring) into a commutative semiring `β` by using an injective map
`lift : α → β`. -/
class CSLift (α : Type u) (β : outParam (Type u)) where
  /-- `lift` is the "canonical injection" from `α` to `β` -/
  lift : α → β
  /-- `lift` is an injective function -/
  inj : Function.Injective lift
goal: Type u

full_name: Mathlib.Tactic.Ring.CSLift.inj
code: /-- `CSLift α β` is a typeclass used by `ring` for lifting operations from `α`
(which is not a commutative semiring) into a commutative semiring `β` by using an injective map
`lift : α → β`. -/
class CSLift (α : Type u) (β : outParam (Type u)) where
  /-- `lift` is the "canonical injection" from `α` to `β` -/
  lift : α → β
  /-- `lift` is an injective function -/
  inj : Function.Injective lift
goal: Function.Injective Mathlib.Tactic.Ring.CSLift.lift

full_name: Mathlib.Tactic.Ring.CSLift.lift
code: /-- `CSLift α β` is a typeclass used by `ring` for lifting operations from `α`
(which is not a commutative semiring) into a commutative semiring `β` by using an injective map
`lift : α → β`. -/
class CSLift (α : Type u) (β : outParam (Type u)) where
  /-- `lift` is the "canonical injection" from `α` to `β` -/
  lift : α → β
  /-- `lift` is an injective function -/
  inj : Function.Injective lift
goal: α → β

full_name: Mathlib.Tactic.Ring.CSLiftVal
code: /-- `CSLiftVal a b` means that `b = lift a`. This is used by `ring` to construct an expression `b`
from the input expression `a`, and then run the usual ring algorithm on `b`. -/
class CSLiftVal {α} {β : outParam (Type u)} [CSLift α β] (a : α) (b : outParam β) : Prop where
  /-- The output value `b` is equal to the lift of `a`. This can be supplied by the default
  instance which sets `b := lift a`, but `ring` will treat this as an atom so it is more useful
  when there are other instances which distribute addition or multiplication. -/
  eq : b = CSLift.lift a
goal: Prop

full_name: Mathlib.Tactic.Ring.CSLiftVal.eq
code: /-- `CSLiftVal a b` means that `b = lift a`. This is used by `ring` to construct an expression `b`
from the input expression `a`, and then run the usual ring algorithm on `b`. -/
class CSLiftVal {α} {β : outParam (Type u)} [CSLift α β] (a : α) (b : outParam β) : Prop where
  /-- The output value `b` is equal to the lift of `a`. This can be supplied by the default
  instance which sets `b := lift a`, but `ring` will treat this as an atom so it is more useful
  when there are other instances which distribute addition or multiplication. -/
  eq : b = CSLift.lift a
goal: b = Mathlib.Tactic.Ring.CSLift.lift a

full_name: Mathlib.Tactic.Ring.instCSLiftValLift
code: instance (priority := low) {α β} [CSLift α β] (a : α) : CSLiftVal a (CSLift.lift a) 
goal: Mathlib.Tactic.Ring.CSLiftVal a (Mathlib.Tactic.Ring.CSLift.lift a)

full_name: Mathlib.Tactic.Ring.of_lift
code: theorem of_lift {α β} [inst : CSLift α β] {a b : α} {a' b' : β}
    [h1 : CSLiftVal a a'] [h2 : CSLiftVal b b'] (h : a' = b') : a = b 
goal: a = b

full_name: Mathlib.Tactic.Ring.of_eq
code: theorem of_eq {α} {a b c : α} (_ : (a : α) = c) (_ : b = c) : a = b 
goal: a = c → b = c → a = b

full_name: Mathlib.Tactic.Ring.initFn._@.Mathlib.Tactic.Ring.Basic._hyg.24210
code: /--
This is a routine which is used to clean up the unsolved subgoal
of a failed `ring1` application. It is overridden in `Mathlib.Tactic.Ring.RingNF`
to apply the `ring_nf` simp set to the goal.
-/
initialize ringCleanupRef : IO.Ref (Expr → MetaM Expr) ← IO.mkRef pure
goal: IO (IO.Ref (Lean.Expr → Lean.MetaM Lean.Expr))

full_name: Mathlib.Tactic.Ring.ringCleanupRef
code: /--
This is a routine which is used to clean up the unsolved subgoal
of a failed `ring1` application. It is overridden in `Mathlib.Tactic.Ring.RingNF`
to apply the `ring_nf` simp set to the goal.
-/
initialize ringCleanupRef : IO.Ref (Expr → MetaM Expr) ← IO.mkRef pure
goal: IO.Ref (Lean.Expr → Lean.MetaM Lean.Expr)

full_name: Mathlib.Tactic.Ring.proveEq
code: /-- Frontend of `ring1`: attempt to close a goal `g`, assuming it is an equation of semirings. -/
def proveEq (g : MVarId) : AtomM Unit 
goal: Mathlib.Tactic.AtomM Unit

full_name: Mathlib.Tactic.Ring.proveEq.ringCore
code: /-- Frontend of `ring1`: attempt to close a goal `g`, assuming it is an equation of semirings. -/
def proveEq (g : MVarId) : AtomM Unit 
goal: Mathlib.Tactic.AtomM Q(«$e₁» = «$e₂»)

full_name: Mathlib.Tactic.Ring._aux_Mathlib_Tactic_Ring_Basic___elabRules_Mathlib_Tactic_Ring_ring1_1
code: /--
Tactic for solving equations of *commutative* (semi)rings,
allowing variables in the exponent.

* This version of `ring` fails if the target is not an equality.
* The variant `ring1!` will use a more aggressive reducibility setting
  to determine equality of atoms.
-/
elab (name := ring1) "ring1" tk:"!"? : tactic => liftMetaMAtMain fun g ↦ do
  AtomM.run (if tk.isSome then .default else .reducible) (proveEq g)
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.Ring.ring1
code: /--
Tactic for solving equations of *commutative* (semi)rings,
allowing variables in the exponent.

* This version of `ring` fails if the target is not an equality.
* The variant `ring1!` will use a more aggressive reducibility setting
  to determine equality of atoms.
-/
elab (name := ring1) "ring1" tk:"!"? : tactic => liftMetaMAtMain fun g ↦ do
  AtomM.run (if tk.isSome then .default else .reducible) (proveEq g)
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.Ring._aux_Mathlib_Tactic_Ring_Basic___macroRules_Mathlib_Tactic_Ring_tacticRing1!_1
code: macro "ring1!" : tactic => `(tactic| ring1 !)
goal: Lean.Macro

full_name: Mathlib.Tactic.Ring.tacticRing1!
code: macro "ring1!" : tactic => `(tactic| ring1 !)
goal: Lean.ParserDescr