Skip to content

Commit f29d34c

Browse files
committed
chore: clean up Mathlib.Analysis.Real.OfDigits (leanprover-community#29566)
This PR golfs the proofs, removes an unnecessary assumption from `ofDigits_digits_sum_eq`, changes the name of `sum_ofDigitsTerm_digits_ge` to `le_sum_ofDigitsTerm_digits` without leaving a deprecation, and removes the use of the `move_mul` tactic.
1 parent 47d990e commit f29d34c

2 files changed

Lines changed: 40 additions & 93 deletions

File tree

Mathlib/Analysis/Real/OfDigits.lean

Lines changed: 40 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ Authors: Vasilii Nesterov
55
-/
66
import Mathlib.Algebra.Order.Floor.Semifield
77
import Mathlib.Analysis.SpecificLimits.Normed
8-
import Mathlib.Tactic.MoveAdd
98
import Mathlib.Tactic.Rify
109

1110
/-!
@@ -50,24 +49,12 @@ theorem ofDigitsTerm_le {b : ℕ} {digits : ℕ → Fin b} {n : ℕ} :
5049

5150
theorem summable_ofDigitsTerm {b : ℕ} {digits : ℕ → Fin b} :
5251
Summable (ofDigitsTerm digits) := by
53-
have hb : 0 < b := b_pos digits
54-
obtain rfl | hb := (Nat.one_le_of_lt hb).eq_or_lt
55-
· have : ofDigitsTerm digits = 0 := by
56-
ext i
57-
simp [ofDigitsTerm]
58-
simp only [this]
59-
exact summable_zero
60-
have h := summable_geometric_of_lt_one (r := (b⁻¹ : ℝ)) (by simp)
61-
(by rify at hb; exact inv_lt_one_of_one_lt₀ hb)
62-
apply Summable.mul_left (a := (b : ℝ)) at h
63-
replace h : Summable fun i ↦ b * (b : ℝ)⁻¹ ^ (i + 1) := by
64-
simp_rw [pow_succ', ← mul_assoc, mul_comm (b : ℝ), mul_assoc, Summable.mul_left _ h]
65-
apply Summable.of_nonneg_of_le (fun _ ↦ ofDigitsTerm_nonneg) _ h
66-
intro i
67-
apply le_trans ofDigitsTerm_le
68-
gcongr
69-
· simp
70-
· rw [inv_pow]
52+
refine Summable.of_nonneg_of_le (fun _ ↦ ofDigitsTerm_nonneg) (fun _ ↦ ofDigitsTerm_le) ?_
53+
obtain rfl | hb := (Nat.one_le_of_lt (b_pos digits)).eq_or_lt
54+
· simpa using summable_zero
55+
simp_rw [pow_succ', mul_inv, ← inv_pow, ← mul_assoc]
56+
refine Summable.mul_left _ (summable_geometric_of_lt_one (by positivity) ?_)
57+
simp [inv_lt_one_iff₀, hb]
7158

7259
/-- `ofDigits d` is the real number `0.d₀d₁d₂...` in base `b`.
7360
We allow repeating representations like `0.999...` here. -/
@@ -79,24 +66,17 @@ theorem ofDigits_nonneg {b : ℕ} (digits : ℕ → Fin b) : 0 ≤ ofDigits digi
7966
exact tsum_nonneg fun _ ↦ ofDigitsTerm_nonneg
8067

8168
theorem ofDigits_le_one {b : ℕ} (digits : ℕ → Fin b) : ofDigits digits ≤ 1 := by
82-
have hb : 0 < b := b_pos digits
83-
obtain rfl | hb' := (Nat.one_le_of_lt hb).eq_or_lt
69+
obtain rfl | hb := (Nat.one_le_of_lt (b_pos digits)).eq_or_lt
8470
· simp [ofDigits, ofDigitsTerm]
85-
rify at hb'
86-
have hb_inv_nonneg : 0 ≤ (b⁻¹ : ℝ) := by simp
87-
have hb_inv_lt_one : (b⁻¹ : ℝ) < 1 := by bound
88-
simp only [ofDigits]
89-
let g (i : ℕ) : ℝ := (1 - (b⁻¹ : ℝ)) * (b⁻¹ : ℝ) ^ i
90-
have hg_summable : Summable g :=
91-
(summable_geometric_of_lt_one (by simp) (inv_lt_one_of_one_lt₀ hb')).mul_left _
92-
convert Summable.tsum_mono (summable_ofDigitsTerm) hg_summable _
93-
· simp only [tsum_mul_left, g]
94-
rw [tsum_geometric_of_lt_one hb_inv_nonneg hb_inv_lt_one, mul_inv_cancel₀ (by linarith)]
95-
· intro i
96-
simp only [inv_pow, g]
97-
convert ofDigitsTerm_le using 1
71+
rify at hb
72+
convert Summable.tsum_mono summable_ofDigitsTerm _ (fun _ ↦ ofDigitsTerm_le)
73+
· simp_rw [pow_succ', mul_inv, ← inv_pow, ← mul_assoc]
74+
rw [tsum_mul_left, tsum_geometric_of_lt_one (by positivity) (by simp [inv_lt_one_iff₀, hb])]
75+
have := sub_pos.mpr hb
9876
field_simp
99-
ring
77+
· simp_rw [pow_succ', mul_inv, ← inv_pow, ← mul_assoc]
78+
refine Summable.mul_left _ (summable_geometric_of_lt_one (by positivity) ?_)
79+
simp [inv_lt_one_iff₀, hb]
10080

10181
theorem ofDigits_eq_sum_add_ofDigits {b : ℕ} (a : ℕ → Fin b) (n : ℕ) :
10282
ofDigits a = (∑ i ∈ Finset.range n, ofDigitsTerm a i) +
@@ -113,91 +93,59 @@ theorem abs_ofDigits_sub_ofDigits_le {b : ℕ} {x y : ℕ → Fin b} {n : ℕ}
11393
(hxy : ∀ i < n, x i = y i) :
11494
|ofDigits x - ofDigits y| ≤ ((b : ℝ) ^ n)⁻¹ := by
11595
rw [ofDigits_eq_sum_add_ofDigits x n, ofDigits_eq_sum_add_ofDigits y n]
116-
have : ∑ i ∈ Finset.range n, ofDigitsTerm x i = ∑ i ∈ Finset.range n, ofDigitsTerm y i := by
117-
apply Finset.sum_congr rfl
118-
intro i hi
119-
simp only [Finset.mem_range] at hi
120-
simp [ofDigitsTerm, hxy i hi]
121-
simp only [this, add_sub_add_left_eq_sub, ge_iff_le]
122-
rw [← mul_sub, abs_mul, abs_of_nonneg (by positivity)]
96+
have : ∑ i ∈ Finset.range n, ofDigitsTerm x i = ∑ i ∈ Finset.range n, ofDigitsTerm y i :=
97+
Finset.sum_congr rfl fun i hi ↦ by simp [ofDigitsTerm, hxy i (Finset.mem_range.mp hi)]
98+
rw [this, add_sub_add_left_eq_sub, ← mul_sub, abs_mul, abs_of_nonneg (by positivity)]
12399
apply mul_le_of_le_one_right (by positivity)
124-
rw [abs_le']
125-
constructor <;> linarith [ofDigits_nonneg (fun i ↦ x (i + n)),
126-
ofDigits_nonneg (fun i ↦ y (i + n)), ofDigits_le_one (fun i ↦ x (i + n)),
127-
ofDigits_le_one (fun i ↦ y (i + n))]
100+
convert abs_sub_le_of_le_of_le (ofDigits_nonneg _) (ofDigits_le_one _)
101+
(ofDigits_nonneg _) (ofDigits_le_one _)
102+
simp
128103

129104
/-- Converts a real number `x` from the interval `[0, 1)` into sequence of
130105
its digits in base `b`. -/
131106
noncomputable def digits (x : ℝ) (b : ℕ) [NeZero b] : ℕ → Fin b :=
132107
fun i ↦ Fin.ofNat _ <| ⌊x * b ^ (i + 1)⌋₊
133108

134-
theorem ofDigits_digits_sum_eq {x : ℝ} {b : ℕ} [NeZero b] (hb : 1 < b)
135-
(hx : x ∈ Set.Ico 0 1) (n : ℕ) :
109+
theorem ofDigits_digits_sum_eq {x : ℝ} {b : ℕ} [NeZero b] (hx : x ∈ Set.Ico 0 1) (n : ℕ) :
136110
b ^ n * ∑ i ∈ Finset.range n, ofDigitsTerm (digits x b) i = ⌊b ^ n * x⌋₊ := by
111+
have := NeZero.ne b
137112
induction n with
138-
| zero =>
139-
simp only [pow_zero, Finset.range_zero, Finset.sum_empty, mul_zero, one_mul]
140-
rw [Set.mem_Ico] at hx
141-
norm_cast
142-
symm
143-
rw [Nat.floor_eq_zero]
144-
exact hx.right
113+
| zero => simp [Nat.floor_eq_zero.mpr hx.right]
145114
| succ n ih =>
146-
rw [Finset.sum_range_succ, mul_add, pow_succ', mul_assoc, ih]
147-
simp only [ofDigitsTerm, digits]
148-
rw [show x * (b : ℝ) ^ (n + 1) = b * (b ^ n * x) by ring]
149-
conv => rhs; rw [mul_assoc]
115+
rw [Finset.sum_range_succ, mul_add, pow_succ', mul_assoc, ih, ofDigitsTerm, digits, ← pow_succ',
116+
mul_left_comm, mul_inv_cancel₀ (by positivity), mul_one, mul_comm x, pow_succ', mul_assoc]
150117
set y := (b : ℝ) ^ n * x
151-
ring_nf
152-
move_mul [← (b : ℝ)⁻¹]
153-
have hb_zero : (b : ℝ) ≠ 0 := by
154-
simpa using NeZero.ne b
155-
simp only [inv_mul_cancel₀ hb_zero, one_mul, Fin.ofNat_eq_cast, Fin.val_natCast, inv_pow]
156-
move_mul [← ((b : ℝ) ^ n)⁻¹]
157-
rw [inv_mul_cancel₀ (by positivity), one_mul]
158118
norm_cast
159-
rw [← Nat.cast_mul_floor_div_cancel (a := y) (show b ≠ 0 by omega), Nat.mod_add_div]
119+
rw [← Nat.cast_mul_floor_div_cancel (a := y) (show b ≠ 0 by omega),
120+
Fin.val_ofNat, Nat.div_add_mod]
160121

161-
theorem sum_ofDigitsTerm_digits_ge {x : ℝ} {b : ℕ} [NeZero b] (hb : 1 < b)
122+
theorem le_sum_ofDigitsTerm_digits {x : ℝ} {b : ℕ} [NeZero b] (hb : 1 < b)
162123
(hx : x ∈ Set.Ico 0 1) (n : ℕ) :
163124
x - (b⁻¹ : ℝ) ^ n ≤ ∑ i ∈ Finset.range n, ofDigitsTerm (digits x b) i := by
164-
have := ofDigits_digits_sum_eq hb hx n
125+
have := ofDigits_digits_sum_eq (b := b) hx n
165126
have h_le := Nat.lt_floor_add_one (b ^ n * x)
166127
rw [← this] at h_le
167128
rw [← mul_le_mul_iff_right₀ (show 0 < (b : ℝ) ^ n by positivity),
168129
mul_sub, inv_pow, mul_inv_cancel₀ (by positivity)]
169130
linarith
170131

171-
theorem sum_ofDigitsTerm_digits_le {x : ℝ} {b : ℕ} [NeZero b] (hb : 1 < b) {n : ℕ}
172-
(hx : x ∈ Set.Ico 0 1) :
132+
theorem sum_ofDigitsTerm_digits_le {x : ℝ} {b : ℕ} [NeZero b]
133+
(hx : x ∈ Set.Ico 0 1) (n : ℕ) :
173134
∑ i ∈ Finset.range n, ofDigitsTerm (digits x b) i ≤ x := by
174-
have := ofDigits_digits_sum_eq hb hx n
135+
have := ofDigits_digits_sum_eq (b := b) hx n
175136
have h_le := Nat.floor_le (a := b ^ n * x) (by have := hx.left; positivity)
137+
have hb := NeZero.ne b
176138
rw [← this, mul_le_mul_iff_of_pos_left (by positivity)] at h_le
177139
exact h_le
178140

179141
theorem hasSum_ofDigitsTerm_digits (x : ℝ) {b : ℕ} [NeZero b] (hb : 1 < b) (hx : x ∈ Set.Ico 0 1) :
180142
HasSum (ofDigitsTerm (digits x b)) x := by
181-
rw [hasSum_iff_tendsto_nat_of_summable_norm]
182-
swap
183-
· conv => arg 1; ext i; rw [norm_eq_abs, abs_of_nonneg (by simp [ofDigitsTerm]; positivity)]
184-
exact summable_ofDigitsTerm
185-
rw [← tendsto_sub_nhds_zero_iff]
186-
apply tendsto_of_tendsto_of_tendsto_of_le_of_le (g := fun n ↦ -(b⁻¹ : ℝ) ^ n) (h := 0)
187-
· rw [show (0 : ℝ) = -0 by simp]
188-
apply Filter.Tendsto.neg
189-
apply tendsto_pow_atTop_nhds_zero_of_abs_lt_one
190-
rw [abs_of_nonneg (by positivity)]
191-
rify at hb
192-
exact inv_lt_one_of_one_lt₀ hb
193-
· apply tendsto_const_nhds
194-
· intro n
195-
simp only [inv_pow, neg_le_sub_iff_le_add]
196-
have := sum_ofDigitsTerm_digits_ge hb hx n
197-
simp only [inv_pow, tsub_le_iff_right] at this
198-
linarith
199-
· intro n
200-
simp [sum_ofDigitsTerm_digits_le hb hx]
143+
rw [hasSum_iff_tendsto_nat_of_summable_norm (by exact summable_ofDigitsTerm.abs)]
144+
refine tendsto_of_tendsto_of_tendsto_of_le_of_le ?_ tendsto_const_nhds
145+
(le_sum_ofDigitsTerm_digits hb hx) (sum_ofDigitsTerm_digits_le hx)
146+
convert tendsto_const_nhds.sub (tendsto_pow_atTop_nhds_zero_of_abs_lt_one _)
147+
· simp
148+
· simp [abs_of_nonneg, inv_lt_one_iff₀, hb]
201149

202150
theorem ofDigits_digits {b : ℕ} [NeZero b] {x : ℝ} (hb : 1 < b) (hx : x ∈ Set.Ico 0 1) :
203151
ofDigits (digits x b) = x := by

scripts/noshake.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,6 @@
501501
"Mathlib.Analysis.Real.Pi.Chudnovsky":
502502
["Batteries.Data.Rat.Float",
503503
"Mathlib.Analysis.SpecialFunctions.Integrals.Basic"],
504-
"Mathlib.Analysis.Real.OfDigits": ["Mathlib.Tactic.MoveAdd"],
505504
"Mathlib.Analysis.Normed.Operator.LinearIsometry":
506505
["Mathlib.Algebra.Star.Basic"],
507506
"Mathlib.Analysis.Normed.Group.AddCircle":

0 commit comments

Comments
 (0)