l3lab/ntp-mathlib huggingface dataset:
/-- If `M` is a representation of two different `R`-algebras `A` and `B` whose actions commute,
then it is a representation the `R`-algebra `A ⊗[R] B`.

An important example arises from a semiring `S`; allowing `S` to act on itself via left and right
multiplication, the roles of `R`, `A`, `B`, `M` are played by `ℕ`, `S`, `Sᵐᵒᵖ`, `S`. This example
is important because a submodule of `S` as a `Module` over `S ⊗[ℕ] Sᵐᵒᵖ` is a two-sided ideal.

NB: This is not an instance because in the case `B = A` and `M = A ⊗[R] A` we would have a diamond
of `smul` actions. Furthermore, this would not be a mere definitional diamond but a true
mathematical diamond in which `A ⊗[R] A` had two distinct scalar actions on itself: one from its
multiplication, and one from this would-be instance. Arguably we could live with this but in any
case the real fix is to address the ambiguity in notation, probably along the lines outlined here:
https://leanprover.zulipchat.com/#narrow/stream/144837-PR-reviews/topic/.234773.20base.20change/near/240929258
-/
protected def module : Module (A ⊗[R] B) M where
  smul x m := moduleAux x m
  zero_smul m := by simp only [(· • ·), map_zero, LinearMap.zero_apply]
  smul_zero x := by simp only [(· • ·), map_zero]
  smul_add x m₁ m₂ := by simp only [(· • ·), map_add]
  add_smul x y m := by 

Proof state:
R : Type u_1
A : Type u_2
B : Type u_3
M : Type u_4
inst✝¹¹ : CommSemiring R
inst✝¹⁰ : AddCommMonoid M
inst✝⁹ : Module R M
inst✝⁸ : Semiring A
inst✝⁷ : Semiring B
inst✝⁶ : Module A M
inst✝⁵ : Module B M
inst✝⁴ : Algebra R A
inst✝³ : Algebra R B
inst✝² : IsScalarTower R A M
inst✝¹ : IsScalarTower R B M
inst✝ : SMulCommClass A B M
x y : A ⊗[R] B
m : M
⊢ (x + y) • m = x • m + y • m

Next tactic:
simp only [(· • ·), map_add, LinearMap.add_apply]
/-- If `M` is a representation of two different `R`-algebras `A` and `B` whose actions commute,
then it is a representation the `R`-algebra `A ⊗[R] B`.

An important example arises from a semiring `S`; allowing `S` to act on itself via left and right
multiplication, the roles of `R`, `A`, `B`, `M` are played by `ℕ`, `S`, `Sᵐᵒᵖ`, `S`. This example
is important because a submodule of `S` as a `Module` over `S ⊗[ℕ] Sᵐᵒᵖ` is a two-sided ideal.

NB: This is not an instance because in the case `B = A` and `M = A ⊗[R] A` we would have a diamond
of `smul` actions. Furthermore, this would not be a mere definitional diamond but a true
mathematical diamond in which `A ⊗[R] A` had two distinct scalar actions on itself: one from its
multiplication, and one from this would-be instance. Arguably we could live with this but in any
case the real fix is to address the ambiguity in notation, probably along the lines outlined here:
https://leanprover.zulipchat.com/#narrow/stream/144837-PR-reviews/topic/.234773.20base.20change/near/240929258
-/
protected def module : Module (A ⊗[R] B) M where
  smul x m := moduleAux x m
  zero_smul m := by 

Proof state:
R : Type u_1
A : Type u_2
B : Type u_3
M : Type u_4
inst✝¹¹ : CommSemiring R
inst✝¹⁰ : AddCommMonoid M
inst✝⁹ : Module R M
inst✝⁸ : Semiring A
inst✝⁷ : Semiring B
inst✝⁶ : Module A M
inst✝⁵ : Module B M
inst✝⁴ : Algebra R A
inst✝³ : Algebra R B
inst✝² : IsScalarTower R A M
inst✝¹ : IsScalarTower R B M
inst✝ : SMulCommClass A B M
m : M
⊢ 0 • m = 0

Next tactic:
simp only [(· • ·), map_zero, LinearMap.zero_apply]
instance : Inhabited ℍ :=
  ⟨⟨Complex.I, by 

Proof state:
⊢ 0 < Complex.I.im

Next tactic:
simp
theorem normSq_pos (z : ℍ) : 0 < Complex.normSq (z : ℂ) := by
  

Proof state:
z : ℍ
⊢ 0 < Complex.normSq ↑z

Next tactic:
rw [Complex.normSq_pos]
theorem normSq_pos (z : ℍ) : 0 < Complex.normSq (z : ℂ) := by
  rw [Complex.normSq_pos]; 

Proof state:
z : ℍ
⊢ ↑z ≠ 0

Next tactic:
exact z.ne_zero
theorem im_inv_neg_coe_pos (z : ℍ) : 0 < (-z : ℂ)⁻¹.im := by
  

Proof state:
z : ℍ
⊢ 0 < (-↑z)⁻¹.im

Next tactic:
simpa using div_pos z.property (normSq_pos z)
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  

Proof state:
cd : Fin 2 → ℝ
z : ℍ
h : cd ≠ 0
⊢ ↑(cd 0) * ↑z + ↑(cd 1) ≠ 0

Next tactic:
contrapose! h
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  

Proof state:
cd : Fin 2 → ℝ
z : ℍ
h : ↑(cd 0) * ↑z + ↑(cd 1) = 0
⊢ cd = 0

Next tactic:
have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    

Proof state:
cd : Fin 2 → ℝ
z : ℍ
h : ↑(cd 0) * ↑z + ↑(cd 1) = 0
⊢ cd 0 = 0

Next tactic:
apply_fun Complex.im at h
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    

Proof state:
cd : Fin 2 → ℝ
z : ℍ
h : (↑(cd 0) * ↑z + ↑(cd 1)).im = 0.im
⊢ cd 0 = 0

Next tactic:
simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
  

Proof state:
cd : Fin 2 → ℝ
z : ℍ
h : ↑(cd 0) * ↑z + ↑(cd 1) = 0
this : cd 0 = 0
⊢ cd = 0

Next tactic:
simp only [this, zero_mul, Complex.ofReal_zero, zero_add, Complex.ofReal_eq_zero]
    at h
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
  simp only [this, zero_mul, Complex.ofReal_zero, zero_add, Complex.ofReal_eq_zero]
    at h
  

Proof state:
cd : Fin 2 → ℝ
z : ℍ
this : cd 0 = 0
h : cd 1 = 0
⊢ cd = 0

Next tactic:
ext i
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
  simp only [this, zero_mul, Complex.ofReal_zero, zero_add, Complex.ofReal_eq_zero]
    at h
  ext i
  

Proof state:
case h
cd : Fin 2 → ℝ
z : ℍ
this : cd 0 = 0
h : cd 1 = 0
i : Fin 2
⊢ cd i = OfNat.ofNat 0 i

Next tactic:
fin_cases i
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
  simp only [this, zero_mul, Complex.ofReal_zero, zero_add, Complex.ofReal_eq_zero]
    at h
  ext i
  fin_cases i <;> 

Proof state:
case h.head
cd : Fin 2 → ℝ
z : ℍ
this : cd 0 = 0
h : cd 1 = 0
⊢ cd { val := 0, isLt := (_ : 0 < 2) } = OfNat.ofNat 0 { val := 0, isLt := (_ : 0 < 2) }

Next tactic:
assumption
theorem linear_ne_zero (cd : Fin 2 → ℝ) (z : ℍ) (h : cd ≠ 0) : (cd 0 : ℂ) * z + cd 1 ≠ 0 := by
  contrapose! h
  have : cd 0 = 0 := by
    -- we will need this twice
    apply_fun Complex.im at h
    simpa only [z.im_ne_zero, Complex.add_im, add_zero, coe_im, zero_mul, or_false_iff,
      Complex.ofReal_im, Complex.zero_im, Complex.mul_im, mul_eq_zero] using h
  simp only [this, zero_mul, Complex.ofReal_zero, zero_add, Complex.ofReal_eq_zero]
    at h
  ext i
  fin_cases i <;> 

Proof state:
case h.tail.head
cd : Fin 2 → ℝ
z : ℍ
this : cd 0 = 0
h : cd 1 = 0
⊢ cd { val := 1, isLt := (_ : (fun a => a < 2) 1) } = OfNat.ofNat 0 { val := 1, isLt := (_ : (fun a => a < 2) 1) }

Next tactic:
assumption
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ denom g z ≠ 0

Next tactic:
intro H
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
⊢ False

Next tactic:
have DET := (mem_glpos _).1 g.prop
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < ↑(GeneralLinearGroup.det ↑g)
⊢ False

Next tactic:
have hz := z.prop
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < ↑(GeneralLinearGroup.det ↑g)
hz : 0 < (↑z).im
⊢ False

Next tactic:
simp only [GeneralLinearGroup.val_det_apply] at DET
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < det ↑↑g
hz : 0 < (↑z).im
⊢ False

Next tactic:
have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by 

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < det ↑↑g
hz : 0 < (↑z).im
⊢ ↑↑g 1 0 = 0 ∨ im z = 0

Next tactic:
simpa [num, denom] using congr_arg Complex.im H
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < det ↑↑g
hz : 0 < (↑z).im
H1 : ↑↑g 1 0 = 0 ∨ im z = 0
⊢ False

Next tactic:
cases' H1 with H1
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
  cases' H1 with H1
  · 

Proof state:
case inl
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < det ↑↑g
hz : 0 < (↑z).im
H1 : ↑↑g 1 0 = 0
⊢ False

Next tactic:
simp only [H1, Complex.ofReal_zero, denom, zero_mul, zero_add,
      Complex.ofReal_eq_zero] at H
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
  cases' H1 with H1
  · simp only [H1, Complex.ofReal_zero, denom, zero_mul, zero_add,
      Complex.ofReal_eq_zero] at H
    

Proof state:
case inl
g : ↥GL(2, ℝ)⁺
z : ℍ
DET : 0 < det ↑↑g
hz : 0 < (↑z).im
H1 : ↑↑g 1 0 = 0
H : ↑↑g 1 1 = 0
⊢ False

Next tactic:
rw [Matrix.det_fin_two (↑ₘg : Matrix (Fin 2) (Fin 2) ℝ)] at DET
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
  cases' H1 with H1
  · simp only [H1, Complex.ofReal_zero, denom, zero_mul, zero_add,
      Complex.ofReal_eq_zero] at H
    rw [Matrix.det_fin_two (↑ₘg : Matrix (Fin 2) (Fin 2) ℝ)] at DET
    

Proof state:
case inl
g : ↥GL(2, ℝ)⁺
z : ℍ
DET : 0 < ↑↑g 0 0 * ↑↑g 1 1 - ↑↑g 0 1 * ↑↑g 1 0
hz : 0 < (↑z).im
H1 : ↑↑g 1 0 = 0
H : ↑↑g 1 1 = 0
⊢ False

Next tactic:
simp only [H, H1, mul_zero, sub_zero, lt_self_iff_false] at DET
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
  cases' H1 with H1
  · simp only [H1, Complex.ofReal_zero, denom, zero_mul, zero_add,
      Complex.ofReal_eq_zero] at H
    rw [Matrix.det_fin_two (↑ₘg : Matrix (Fin 2) (Fin 2) ℝ)] at DET
    simp only [H, H1, mul_zero, sub_zero, lt_self_iff_false] at DET
  · 

Proof state:
case inr
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < det ↑↑g
hz : 0 < (↑z).im
h✝ : im z = 0
⊢ False

Next tactic:
change z.im > 0 at hz
theorem denom_ne_zero (g : GL(2, ℝ)⁺) (z : ℍ) : denom g z ≠ 0 := by
  intro H
  have DET := (mem_glpos _).1 g.prop
  have hz := z.prop
  simp only [GeneralLinearGroup.val_det_apply] at DET
  have H1 : (↑ₘg 1 0 : ℝ) = 0 ∨ z.im = 0 := by simpa [num, denom] using congr_arg Complex.im H
  cases' H1 with H1
  · simp only [H1, Complex.ofReal_zero, denom, zero_mul, zero_add,
      Complex.ofReal_eq_zero] at H
    rw [Matrix.det_fin_two (↑ₘg : Matrix (Fin 2) (Fin 2) ℝ)] at DET
    simp only [H, H1, mul_zero, sub_zero, lt_self_iff_false] at DET
  · change z.im > 0 at hz
    

Proof state:
case inr
g : ↥GL(2, ℝ)⁺
z : ℍ
H : denom g z = 0
DET : 0 < det ↑↑g
h✝ : im z = 0
hz : im z > 0
⊢ False

Next tactic:
linarith
theorem smulAux'_im (g : GL(2, ℝ)⁺) (z : ℍ) :
    (smulAux' g z).im = det ↑ₘg * z.im / Complex.normSq (denom g z) := by
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ (smulAux' g z).im = det ↑↑g * im z / Complex.normSq (denom g z)

Next tactic:
rw [smulAux', Complex.div_im]
theorem smulAux'_im (g : GL(2, ℝ)⁺) (z : ℍ) :
    (smulAux' g z).im = det ↑ₘg * z.im / Complex.normSq (denom g z) := by
  rw [smulAux', Complex.div_im]
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ (num g z).im * (denom g z).re / Complex.normSq (denom g z) -
      (num g z).re * (denom g z).im / Complex.normSq (denom g z) =
    det ↑↑g * im z / Complex.normSq (denom g z)

Next tactic:
field_simp [smulAux', num, denom]
theorem smulAux'_im (g : GL(2, ℝ)⁺) (z : ℍ) :
    (smulAux' g z).im = det ↑ₘg * z.im / Complex.normSq (denom g z) := by
  rw [smulAux', Complex.div_im]
  field_simp [smulAux', num, denom]
  -- porting note: the local notation still didn't work here
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ ↑↑g 0 0 * im z * (↑↑g 1 0 * re z + ↑↑g 1 1) / Complex.normSq (↑(↑↑g 1 0) * ↑z + ↑(↑↑g 1 1)) -
      (↑↑g 0 0 * re z + ↑↑g 0 1) * (↑↑g 1 0 * im z) / Complex.normSq (↑(↑↑g 1 0) * ↑z + ↑(↑↑g 1 1)) =
    det ↑↑g * im z / Complex.normSq (↑(↑↑g 1 0) * ↑z + ↑(↑↑g 1 1))

Next tactic:
rw [Matrix.det_fin_two ((g : GL (Fin 2) ℝ) : Matrix (Fin 2) (Fin 2) ℝ)]
theorem smulAux'_im (g : GL(2, ℝ)⁺) (z : ℍ) :
    (smulAux' g z).im = det ↑ₘg * z.im / Complex.normSq (denom g z) := by
  rw [smulAux', Complex.div_im]
  field_simp [smulAux', num, denom]
  -- porting note: the local notation still didn't work here
  rw [Matrix.det_fin_two ((g : GL (Fin 2) ℝ) : Matrix (Fin 2) (Fin 2) ℝ)]
  

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ ↑↑g 0 0 * im z * (↑↑g 1 0 * re z + ↑↑g 1 1) / Complex.normSq (↑(↑↑g 1 0) * ↑z + ↑(↑↑g 1 1)) -
      (↑↑g 0 0 * re z + ↑↑g 0 1) * (↑↑g 1 0 * im z) / Complex.normSq (↑(↑↑g 1 0) * ↑z + ↑(↑↑g 1 1)) =
    (↑↑g 0 0 * ↑↑g 1 1 - ↑↑g 0 1 * ↑↑g 1 0) * im z / Complex.normSq (↑(↑↑g 1 0) * ↑z + ↑(↑↑g 1 1))

Next tactic:
ring
/-- Fractional linear transformation, also known as the Moebius transformation -/
def smulAux (g : GL(2, ℝ)⁺) (z : ℍ) : ℍ :=
  mk (smulAux' g z) <| by
    

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ 0 < (smulAux' g z).im

Next tactic:
rw [smulAux'_im]
/-- Fractional linear transformation, also known as the Moebius transformation -/
def smulAux (g : GL(2, ℝ)⁺) (z : ℍ) : ℍ :=
  mk (smulAux' g z) <| by
    rw [smulAux'_im]
    

Proof state:
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ 0 < det ↑↑g * im z / Complex.normSq (denom g z)

Next tactic:
convert mul_pos ((mem_glpos _).1 g.prop)
        (div_pos z.im_pos (Complex.normSq_pos.mpr (denom_ne_zero g z))) using 1
/-- Fractional linear transformation, also known as the Moebius transformation -/
def smulAux (g : GL(2, ℝ)⁺) (z : ℍ) : ℍ :=
  mk (smulAux' g z) <| by
    rw [smulAux'_im]
    convert mul_pos ((mem_glpos _).1 g.prop)
        (div_pos z.im_pos (Complex.normSq_pos.mpr (denom_ne_zero g z))) using 1
    

Proof state:
case h.e'_4
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ det ↑↑g * im z / Complex.normSq (denom g z) = ↑(GeneralLinearGroup.det ↑g) * (im z / Complex.normSq (denom g z))

Next tactic:
simp only [GeneralLinearGroup.val_det_apply]
/-- Fractional linear transformation, also known as the Moebius transformation -/
def smulAux (g : GL(2, ℝ)⁺) (z : ℍ) : ℍ :=
  mk (smulAux' g z) <| by
    rw [smulAux'_im]
    convert mul_pos ((mem_glpos _).1 g.prop)
        (div_pos z.im_pos (Complex.normSq_pos.mpr (denom_ne_zero g z))) using 1
    simp only [GeneralLinearGroup.val_det_apply]
    

Proof state:
case h.e'_4
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ det ↑↑g * im z / Complex.normSq (denom g z) = det ↑↑g * (im z / Complex.normSq (denom g z))

Next tactic:
ring
theorem denom_cocycle (x y : GL(2, ℝ)⁺) (z : ℍ) :
    denom (x * y) z = denom x (smulAux y z) * denom y z := by
  

Proof state:
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ denom (x * y) z = denom x (smulAux y z) * denom y z

Next tactic:
change _ = (_ * (_ / _) + _) * _
theorem denom_cocycle (x y : GL(2, ℝ)⁺) (z : ℍ) :
    denom (x * y) z = denom x (smulAux y z) * denom y z := by
  change _ = (_ * (_ / _) + _) * _
  

Proof state:
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ denom (x * y) z = (↑(↑↑x 1 0) * (num y z / denom y z) + ↑(↑↑x 1 1)) * denom y z

Next tactic:
field_simp [denom_ne_zero]
theorem denom_cocycle (x y : GL(2, ℝ)⁺) (z : ℍ) :
    denom (x * y) z = denom x (smulAux y z) * denom y z := by
  change _ = (_ * (_ / _) + _) * _
  field_simp [denom_ne_zero]
  

Proof state:
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ denom (x * y) z = ↑(↑↑x 1 0) * num y z + ↑(↑↑x 1 1) * denom y z

Next tactic:
simp only [Matrix.mul_apply, dotProduct, Fin.sum_univ_succ, denom, num, Subgroup.coe_mul,
    GeneralLinearGroup.coe_mul, Fintype.univ_ofSubsingleton, Fin.mk_zero, Finset.sum_singleton,
    Fin.succ_zero_eq_one, Complex.ofReal_add, Complex.ofReal_mul]
theorem denom_cocycle (x y : GL(2, ℝ)⁺) (z : ℍ) :
    denom (x * y) z = denom x (smulAux y z) * denom y z := by
  change _ = (_ * (_ / _) + _) * _
  field_simp [denom_ne_zero]
  simp only [Matrix.mul_apply, dotProduct, Fin.sum_univ_succ, denom, num, Subgroup.coe_mul,
    GeneralLinearGroup.coe_mul, Fintype.univ_ofSubsingleton, Fin.mk_zero, Finset.sum_singleton,
    Fin.succ_zero_eq_one, Complex.ofReal_add, Complex.ofReal_mul]
  

Proof state:
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ (↑(↑↑x 1 0) * ↑(↑↑y 0 0) + ↑(↑↑x 1 1) * ↑(↑↑y 1 0)) * ↑z + (↑(↑↑x 1 0) * ↑(↑↑y 0 1) + ↑(↑↑x 1 1) * ↑(↑↑y 1 1)) =
    ↑(↑↑x 1 0) * (↑(↑↑y 0 0) * ↑z + ↑(↑↑y 0 1)) + ↑(↑↑x 1 1) * (↑(↑↑y 1 0) * ↑z + ↑(↑↑y 1 1))

Next tactic:
ring
theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by
  

Proof state:
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ smulAux (x * y) z = smulAux x (smulAux y z)

Next tactic:
ext1
theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by
  ext1
  -- Porting note: was `change _ / _ = (_ * (_ / _) + _) * _`
  

Proof state:
case h
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ ↑(smulAux (x * y) z) = ↑(smulAux x (smulAux y z))

Next tactic:
change _ / _ = (_ * (_ / _) + _) / _
theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by
  ext1
  -- Porting note: was `change _ / _ = (_ * (_ / _) + _) * _`
  change _ / _ = (_ * (_ / _) + _) / _
  

Proof state:
case h
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ num (x * y) z / denom (x * y) z = (↑(↑↑x 0 0) * (num y z / denom y z) + ↑(↑↑x 0 1)) / denom x (smulAux y z)

Next tactic:
rw [denom_cocycle]
theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by
  ext1
  -- Porting note: was `change _ / _ = (_ * (_ / _) + _) * _`
  change _ / _ = (_ * (_ / _) + _) / _
  rw [denom_cocycle]
  

Proof state:
case h
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ num (x * y) z / (denom x (smulAux y z) * denom y z) =
    (↑(↑↑x 0 0) * (num y z / denom y z) + ↑(↑↑x 0 1)) / denom x (smulAux y z)

Next tactic:
field_simp [denom_ne_zero]
theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by
  ext1
  -- Porting note: was `change _ / _ = (_ * (_ / _) + _) * _`
  change _ / _ = (_ * (_ / _) + _) / _
  rw [denom_cocycle]
  field_simp [denom_ne_zero]
  

Proof state:
case h
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ num (x * y) z * (denom y z * denom x (smulAux y z)) =
    (↑(↑↑x 0 0) * num y z + ↑(↑↑x 0 1) * denom y z) * (denom x (smulAux y z) * denom y z)

Next tactic:
simp only [Matrix.mul_apply, dotProduct, Fin.sum_univ_succ, num, denom, Subgroup.coe_mul,
    GeneralLinearGroup.coe_mul, Fintype.univ_ofSubsingleton, Fin.mk_zero, Finset.sum_singleton,
    Fin.succ_zero_eq_one, Complex.ofReal_add, Complex.ofReal_mul]
theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by
  ext1
  -- Porting note: was `change _ / _ = (_ * (_ / _) + _) * _`
  change _ / _ = (_ * (_ / _) + _) / _
  rw [denom_cocycle]
  field_simp [denom_ne_zero]
  simp only [Matrix.mul_apply, dotProduct, Fin.sum_univ_succ, num, denom, Subgroup.coe_mul,
    GeneralLinearGroup.coe_mul, Fintype.univ_ofSubsingleton, Fin.mk_zero, Finset.sum_singleton,
    Fin.succ_zero_eq_one, Complex.ofReal_add, Complex.ofReal_mul]
  

Proof state:
case h
x y : ↥GL(2, ℝ)⁺
z : ℍ
⊢ ((↑(↑↑x 0 0) * ↑(↑↑y 0 0) + ↑(↑↑x 0 1) * ↑(↑↑y 1 0)) * ↑z + (↑(↑↑x 0 0) * ↑(↑↑y 0 1) + ↑(↑↑x 0 1) * ↑(↑↑y 1 1))) *
      ((↑(↑↑y 1 0) * ↑z + ↑(↑↑y 1 1)) * (↑(↑↑x 1 0) * ↑(smulAux y z) + ↑(↑↑x 1 1))) =
    (↑(↑↑x 0 0) * (↑(↑↑y 0 0) * ↑z + ↑(↑↑y 0 1)) + ↑(↑↑x 0 1) * (↑(↑↑y 1 0) * ↑z + ↑(↑↑y 1 1))) *
      ((↑(↑↑x 1 0) * ↑(smulAux y z) + ↑(↑↑x 1 1)) * (↑(↑↑y 1 0) * ↑z + ↑(↑↑y 1 1)))

Next tactic:
ring
/-- The action of `GLPos 2 ℝ` on the upper half-plane by fractional linear transformations. -/
instance : MulAction GL(2, ℝ)⁺ ℍ where
  smul := smulAux
  one_smul z := by
    

Proof state:
z : ℍ
⊢ 1 • z = z

Next tactic:
ext1
/-- The action of `GLPos 2 ℝ` on the upper half-plane by fractional linear transformations. -/
instance : MulAction GL(2, ℝ)⁺ ℍ where
  smul := smulAux
  one_smul z := by
    ext1
    

Proof state:
case h
z : ℍ
⊢ ↑(1 • z) = ↑z

Next tactic:
change _ / _ = _
/-- The action of `GLPos 2 ℝ` on the upper half-plane by fractional linear transformations. -/
instance : MulAction GL(2, ℝ)⁺ ℍ where
  smul := smulAux
  one_smul z := by
    ext1
    change _ / _ = _
    

Proof state:
case h
z : ℍ
⊢ num 1 z / denom 1 z = ↑z

Next tactic:
simp [num, denom]
set_option autoImplicit true in
@[simp]
theorem det_coe' : det (Units.val <| Subtype.val <| coe' g) = 1 := by
  

Proof state:
Γ : Subgroup SL(2, ℤ)
g : SL(2, ℤ)
⊢ det ↑↑↑g = 1

Next tactic:
simp only [SpecialLinearGroup.coe_GLPos_coe_GL_coe_matrix, SpecialLinearGroup.det_coe, coe']
instance SL_to_GL_tower : IsScalarTower SL(2, ℤ) GL(2, ℝ)⁺ ℍ where
  smul_assoc := by
    

Proof state:
Γ : Subgroup SL(2, ℤ)
⊢ ∀ (x : SL(2, ℤ)) (y : ↥GL(2, ℝ)⁺) (z : ℍ), (x • y) • z = x • y • z

Next tactic:
intro s g z
instance SL_to_GL_tower : IsScalarTower SL(2, ℤ) GL(2, ℝ)⁺ ℍ where
  smul_assoc := by
    intro s g z
    

Proof state:
Γ : Subgroup SL(2, ℤ)
s : SL(2, ℤ)
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ (s • g) • z = s • g • z

Next tactic:
simp only [SLOnGLPos_smul_apply]
instance SL_to_GL_tower : IsScalarTower SL(2, ℤ) GL(2, ℝ)⁺ ℍ where
  smul_assoc := by
    intro s g z
    simp only [SLOnGLPos_smul_apply]
    

Proof state:
Γ : Subgroup SL(2, ℤ)
s : SL(2, ℤ)
g : ↥GL(2, ℝ)⁺
z : ℍ
⊢ (↑s * g) • z = s • g • z

Next tactic:
apply mul_smul'
instance subgroup_on_glpos : IsScalarTower Γ GL(2, ℝ)⁺ ℍ where
  smul_assoc := by
    

Proof state:
Γ : Subgroup SL(2, ℤ)
⊢ ∀ (x : ↥Γ) (y : ↥GL(2, ℝ)⁺) (z : ℍ), (x • y) • z = x • y • z

Next tactic:
intro s g z