-- Mathlib/Analysis/Complex/UpperHalfPlane/Topology.lean
theorem ModularGroup_T_zpow_mem_verticalStrip (z : ℍ) {N : ℕ} (hn : 0 < N) :
    ∃ n : ℤ, ModularGroup.T ^ (N * n) • z ∈ verticalStrip N z.im

Proof state:
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ ∃ n, ModularGroup.T ^ (↑N * n) • z ∈ verticalStrip (↑N) z.im

Tactic:
use -n

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ ModularGroup.T ^ (↑N * -n) • z ∈ verticalStrip (↑N) z.im

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
h2 : z.re + -(↑N * ↑n) = z.re - ↑n * ↑N
⊢ z.re - ↑⌊z.re / ↑N⌋ * ↑N ≤ ↑N

Tactic:
apply (Int.sub_floor_div_mul_lt (z.re : ℝ) hnn).le

Result:
no goals

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ |z.re + ↑(-↑N * ⌊z.re / ↑N⌋)| ≤ ↑N

Tactic:
simp only [neg_mul, Int.cast_neg, Int.cast_mul, Int.cast_natCast]

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ |z.re + -(↑N * ↑⌊z.re / ↑N⌋)| ≤ ↑N

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
h2 : z.re + -(↑N * ↑n) = z.re - ↑n * ↑N
⊢ |z.re + -(↑N * ↑⌊z.re / ↑N⌋)| ≤ ↑N

Tactic:
rw [h2, abs_eq_self.2 (Int.sub_floor_div_mul_nonneg (z.re : ℝ) hnn)]

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
h2 : z.re + -(↑N * ↑n) = z.re - ↑n * ↑N
⊢ z.re - ↑⌊z.re / ↑N⌋ * ↑N ≤ ↑N

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ |z.re + -(↑N * ↑⌊z.re / ↑N⌋)| ≤ ↑N

Tactic:
have hnn : (0 : ℝ) < (N : ℝ) := by norm_cast at *

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
⊢ |z.re + -(↑N * ↑⌊z.re / ↑N⌋)| ≤ ↑N

Proof state:
z : ℍ
N : ℕ
hn : 0 < N
⊢ ∃ n, ModularGroup.T ^ (↑N * n) • z ∈ verticalStrip (↑N) z.im

Tactic:
let n := Int.floor (z.re/N)

Result:
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ ∃ n, ModularGroup.T ^ (↑N * n) • z ∈ verticalStrip (↑N) z.im

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
⊢ |z.re + -(↑N * ↑⌊z.re / ↑N⌋)| ≤ ↑N

Tactic:
have h2 : z.re + -(N * n) =  z.re - n * N := by ring

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
h2 : z.re + -(↑N * ↑n) = z.re - ↑n * ↑N
⊢ |z.re + -(↑N * ↑⌊z.re / ↑N⌋)| ≤ ↑N

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑N * -↑n +ᵥ z).re = -↑N * ↑⌊z.re / ↑N⌋ + z.re
⊢ |(↑(↑N * -n) +ᵥ z).re| ≤ ↑N

Tactic:
norm_cast at *

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ |(↑(↑N * -n) +ᵥ z).re| ≤ ↑N

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ ↑(↑N * -n) +ᵥ z ∈ verticalStrip (↑N) z.im

Tactic:
refine ⟨?_, (by simp only [mul_neg, Int.cast_neg, Int.cast_mul, Int.cast_natCast, vadd_im,
  le_refl])⟩

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ |(↑(↑N * -n) +ᵥ z).re| ≤ ↑N

Proof state:
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ (↑N * -↑n +ᵥ z).re = -↑N * ↑⌊z.re / ↑N⌋ + z.re

Tactic:
simp only [n, Int.cast_natCast, mul_neg, vadd_re, neg_mul]

Result:
no goals

Proof state:
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ z.im ≤ (↑(↑N * -n) +ᵥ z).im

Tactic:
simp only [mul_neg, Int.cast_neg, Int.cast_mul, Int.cast_natCast, vadd_im,
le_refl]

Result:
no goals

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ |(↑(↑N * -n) +ᵥ z).re| ≤ ↑N

Tactic:
rw [h, add_comm]

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ |z.re + ↑(-↑N * ⌊z.re / ↑N⌋)| ≤ ↑N

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ ModularGroup.T ^ (↑N * -n) • z ∈ verticalStrip (↑N) z.im

Tactic:
rw [modular_T_zpow_smul z (N * -n)]

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ ↑(↑N * -n) +ᵥ z ∈ verticalStrip (↑N) z.im

Proof state:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
⊢ |(↑(↑N * -n) +ᵥ z).re| ≤ ↑N

Tactic:
have h : (N * (-n : ℝ) +ᵥ z).re = -N * Int.floor (z.re / N) + z.re := by
  simp only [n, Int.cast_natCast, mul_neg, vadd_re, neg_mul]

Result:
case h
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑N * -↑n +ᵥ z).re = -↑N * ↑⌊z.re / ↑N⌋ + z.re
⊢ |(↑(↑N * -n) +ᵥ z).re| ≤ ↑N

Proof state:
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
⊢ 0 < ↑N

Tactic:
norm_cast at *

Result:
no goals

Proof state:
z : ℍ
N : ℕ
hn : 0 < N
n : ℤ := ⌊z.re / ↑N⌋
h : (↑(↑N * -n) +ᵥ z).re = ↑(-↑N * ⌊z.re / ↑N⌋) + z.re
hnn : 0 < ↑N
⊢ z.re + -(↑N * ↑n) = z.re - ↑n * ↑N

Tactic:
ring

Result:
no goals