l3lab/ntp-mathlib huggingface dataset:
/--
The Schnirelmann density of the set of naturals which are `1 mod m` is `m⁻¹`, for any `m ≠ 1`.

Note that if `m = 1`, this set is empty.
-/
lemma schnirelmannDensity_setOf_mod_eq_one {m : ℕ} (hm : m ≠ 1) :
    schnirelmannDensity {n | n % m = 1} = (m⁻¹ : ℝ) := by
  rcases m.eq_zero_or_pos with rfl | hm'
  · simp only [Nat.cast_zero, inv_zero]
    refine schnirelmannDensity_finite ?_
    simp
  apply le_antisymm (schnirelmannDensity_le_of_le m hm'.ne' _) _
  · rw [← one_div]
    apply div_le_div_of_le (Nat.cast_nonneg _)
    simp only [Set.mem_setOf_eq, Nat.cast_le_one, card_le_one_iff_subset_singleton, subset_iff,
      mem_filter, mem_Ioc, mem_singleton, and_imp]
    use 1
    intro x _ hxm h
    rcases eq_or_lt_of_le hxm with rfl | hxm'
    · simp at h
    rwa [Nat.mod_eq_of_lt hxm'] at h
  rw [le_schnirelmannDensity_iff]
  intro n hn
  simp only [Set.mem_setOf_eq]
  have : (Icc 0 ((n - 1) / m)).image (· * m + 1) ⊆ (Ioc 0 n).filter (· % m = 1)
  · simp only [subset_iff, mem_image, forall_exists_index, mem_filter, mem_Ioc, mem_Icc, and_imp]
    rintro _ y _ hy' rfl
    have hm : 2 ≤ m := hm.lt_of_le' hm'
    simp only [Nat.mul_add_mod', Nat.mod_eq_of_lt hm, add_pos_iff, or_true, and_true, true_and,
      ← Nat.le_sub_iff_add_le hn, zero_lt_one]
    exact Nat.mul_le_of_le_div _ _ _ hy'
  rw [le_div_iff (Nat.cast_pos.2 hn), mul_comm, ← div_eq_mul_inv]
  apply (Nat.cast_le.2 (card_le_of_subset this)).trans'
  rw [card_image_of_injective, Nat.card_Icc, Nat.sub_zero, div_le_iff (Nat.cast_pos.2 hm'),
    ← Nat.cast_mul, Nat.cast_le, add_one_mul (α := ℕ)]
  · have := @Nat.lt_div_mul_add n.pred m hm'
    

Proof state:
m : ℕ
hm : m ≠ 1
hm' : m > 0
n : ℕ
hn : 0 < n
this✝ : image (fun x => x * m + 1) (Icc 0 ((n - 1) / m)) ⊆ filter (fun x => x % m = 1) (Ioc 0 n)
this : Nat.pred n < Nat.pred n / m * m + m
⊢ n ≤ (n - 1) / m * m + m

Next tactic:
rwa [← Nat.succ_le, Nat.succ_pred hn.ne'] at this
/--
The Schnirelmann density of the set of naturals which are `1 mod m` is `m⁻¹`, for any `m ≠ 1`.

Note that if `m = 1`, this set is empty.
-/
lemma schnirelmannDensity_setOf_mod_eq_one {m : ℕ} (hm : m ≠ 1) :
    schnirelmannDensity {n | n % m = 1} = (m⁻¹ : ℝ) := by
  rcases m.eq_zero_or_pos with rfl | hm'
  · simp only [Nat.cast_zero, inv_zero]
    refine schnirelmannDensity_finite ?_
    simp
  apply le_antisymm (schnirelmannDensity_le_of_le m hm'.ne' _) _
  · rw [← one_div]
    apply div_le_div_of_le (Nat.cast_nonneg _)
    simp only [Set.mem_setOf_eq, Nat.cast_le_one, card_le_one_iff_subset_singleton, subset_iff,
      mem_filter, mem_Ioc, mem_singleton, and_imp]
    use 1
    intro x _ hxm h
    rcases eq_or_lt_of_le hxm with rfl | hxm'
    · simp at h
    rwa [Nat.mod_eq_of_lt hxm'] at h
  rw [le_schnirelmannDensity_iff]
  intro n hn
  simp only [Set.mem_setOf_eq]
  have : (Icc 0 ((n - 1) / m)).image (· * m + 1) ⊆ (Ioc 0 n).filter (· % m = 1)
  · simp only [subset_iff, mem_image, forall_exists_index, mem_filter, mem_Ioc, mem_Icc, and_imp]
    rintro _ y _ hy' rfl
    have hm : 2 ≤ m := hm.lt_of_le' hm'
    simp only [Nat.mul_add_mod', Nat.mod_eq_of_lt hm, add_pos_iff, or_true, and_true, true_and,
      ← Nat.le_sub_iff_add_le hn, zero_lt_one]
    exact Nat.mul_le_of_le_div _ _ _ hy'
  rw [le_div_iff (Nat.cast_pos.2 hn), mul_comm, ← div_eq_mul_inv]
  apply (Nat.cast_le.2 (card_le_of_subset this)).trans'
  rw [card_image_of_injective, Nat.card_Icc, Nat.sub_zero, div_le_iff (Nat.cast_pos.2 hm'),
    ← Nat.cast_mul, Nat.cast_le, add_one_mul (α := ℕ)]
  · have := @Nat.lt_div_mul_add n.pred m hm'
    rwa [← Nat.succ_le, Nat.succ_pred hn.ne'] at this
  

Proof state:
case H
m : ℕ
hm : m ≠ 1
hm' : m > 0
n : ℕ
hn : 0 < n
this : image (fun x => x * m + 1) (Icc 0 ((n - 1) / m)) ⊆ filter (fun x => x % m = 1) (Ioc 0 n)
⊢ Function.Injective fun x => x * m + 1

Next tactic:
intro a b
/--
The Schnirelmann density of the set of naturals which are `1 mod m` is `m⁻¹`, for any `m ≠ 1`.

Note that if `m = 1`, this set is empty.
-/
lemma schnirelmannDensity_setOf_mod_eq_one {m : ℕ} (hm : m ≠ 1) :
    schnirelmannDensity {n | n % m = 1} = (m⁻¹ : ℝ) := by
  rcases m.eq_zero_or_pos with rfl | hm'
  · simp only [Nat.cast_zero, inv_zero]
    refine schnirelmannDensity_finite ?_
    simp
  apply le_antisymm (schnirelmannDensity_le_of_le m hm'.ne' _) _
  · rw [← one_div]
    apply div_le_div_of_le (Nat.cast_nonneg _)
    simp only [Set.mem_setOf_eq, Nat.cast_le_one, card_le_one_iff_subset_singleton, subset_iff,
      mem_filter, mem_Ioc, mem_singleton, and_imp]
    use 1
    intro x _ hxm h
    rcases eq_or_lt_of_le hxm with rfl | hxm'
    · simp at h
    rwa [Nat.mod_eq_of_lt hxm'] at h
  rw [le_schnirelmannDensity_iff]
  intro n hn
  simp only [Set.mem_setOf_eq]
  have : (Icc 0 ((n - 1) / m)).image (· * m + 1) ⊆ (Ioc 0 n).filter (· % m = 1)
  · simp only [subset_iff, mem_image, forall_exists_index, mem_filter, mem_Ioc, mem_Icc, and_imp]
    rintro _ y _ hy' rfl
    have hm : 2 ≤ m := hm.lt_of_le' hm'
    simp only [Nat.mul_add_mod', Nat.mod_eq_of_lt hm, add_pos_iff, or_true, and_true, true_and,
      ← Nat.le_sub_iff_add_le hn, zero_lt_one]
    exact Nat.mul_le_of_le_div _ _ _ hy'
  rw [le_div_iff (Nat.cast_pos.2 hn), mul_comm, ← div_eq_mul_inv]
  apply (Nat.cast_le.2 (card_le_of_subset this)).trans'
  rw [card_image_of_injective, Nat.card_Icc, Nat.sub_zero, div_le_iff (Nat.cast_pos.2 hm'),
    ← Nat.cast_mul, Nat.cast_le, add_one_mul (α := ℕ)]
  · have := @Nat.lt_div_mul_add n.pred m hm'
    rwa [← Nat.succ_le, Nat.succ_pred hn.ne'] at this
  intro a b
  

Proof state:
case H
m : ℕ
hm : m ≠ 1
hm' : m > 0
n : ℕ
hn : 0 < n
this : image (fun x => x * m + 1) (Icc 0 ((n - 1) / m)) ⊆ filter (fun x => x % m = 1) (Ioc 0 n)
a b : ℕ
⊢ (fun x => x * m + 1) a = (fun x => x * m + 1) b → a = b

Next tactic:
simp [hm'.ne']
lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} :
    schnirelmannDensity {n | n ≡ 1 [MOD m]} = (m⁻¹ : ℝ) := by
  

Proof state:
m : ℕ
⊢ schnirelmannDensity {n | n ≡ 1 [MOD m]} = (↑m)⁻¹

Next tactic:
rcases eq_or_ne m 1 with rfl | hm
lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} :
    schnirelmannDensity {n | n ≡ 1 [MOD m]} = (m⁻¹ : ℝ) := by
  rcases eq_or_ne m 1 with rfl | hm
  · 

Proof state:
case inl
⊢ schnirelmannDensity {n | n ≡ 1 [MOD 1]} = (↑1)⁻¹

Next tactic:
simp [Nat.modEq_one]
lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} :
    schnirelmannDensity {n | n ≡ 1 [MOD m]} = (m⁻¹ : ℝ) := by
  rcases eq_or_ne m 1 with rfl | hm
  · simp [Nat.modEq_one]
  

Proof state:
case inr
m : ℕ
hm : m ≠ 1
⊢ schnirelmannDensity {n | n ≡ 1 [MOD m]} = (↑m)⁻¹

Next tactic:
rw [← schnirelmannDensity_setOf_mod_eq_one hm]
lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} :
    schnirelmannDensity {n | n ≡ 1 [MOD m]} = (m⁻¹ : ℝ) := by
  rcases eq_or_ne m 1 with rfl | hm
  · simp [Nat.modEq_one]
  rw [← schnirelmannDensity_setOf_mod_eq_one hm]
  

Proof state:
case inr
m : ℕ
hm : m ≠ 1
⊢ schnirelmannDensity {n | n ≡ 1 [MOD m]} = schnirelmannDensity {n | n % m = 1}

Next tactic:
apply schnirelmannDensity_congr
lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} :
    schnirelmannDensity {n | n ≡ 1 [MOD m]} = (m⁻¹ : ℝ) := by
  rcases eq_or_ne m 1 with rfl | hm
  · simp [Nat.modEq_one]
  rw [← schnirelmannDensity_setOf_mod_eq_one hm]
  apply schnirelmannDensity_congr
  

Proof state:
case inr.h
m : ℕ
hm : m ≠ 1
⊢ {n | n ≡ 1 [MOD m]} = {n | n % m = 1}

Next tactic:
ext n
lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} :
    schnirelmannDensity {n | n ≡ 1 [MOD m]} = (m⁻¹ : ℝ) := by
  rcases eq_or_ne m 1 with rfl | hm
  · simp [Nat.modEq_one]
  rw [← schnirelmannDensity_setOf_mod_eq_one hm]
  apply schnirelmannDensity_congr
  ext n
  

Proof state:
case inr.h.h
m : ℕ
hm : m ≠ 1
n : ℕ
⊢ n ∈ {n | n ≡ 1 [MOD m]} ↔ n ∈ {n | n % m = 1}

Next tactic:
simp only [Set.mem_setOf_eq, Nat.ModEq, Nat.one_mod_of_ne_one hm]
lemma schnirelmannDensity_setOf_Odd : schnirelmannDensity (setOf Odd) = 2⁻¹ := by
  

Proof state:
⊢ schnirelmannDensity (setOf Odd) = 2⁻¹

Next tactic:
have h : setOf Odd = {n | n % 2 = 1} := Set.ext fun _ => Nat.odd_iff
lemma schnirelmannDensity_setOf_Odd : schnirelmannDensity (setOf Odd) = 2⁻¹ := by
  have h : setOf Odd = {n | n % 2 = 1} := Set.ext fun _ => Nat.odd_iff
  

Proof state:
h : setOf Odd = {n | n % 2 = 1}
⊢ schnirelmannDensity (setOf Odd) = 2⁻¹

Next tactic:
simp only [h]
lemma schnirelmannDensity_setOf_Odd : schnirelmannDensity (setOf Odd) = 2⁻¹ := by
  have h : setOf Odd = {n | n % 2 = 1} := Set.ext fun _ => Nat.odd_iff
  simp only [h]
  

Proof state:
h : setOf Odd = {n | n % 2 = 1}
⊢ schnirelmannDensity {n | n % 2 = 1} = 2⁻¹

Next tactic:
rw [schnirelmannDensity_setOf_mod_eq_one (by norm_num1), Nat.cast_two]
lemma schnirelmannDensity_setOf_Odd : schnirelmannDensity (setOf Odd) = 2⁻¹ := by
  have h : setOf Odd = {n | n % 2 = 1} := Set.ext fun _ => Nat.odd_iff
  simp only [h]
  rw [schnirelmannDensity_setOf_mod_eq_one (by 

Proof state:
h : setOf Odd = {n | n % 2 = 1}
⊢ 2 ≠ 1

Next tactic:
norm_num1
@[to_additive (attr := ext)]
theorem ext : Function.Injective (val : αˣ → α)
  | ⟨v, i₁, vi₁, iv₁⟩, ⟨v', i₂, vi₂, iv₂⟩, e => by
    

Proof state:
α : Type u
inst✝ : Monoid α
v i₁ : α
vi₁ : v * i₁ = 1
iv₁ : i₁ * v = 1
v' i₂ : α
vi₂ : v' * i₂ = 1
iv₂ : i₂ * v' = 1
e : ↑{ val := v, inv := i₁, val_inv := vi₁, inv_val := iv₁ } = ↑{ val := v', inv := i₂, val_inv := vi₂, inv_val := iv₂ }
⊢ { val := v, inv := i₁, val_inv := vi₁, inv_val := iv₁ } = { val := v', inv := i₂, val_inv := vi₂, inv_val := iv₂ }

Next tactic:
simp only at e
@[to_additive (attr := ext)]
theorem ext : Function.Injective (val : αˣ → α)
  | ⟨v, i₁, vi₁, iv₁⟩, ⟨v', i₂, vi₂, iv₂⟩, e => by
    simp only at e; 

Proof state:
α : Type u
inst✝ : Monoid α
v i₁ : α
vi₁ : v * i₁ = 1
iv₁ : i₁ * v = 1
v' i₂ : α
vi₂ : v' * i₂ = 1
iv₂ : i₂ * v' = 1
e : v = v'
⊢ { val := v, inv := i₁, val_inv := vi₁, inv_val := iv₁ } = { val := v', inv := i₂, val_inv := vi₂, inv_val := iv₂ }

Next tactic:
subst v'
@[to_additive (attr := ext)]
theorem ext : Function.Injective (val : αˣ → α)
  | ⟨v, i₁, vi₁, iv₁⟩, ⟨v', i₂, vi₂, iv₂⟩, e => by
    simp only at e; subst v'; 

Proof state:
α : Type u
inst✝ : Monoid α
v i₁ : α
vi₁ : v * i₁ = 1
iv₁ : i₁ * v = 1
i₂ : α
vi₂ : v * i₂ = 1
iv₂ : i₂ * v = 1
⊢ { val := v, inv := i₁, val_inv := vi₁, inv_val := iv₁ } = { val := v, inv := i₂, val_inv := vi₂, inv_val := iv₂ }

Next tactic:
congr
@[to_additive (attr := ext)]
theorem ext : Function.Injective (val : αˣ → α)
  | ⟨v, i₁, vi₁, iv₁⟩, ⟨v', i₂, vi₂, iv₂⟩, e => by
    simp only at e; subst v'; congr;
    

Proof state:
case e_inv
α : Type u
inst✝ : Monoid α
v i₁ : α
vi₁ : v * i₁ = 1
iv₁ : i₁ * v = 1
i₂ : α
vi₂ : v * i₂ = 1
iv₂ : i₂ * v = 1
⊢ i₁ = i₂

Next tactic:
simpa only [iv₂, vi₁, one_mul, mul_one] using mul_assoc i₂ v i₁
/-- Units of a monoid form have a multiplication and multiplicative identity. -/
@[to_additive "Additive units of an additive monoid have an addition and an additive identity."]
instance : MulOneClass αˣ where
  mul u₁ u₂ :=
    ⟨u₁.val * u₂.val, u₂.inv * u₁.inv,
      by 

Proof state:
α : Type u
inst✝ : Monoid α
u₁ u₂ : αˣ
⊢ ↑u₁ * ↑u₂ * (u₂.inv * u₁.inv) = 1

Next tactic:
rw [mul_assoc, ← mul_assoc u₂.val, val_inv, one_mul, val_inv]
/-- Units of a monoid form have a multiplication and multiplicative identity. -/
@[to_additive "Additive units of an additive monoid have an addition and an additive identity."]
instance : MulOneClass αˣ where
  mul u₁ u₂ :=
    ⟨u₁.val * u₂.val, u₂.inv * u₁.inv,
      by rw [mul_assoc, ← mul_assoc u₂.val, val_inv, one_mul, val_inv],
      by 

Proof state:
α : Type u
inst✝ : Monoid α
u₁ u₂ : αˣ
⊢ u₂.inv * u₁.inv * (↑u₁ * ↑u₂) = 1

Next tactic:
rw [mul_assoc, ← mul_assoc u₁.inv, inv_val, one_mul, inv_val]
@[to_additive (attr := simp, norm_cast)]
theorem val_eq_one {a : αˣ} : (a : α) = 1 ↔ a = 1 := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u a : αˣ
⊢ ↑a = 1 ↔ a = 1

Next tactic:
rw [← Units.val_one, eq_iff]
@[to_additive]
theorem inv_mul_of_eq {a : α} (h : ↑u = a) : ↑u⁻¹ * a = 1 := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
h : ↑u = a
⊢ ↑u⁻¹ * a = 1

Next tactic:
rw [← h, u.inv_mul]
@[to_additive]
theorem mul_inv_of_eq {a : α} (h : ↑u = a) : a * ↑u⁻¹ = 1 := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
h : ↑u = a
⊢ a * ↑u⁻¹ = 1

Next tactic:
rw [← h, u.mul_inv]
@[to_additive (attr := simp)]
theorem mul_inv_cancel_left (a : αˣ) (b : α) : (a : α) * (↑a⁻¹ * b) = b := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c u a : αˣ
b : α
⊢ ↑a * (↑a⁻¹ * b) = b

Next tactic:
rw [← mul_assoc, mul_inv, one_mul]
@[to_additive (attr := simp)]
theorem inv_mul_cancel_left (a : αˣ) (b : α) : (↑a⁻¹ : α) * (a * b) = b := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c u a : αˣ
b : α
⊢ ↑a⁻¹ * (↑a * b) = b

Next tactic:
rw [← mul_assoc, inv_mul, one_mul]
@[to_additive (attr := simp)]
theorem mul_inv_cancel_right (a : α) (b : αˣ) : a * b * ↑b⁻¹ = a := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c u : αˣ
a : α
b : αˣ
⊢ a * ↑b * ↑b⁻¹ = a

Next tactic:
rw [mul_assoc, mul_inv, mul_one]
@[to_additive (attr := simp)]
theorem inv_mul_cancel_right (a : α) (b : αˣ) : a * ↑b⁻¹ * b = a := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c u : αˣ
a : α
b : αˣ
⊢ a * ↑b⁻¹ * ↑b = a

Next tactic:
rw [mul_assoc, inv_mul, mul_one]
@[to_additive (attr := simp)]
theorem mul_right_inj (a : αˣ) {b c : α} : (a : α) * b = a * c ↔ b = c :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c✝ u a : αˣ
b c : α
h : ↑a * b = ↑a * c
⊢ b = c

Next tactic:
simpa only [inv_mul_cancel_left] using congr_arg (fun x : α => ↑(a⁻¹ : αˣ) * x) h
@[to_additive (attr := simp)]
theorem mul_left_inj (a : αˣ) {b c : α} : b * a = c * a ↔ b = c :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c✝ u a : αˣ
b c : α
h : b * ↑a = c * ↑a
⊢ b = c

Next tactic:
simpa only [mul_inv_cancel_right] using congr_arg (fun x : α => x * ↑(a⁻¹ : αˣ)) h
@[to_additive]
theorem eq_mul_inv_iff_mul_eq {a b : α} : a = b * ↑c⁻¹ ↔ a * c = b :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c u : αˣ
a b : α
h : a = b * ↑c⁻¹
⊢ a * ↑c = b

Next tactic:
rw [h, inv_mul_cancel_right]
@[to_additive]
theorem eq_mul_inv_iff_mul_eq {a b : α} : a = b * ↑c⁻¹ ↔ a * c = b :=
  ⟨fun h => by rw [h, inv_mul_cancel_right], fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b✝ c u : αˣ
a b : α
h : a * ↑c = b
⊢ a = b * ↑c⁻¹

Next tactic:
rw [← h, mul_inv_cancel_right]
@[to_additive]
theorem eq_inv_mul_iff_mul_eq {a c : α} : a = ↑b⁻¹ * c ↔ ↑b * a = c :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c✝ u : αˣ
a c : α
h : a = ↑b⁻¹ * c
⊢ ↑b * a = c

Next tactic:
rw [h, mul_inv_cancel_left]
@[to_additive]
theorem eq_inv_mul_iff_mul_eq {a c : α} : a = ↑b⁻¹ * c ↔ ↑b * a = c :=
  ⟨fun h => by rw [h, mul_inv_cancel_left], fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c✝ u : αˣ
a c : α
h : ↑b * a = c
⊢ a = ↑b⁻¹ * c

Next tactic:
rw [← h, inv_mul_cancel_left]
@[to_additive]
theorem inv_mul_eq_iff_eq_mul {b c : α} : ↑a⁻¹ * b = c ↔ b = a * c :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a b✝ c✝ u : αˣ
b c : α
h : ↑a⁻¹ * b = c
⊢ b = ↑a * c

Next tactic:
rw [← h, mul_inv_cancel_left]
@[to_additive]
theorem inv_mul_eq_iff_eq_mul {b c : α} : ↑a⁻¹ * b = c ↔ b = a * c :=
  ⟨fun h => by rw [← h, mul_inv_cancel_left], fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a b✝ c✝ u : αˣ
b c : α
h : b = ↑a * c
⊢ ↑a⁻¹ * b = c

Next tactic:
rw [h, inv_mul_cancel_left]
@[to_additive]
theorem mul_inv_eq_iff_eq_mul {a c : α} : a * ↑b⁻¹ = c ↔ a = c * b :=
  ⟨fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c✝ u : αˣ
a c : α
h : a * ↑b⁻¹ = c
⊢ a = c * ↑b

Next tactic:
rw [← h, inv_mul_cancel_right]
@[to_additive]
theorem mul_inv_eq_iff_eq_mul {a c : α} : a * ↑b⁻¹ = c ↔ a = c * b :=
  ⟨fun h => by rw [← h, inv_mul_cancel_right], fun h => by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c✝ u : αˣ
a c : α
h : a = c * ↑b
⊢ a * ↑b⁻¹ = c

Next tactic:
rw [h, mul_inv_cancel_right]
@[to_additive]
protected theorem inv_eq_of_mul_eq_one_left {a : α} (h : a * u = 1) : ↑u⁻¹ = a :=
  calc
    ↑u⁻¹ = (1 : α) * ↑u⁻¹ := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
h : a * ↑u = 1
⊢ ↑u⁻¹ = 1 * ↑u⁻¹

Next tactic:
rw [one_mul]
@[to_additive]
protected theorem inv_eq_of_mul_eq_one_left {a : α} (h : a * u = 1) : ↑u⁻¹ = a :=
  calc
    ↑u⁻¹ = (1 : α) * ↑u⁻¹ := by rw [one_mul]
    _ = a := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
h : a * ↑u = 1
⊢ 1 * ↑u⁻¹ = a

Next tactic:
rw [← h, mul_inv_cancel_right]
@[to_additive]
protected theorem inv_eq_of_mul_eq_one_right {a : α} (h : ↑u * a = 1) : ↑u⁻¹ = a :=
  calc
    ↑u⁻¹ = ↑u⁻¹ * (1 : α) := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
h : ↑u * a = 1
⊢ ↑u⁻¹ = ↑u⁻¹ * 1

Next tactic:
rw [mul_one]
@[to_additive]
protected theorem inv_eq_of_mul_eq_one_right {a : α} (h : ↑u * a = 1) : ↑u⁻¹ = a :=
  calc
    ↑u⁻¹ = ↑u⁻¹ * (1 : α) := by rw [mul_one]
    _ = a := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
h : ↑u * a = 1
⊢ ↑u⁻¹ * 1 = a

Next tactic:
rw [← h, inv_mul_cancel_left]
@[to_additive]
theorem mul_eq_one_iff_eq_inv {a : α} : a * u = 1 ↔ a = ↑u⁻¹ := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
⊢ a * ↑u = 1 ↔ a = ↑u⁻¹

Next tactic:
rw [← mul_inv_eq_one, inv_inv]
@[to_additive]
theorem mul_eq_one_iff_inv_eq {a : α} : ↑u * a = 1 ↔ ↑u⁻¹ = a := by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c u : αˣ
a : α
⊢ ↑u * a = 1 ↔ ↑u⁻¹ = a

Next tactic:
rw [← inv_mul_eq_one, inv_inv]
@[to_additive]
theorem inv_unique {u₁ u₂ : αˣ} (h : (↑u₁ : α) = ↑u₂) : (↑u₁⁻¹ : α) = ↑u₂⁻¹ :=
  Units.inv_eq_of_mul_eq_one_right <| by 

Proof state:
α : Type u
inst✝ : Monoid α
a b c u u₁ u₂ : αˣ
h : ↑u₁ = ↑u₂
⊢ ↑u₁ * ↑u₂⁻¹ = 1

Next tactic:
rw [h, u₂.mul_inv]
@[simp]
theorem divp_mul_cancel (a : α) (u : αˣ) : a /ₚ u * u = a :=
  (mul_assoc _ _ _).trans <| by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c a : α
u : αˣ
⊢ a * (↑u⁻¹ * ↑u) = a

Next tactic:
rw [Units.inv_mul, mul_one]
@[simp]
theorem mul_divp_cancel (a : α) (u : αˣ) : a * u /ₚ u = a :=
  (mul_assoc _ _ _).trans <| by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c a : α
u : αˣ
⊢ a * (↑u * ↑u⁻¹) = a

Next tactic:
rw [Units.mul_inv, mul_one]
@[field_simps]
theorem divp_divp_eq_divp_mul (x : α) (u₁ u₂ : αˣ) : x /ₚ u₁ /ₚ u₂ = x /ₚ (u₂ * u₁) := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a b c x : α
u₁ u₂ : αˣ
⊢ x /ₚ u₁ /ₚ u₂ = x /ₚ (u₂ * u₁)

Next tactic:
simp only [divp, mul_inv_rev, Units.val_mul, mul_assoc]
@[field_simps 1010]
theorem divp_eq_iff_mul_eq {x : α} {u : αˣ} {y : α} : x /ₚ u = y ↔ y * u = x :=
  u.mul_left_inj.symm.trans <| by 

Proof state:
α : Type u
inst✝ : Monoid α
a b c x : α
u : αˣ
y : α
⊢ x /ₚ u * ↑u = y * ↑u ↔ y * ↑u = x

Next tactic:
rw [divp_mul_cancel]
@[field_simps 1010]
theorem divp_eq_iff_mul_eq {x : α} {u : αˣ} {y : α} : x /ₚ u = y ↔ y * u = x :=
  u.mul_left_inj.symm.trans <| by rw [divp_mul_cancel]; 

Proof state:
α : Type u
inst✝ : Monoid α
a b c x : α
u : αˣ
y : α
⊢ x = y * ↑u ↔ y * ↑u = x

Next tactic:
exact ⟨Eq.symm, Eq.symm⟩
@[field_simps]
theorem eq_divp_iff_mul_eq {x : α} {u : αˣ} {y : α} : x = y /ₚ u ↔ x * u = y := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a b c x : α
u : αˣ
y : α
⊢ x = y /ₚ u ↔ x * ↑u = y

Next tactic:
rw [eq_comm, divp_eq_iff_mul_eq]
theorem divp_eq_one_iff_eq {a : α} {u : αˣ} : a /ₚ u = 1 ↔ a = u :=
  (Units.mul_left_inj u).symm.trans <| by 

Proof state:
α : Type u
inst✝ : Monoid α
a✝ b c a : α
u : αˣ
⊢ a /ₚ u * ↑u = 1 * ↑u ↔ a = ↑u

Next tactic:
rw [divp_mul_cancel, one_mul]
/-- Used for `field_simp` to deal with inverses of units. -/
@[field_simps]
theorem inv_eq_one_divp (u : αˣ) : ↑u⁻¹ = 1 /ₚ u := by 

Proof state:
α : Type u
inst✝ : Monoid α
a b c : α
u : αˣ
⊢ ↑u⁻¹ = 1 /ₚ u

Next tactic:
rw [one_divp]
/-- Used for `field_simp` to deal with inverses of units. This form of the lemma
is essential since `field_simp` likes to use `inv_eq_one_div` to rewrite
`↑u⁻¹ = ↑(1 / u)`.
-/
@[field_simps]
theorem inv_eq_one_divp' (u : αˣ) : ((1 / u : αˣ) : α) = 1 /ₚ u := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a b c : α
u : αˣ
⊢ ↑(1 / u) = 1 /ₚ u

Next tactic:
rw [one_div, one_divp]
/-- `field_simp` moves division inside `αˣ` to the right, and this lemma
lifts the calculation to `α`.
-/
@[field_simps]
theorem val_div_eq_divp (u₁ u₂ : αˣ) : ↑(u₁ / u₂) = ↑u₁ /ₚ u₂ := by
  

Proof state:
α : Type u
inst✝ : Monoid α
a b c : α
u₁ u₂ : αˣ
⊢ ↑(u₁ / u₂) = ↑u₁ /ₚ u₂

Next tactic:
rw [divp, division_def, Units.val_mul]
@[field_simps]
theorem divp_mul_eq_mul_divp (x y : α) (u : αˣ) : x /ₚ u * y = x * y /ₚ u := by
  

Proof state:
α : Type u
inst✝ : CommMonoid α
x y : α
u : αˣ
⊢ x /ₚ u * y = x * y /ₚ u

Next tactic:
rw [divp, divp, mul_right_comm]
@[field_simps]
theorem divp_eq_divp_iff {x y : α} {ux uy : αˣ} : x /ₚ ux = y /ₚ uy ↔ x * uy = y * ux := by
  

Proof state:
α : Type u
inst✝ : CommMonoid α
x y : α
ux uy : αˣ
⊢ x /ₚ ux = y /ₚ uy ↔ x * ↑uy = y * ↑ux

Next tactic:
rw [divp_eq_iff_mul_eq, divp_mul_eq_mul_divp, divp_eq_iff_mul_eq]
@[field_simps]
theorem divp_mul_divp (x y : α) (ux uy : αˣ) : x /ₚ ux * (y /ₚ uy) = x * y /ₚ (ux * uy) := by
  

Proof state:
α : Type u
inst✝ : CommMonoid α
x y : α
ux uy : αˣ
⊢ x /ₚ ux * (y /ₚ uy) = x * y /ₚ (ux * uy)

Next tactic:
rw [divp_mul_eq_mul_divp, divp_assoc', divp_divp_eq_divp_mul]
@[to_additive]
theorem eq_one_of_mul_right (h : a * b = 1) : a = 1 :=
  congr_arg Units.inv <| Subsingleton.elim (Units.mk _ _ (by 

Proof state:
α : Type u
inst✝¹ : CommMonoid α
inst✝ : Subsingleton αˣ
a b : α
h : a * b = 1
⊢ b * a = 1

Next tactic:
rwa [mul_comm]
@[to_additive]
theorem eq_one_of_mul_left (h : a * b = 1) : b = 1 :=
  congr_arg Units.inv <| Subsingleton.elim (Units.mk _ _ h <| by 

Proof state:
α : Type u
inst✝¹ : CommMonoid α
inst✝ : Subsingleton αˣ
a b : α
h : a * b = 1
⊢ b * a = 1

Next tactic:
rwa [mul_comm]
@[to_additive (attr := simp)]
theorem mul_eq_one : a * b = 1 ↔ a = 1 ∧ b = 1 :=
  ⟨fun h => ⟨eq_one_of_mul_right h, eq_one_of_mul_left h⟩, by
    

Proof state:
α : Type u
inst✝¹ : CommMonoid α
inst✝ : Subsingleton αˣ
a b : α
⊢ a = 1 ∧ b = 1 → a * b = 1

Next tactic:
rintro ⟨rfl, rfl⟩
@[to_additive (attr := simp)]
theorem mul_eq_one : a * b = 1 ↔ a = 1 ∧ b = 1 :=
  ⟨fun h => ⟨eq_one_of_mul_right h, eq_one_of_mul_left h⟩, by
    rintro ⟨rfl, rfl⟩
    

Proof state:
case intro
α : Type u
inst✝¹ : CommMonoid α
inst✝ : Subsingleton αˣ
⊢ 1 * 1 = 1

Next tactic:
exact mul_one _
@[to_additive IsAddUnit.exists_neg]
theorem IsUnit.exists_right_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, a * b = 1 := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a : M
h : IsUnit a
⊢ ∃ b, a * b = 1

Next tactic:
rcases h with ⟨⟨a, b, hab, _⟩, rfl⟩
@[to_additive IsAddUnit.exists_neg]
theorem IsUnit.exists_right_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, a * b = 1 := by
  rcases h with ⟨⟨a, b, hab, _⟩, rfl⟩
  

Proof state:
case intro.mk
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a b : M
hab : a * b = 1
inv_val✝ : b * a = 1
⊢ ∃ b_1, ↑{ val := a, inv := b, val_inv := hab, inv_val := inv_val✝ } * b_1 = 1

Next tactic:
exact ⟨b, hab⟩
@[to_additive IsAddUnit.exists_neg']
theorem IsUnit.exists_left_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, b * a = 1 := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a : M
h : IsUnit a
⊢ ∃ b, b * a = 1

Next tactic:
rcases h with ⟨⟨a, b, _, hba⟩, rfl⟩
@[to_additive IsAddUnit.exists_neg']
theorem IsUnit.exists_left_inv [Monoid M] {a : M} (h : IsUnit a) : ∃ b, b * a = 1 := by
  rcases h with ⟨⟨a, b, _, hba⟩, rfl⟩
  

Proof state:
case intro.mk
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
a b : M
val_inv✝ : a * b = 1
hba : b * a = 1
⊢ ∃ b_1, b_1 * ↑{ val := a, inv := b, val_inv := val_inv✝, inv_val := hba } = 1

Next tactic:
exact ⟨b, hba⟩
@[to_additive]
theorem isUnit_iff_exists_inv' [CommMonoid M] {a : M} : IsUnit a ↔ ∃ b, b * a = 1 := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : CommMonoid M
a : M
⊢ IsUnit a ↔ ∃ b, b * a = 1

Next tactic:
simp [isUnit_iff_exists_inv, mul_comm]
@[to_additive]
theorem IsUnit.mul [Monoid M] {x y : M} : IsUnit x → IsUnit y → IsUnit (x * y) := by
  

Proof state:
α : Type u
M : Type u_1
N : Type u_2
inst✝ : Monoid M
x y : M
⊢ IsUnit x → IsUnit y → IsUnit (x * y)

Next tactic:
rintro ⟨x, rfl⟩ ⟨y, rfl⟩