Skip to content

Commit 331a5bb

Browse files
RemyDegenneRuben-VandeVeldeChrisHughes24
committed
feat: port Data.Nat.Log (#1089)
11bb0c9152e5d14278fb0ac5e0be6d50e2c8fa05 Warning: attributes `mono` and `pp_nodot` are unknown and were commented out (with porting notes). Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com>
1 parent 1bec125 commit 331a5bb

File tree

2 files changed

+373
-0
lines changed

2 files changed

+373
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ import Mathlib.Data.Nat.Choose.Basic
205205
import Mathlib.Data.Nat.Dist
206206
import Mathlib.Data.Nat.Factorial.Basic
207207
import Mathlib.Data.Nat.Gcd.Basic
208+
import Mathlib.Data.Nat.Log
208209
import Mathlib.Data.Nat.Order.Basic
209210
import Mathlib.Data.Nat.Order.Lemmas
210211
import Mathlib.Data.Nat.PSub

Mathlib/Data/Nat/Log.lean

Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
/-
2+
Copyright (c) 2020 Simon Hudon. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Simon Hudon, Yaël Dillies
5+
Ported by: Rémy Degenne
6+
7+
! This file was ported from Lean 3 source module data.nat.log
8+
! leanprover-community/mathlib commit 11bb0c9152e5d14278fb0ac5e0be6d50e2c8fa05
9+
! Please do not edit these lines, except to modify the commit id
10+
! if you have ported upstream changes.
11+
-/
12+
import Mathlib.Data.Nat.Pow
13+
import Mathlib.Tactic.ByContra
14+
15+
/-!
16+
# Natural number logarithms
17+
18+
This file defines two `ℕ`-valued analogs of the logarithm of `n` with base `b`:
19+
* `log b n`: Lower logarithm, or floor **log**. Greatest `k` such that `b^k ≤ n`.
20+
* `clog b n`: Upper logarithm, or **c**eil **log**. Least `k` such that `n ≤ b^k`.
21+
22+
These are interesting because, for `1 < b`, `Nat.log b` and `Nat.clog b` are respectively right and
23+
left adjoints of `Nat.pow b`. See `pow_le_iff_le_log` and `le_pow_iff_clog_le`.
24+
-/
25+
26+
27+
namespace Nat
28+
29+
/-! ### Floor logarithm -/
30+
31+
32+
/-- `log b n`, is the logarithm of natural number `n` in base `b`. It returns the largest `k : ℕ`
33+
such that `b^k ≤ n`, so if `b^k = n`, it returns exactly `k`. -/
34+
--@[pp_nodot] porting note: unknown attribute
35+
def log (b : ℕ) : ℕ → ℕ
36+
| n =>
37+
if h : b ≤ n ∧ 1 < b then
38+
have : n / b < n := div_lt_self ((zero_lt_one.trans h.2).trans_le h.1) h.2
39+
log b (n / b) + 1
40+
else 0
41+
#align nat.log Nat.log
42+
43+
@[simp]
44+
theorem log_eq_zero_iff {b n : ℕ} : log b n = 0 ↔ n < b ∨ b ≤ 1 := by
45+
rw [log, dite_eq_right_iff]
46+
simp only [Nat.succ_ne_zero, imp_false, not_and_or, not_le, not_lt]
47+
#align nat.log_eq_zero_iff Nat.log_eq_zero_iff
48+
49+
theorem log_of_lt {b n : ℕ} (hb : n < b) : log b n = 0 :=
50+
log_eq_zero_iff.2 (Or.inl hb)
51+
#align nat.log_of_lt Nat.log_of_lt
52+
53+
theorem log_of_left_le_one {b : ℕ} (hb : b ≤ 1) (n) : log b n = 0 :=
54+
log_eq_zero_iff.2 (Or.inr hb)
55+
#align nat.log_of_left_le_one Nat.log_of_left_le_one
56+
57+
@[simp]
58+
theorem log_pos_iff {b n : ℕ} : 0 < log b n ↔ b ≤ n ∧ 1 < b := by
59+
rw [pos_iff_ne_zero, Ne.def, log_eq_zero_iff, not_or, not_lt, not_le]
60+
#align nat.log_pos_iff Nat.log_pos_iff
61+
62+
theorem log_pos {b n : ℕ} (hb : 1 < b) (hbn : b ≤ n) : 0 < log b n :=
63+
log_pos_iff.2 ⟨hbn, hb⟩
64+
#align nat.log_pos Nat.log_pos
65+
66+
theorem log_of_one_lt_of_le {b n : ℕ} (h : 1 < b) (hn : b ≤ n) : log b n = log b (n / b) + 1 := by
67+
rw [log]
68+
exact if_pos ⟨hn, h⟩
69+
#align nat.log_of_one_lt_of_le Nat.log_of_one_lt_of_le
70+
71+
@[simp]
72+
theorem log_zero_left : ∀ n, log 0 n = 0 :=
73+
log_of_left_le_one zero_le_one
74+
#align nat.log_zero_left Nat.log_zero_left
75+
76+
@[simp]
77+
theorem log_zero_right (b : ℕ) : log b 0 = 0 :=
78+
log_eq_zero_iff.2 (le_total 1 b)
79+
#align nat.log_zero_right Nat.log_zero_right
80+
81+
@[simp]
82+
theorem log_one_left : ∀ n, log 1 n = 0 :=
83+
log_of_left_le_one le_rfl
84+
#align nat.log_one_left Nat.log_one_left
85+
86+
@[simp]
87+
theorem log_one_right (b : ℕ) : log b 1 = 0 :=
88+
log_eq_zero_iff.2 (lt_or_le _ _)
89+
#align nat.log_one_right Nat.log_one_right
90+
91+
/-- `pow b` and `log b` (almost) form a Galois connection. See also `Nat.pow_le_of_le_log` and
92+
`Nat.le_log_of_pow_le` for individual implications under weaker assumptions. -/
93+
theorem pow_le_iff_le_log {b : ℕ} (hb : 1 < b) {x y : ℕ} (hy : y ≠ 0) : b ^ x ≤ y ↔ x ≤ log b y :=
94+
by
95+
induction' y using Nat.strong_induction_on with y ih generalizing x
96+
cases x with
97+
| zero => exact iff_of_true hy.bot_lt (zero_le _)
98+
| succ x =>
99+
rw [log]; split_ifs with h
100+
· have b_pos : 0 < b := zero_le_one.trans_lt hb
101+
rw [succ_eq_add_one, add_le_add_iff_right, ←
102+
ih (y / b) (div_lt_self hy.bot_lt hb) (Nat.div_pos h.1 b_pos).ne', le_div_iff_mul_le b_pos,
103+
pow_succ', mul_comm]
104+
· exact iff_of_false (fun hby => h ⟨(le_self_pow hb.le x.succ_ne_zero).trans hby, hb⟩)
105+
(not_succ_le_zero _)
106+
#align nat.pow_le_iff_le_log Nat.pow_le_iff_le_log
107+
108+
theorem lt_pow_iff_log_lt {b : ℕ} (hb : 1 < b) {x y : ℕ} (hy : y ≠ 0) : y < b ^ x ↔ log b y < x :=
109+
lt_iff_lt_of_le_iff_le (pow_le_iff_le_log hb hy)
110+
#align nat.lt_pow_iff_log_lt Nat.lt_pow_iff_log_lt
111+
112+
theorem pow_le_of_le_log {b x y : ℕ} (hy : y ≠ 0) (h : x ≤ log b y) : b ^ x ≤ y := by
113+
refine' (le_or_lt b 1).elim (fun hb => _) fun hb => (pow_le_iff_le_log hb hy).2 h
114+
rw [log_of_left_le_one hb, nonpos_iff_eq_zero] at h
115+
rwa [h, pow_zero, one_le_iff_ne_zero]
116+
#align nat.pow_le_of_le_log Nat.pow_le_of_le_log
117+
118+
theorem le_log_of_pow_le {b x y : ℕ} (hb : 1 < b) (h : b ^ x ≤ y) : x ≤ log b y := by
119+
rcases ne_or_eq y 0 with (hy | rfl)
120+
exacts[(pow_le_iff_le_log hb hy).1 h, (h.not_lt (pow_pos (zero_lt_one.trans hb) _)).elim]
121+
#align nat.le_log_of_pow_le Nat.le_log_of_pow_le
122+
123+
theorem pow_log_le_self (b : ℕ) {x : ℕ} (hx : x ≠ 0) : b ^ log b x ≤ x :=
124+
pow_le_of_le_log hx le_rfl
125+
#align nat.pow_log_le_self Nat.pow_log_le_self
126+
127+
theorem log_lt_of_lt_pow {b x y : ℕ} (hy : y ≠ 0) : y < b ^ x → log b y < x :=
128+
lt_imp_lt_of_le_imp_le (pow_le_of_le_log hy)
129+
#align nat.log_lt_of_lt_pow Nat.log_lt_of_lt_pow
130+
131+
theorem lt_pow_of_log_lt {b x y : ℕ} (hb : 1 < b) : log b y < x → y < b ^ x :=
132+
lt_imp_lt_of_le_imp_le (le_log_of_pow_le hb)
133+
#align nat.lt_pow_of_log_lt Nat.lt_pow_of_log_lt
134+
135+
theorem lt_pow_succ_log_self {b : ℕ} (hb : 1 < b) (x : ℕ) : x < b ^ (log b x).succ :=
136+
lt_pow_of_log_lt hb (lt_succ_self _)
137+
#align nat.lt_pow_succ_log_self Nat.lt_pow_succ_log_self
138+
139+
theorem log_eq_iff {b m n : ℕ} (h : m ≠ 01 < b ∧ n ≠ 0) :
140+
log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1) := by
141+
rcases em (1 < b ∧ n ≠ 0) with (⟨hb, hn⟩ | hbn)
142+
· rw [le_antisymm_iff, ← lt_succ_iff, ← pow_le_iff_le_log, ← lt_pow_iff_log_lt, and_comm] <;>
143+
assumption
144+
· have hm : m ≠ 0 := h.resolve_right hbn
145+
rw [not_and_or, not_lt, Ne.def, not_not] at hbn
146+
rcases hbn with (hb | rfl)
147+
· simpa only [log_of_left_le_one hb, hm.symm, false_iff_iff, not_and, not_lt] using
148+
le_trans (pow_le_pow_of_le_one' hb m.le_succ)
149+
· simpa only [log_zero_right, hm.symm, nonpos_iff_eq_zero, false_iff, not_and, not_lt,
150+
add_pos_iff, or_true, pow_eq_zero_iff] using pow_eq_zero
151+
#align nat.log_eq_iff Nat.log_eq_iff
152+
153+
theorem log_eq_of_pow_le_of_lt_pow {b m n : ℕ} (h₁ : b ^ m ≤ n) (h₂ : n < b ^ (m + 1)) :
154+
log b n = m := by
155+
rcases eq_or_ne m 0 with (rfl | hm)
156+
· rw [pow_one] at h₂
157+
exact log_of_lt h₂
158+
· exact (log_eq_iff (Or.inl hm)).2 ⟨h₁, h₂⟩
159+
#align nat.log_eq_of_pow_le_of_lt_pow Nat.log_eq_of_pow_le_of_lt_pow
160+
161+
theorem log_pow {b : ℕ} (hb : 1 < b) (x : ℕ) : log b (b ^ x) = x :=
162+
log_eq_of_pow_le_of_lt_pow le_rfl (pow_lt_pow hb x.lt_succ_self)
163+
#align nat.log_pow Nat.log_pow
164+
165+
theorem log_eq_one_iff' {b n : ℕ} : log b n = 1 ↔ b ≤ n ∧ n < b * b := by
166+
rw [log_eq_iff (Or.inl one_ne_zero), pow_add, pow_one]
167+
#align nat.log_eq_one_iff' Nat.log_eq_one_iff'
168+
169+
theorem log_eq_one_iff {b n : ℕ} : log b n = 1 ↔ n < b * b ∧ 1 < b ∧ b ≤ n :=
170+
log_eq_one_iff'.trans
171+
fun h => ⟨h.2, lt_mul_self_iff.1 (h.1.trans_lt h.2), h.1⟩, fun h => ⟨h.2.2, h.1⟩⟩
172+
#align nat.log_eq_one_iff Nat.log_eq_one_iff
173+
174+
theorem log_mul_base {b n : ℕ} (hb : 1 < b) (hn : n ≠ 0) : log b (n * b) = log b n + 1 := by
175+
apply log_eq_of_pow_le_of_lt_pow <;> rw [pow_succ', mul_comm b]
176+
exacts [mul_le_mul_right' (pow_log_le_self _ hn) _,
177+
(mul_lt_mul_right (zero_lt_one.trans hb)).2 (lt_pow_succ_log_self hb _)]
178+
#align nat.log_mul_base Nat.log_mul_base
179+
180+
theorem pow_log_le_add_one (b : ℕ) : ∀ x, b ^ log b x ≤ x + 1
181+
| 0 => by rw [log_zero_right, pow_zero]
182+
| x + 1 => (pow_log_le_self b x.succ_ne_zero).trans (x + 1).le_succ
183+
#align nat.pow_log_le_add_one Nat.pow_log_le_add_one
184+
185+
theorem log_monotone {b : ℕ} : Monotone (log b) := by
186+
refine' monotone_nat_of_le_succ fun n => _
187+
cases' le_or_lt b 1 with hb hb
188+
· rw [log_of_left_le_one hb]
189+
exact zero_le _
190+
· exact le_log_of_pow_le hb (pow_log_le_add_one _ _)
191+
#align nat.log_monotone Nat.log_monotone
192+
193+
--@[mono] -- porting note: unknown attribute
194+
theorem log_mono_right {b n m : ℕ} (h : n ≤ m) : log b n ≤ log b m :=
195+
log_monotone h
196+
#align nat.log_mono_right Nat.log_mono_right
197+
198+
--@[mono]
199+
theorem log_anti_left {b c n : ℕ} (hc : 1 < c) (hb : c ≤ b) : log b n ≤ log c n := by
200+
rcases eq_or_ne n 0 with (rfl | hn); · rw [log_zero_right, log_zero_right]
201+
apply le_log_of_pow_le hc
202+
calc
203+
c ^ log b n ≤ b ^ log b n := pow_le_pow_of_le_left' hb _
204+
_ ≤ n := pow_log_le_self _ hn
205+
206+
#align nat.log_anti_left Nat.log_anti_left
207+
208+
theorem log_antitone_left {n : ℕ} : AntitoneOn (fun b => log b n) (Set.Ioi 1) := fun _ hc _ _ hb =>
209+
log_anti_left (Set.mem_Iio.1 hc) hb
210+
#align nat.log_antitone_left Nat.log_antitone_left
211+
212+
@[simp]
213+
theorem log_div_base (b n : ℕ) : log b (n / b) = log b n - 1 := by
214+
cases' le_or_lt b 1 with hb hb
215+
· rw [log_of_left_le_one hb, log_of_left_le_one hb, Nat.zero_sub]
216+
cases' lt_or_le n b with h h
217+
· rw [div_eq_of_lt h, log_of_lt h, log_zero_right]
218+
rw [log_of_one_lt_of_le hb h, add_tsub_cancel_right]
219+
#align nat.log_div_base Nat.log_div_base
220+
221+
@[simp]
222+
theorem log_div_mul_self (b n : ℕ) : log b (n / b * b) = log b n := by
223+
cases' le_or_lt b 1 with hb hb
224+
· rw [log_of_left_le_one hb, log_of_left_le_one hb]
225+
cases' lt_or_le n b with h h
226+
· rw [div_eq_of_lt h, zero_mul, log_zero_right, log_of_lt h]
227+
rw [log_mul_base hb (Nat.div_pos h (zero_le_one.trans_lt hb)).ne', log_div_base,
228+
tsub_add_cancel_of_le (succ_le_iff.2 <| log_pos hb h)]
229+
#align nat.log_div_mul_self Nat.log_div_mul_self
230+
231+
theorem add_pred_div_lt {b n : ℕ} (hb : 1 < b) (hn : 2 ≤ n) : (n + b - 1) / b < n := by
232+
rw [div_lt_iff_lt_mul (zero_lt_one.trans hb), ← succ_le_iff, ← pred_eq_sub_one,
233+
succ_pred_eq_of_pos (add_pos (zero_lt_one.trans hn) (zero_lt_one.trans hb))]
234+
exact add_le_mul hn hb
235+
#align nat.add_pred_div_lt Nat.add_pred_div_lt
236+
237+
/-! ### Ceil logarithm -/
238+
239+
240+
/-- `clog b n`, is the upper logarithm of natural number `n` in base `b`. It returns the smallest
241+
`k : ℕ` such that `n ≤ b^k`, so if `b^k = n`, it returns exactly `k`. -/
242+
--@[pp_nodot]
243+
def clog (b : ℕ) : ℕ → ℕ
244+
| n =>
245+
if h : 1 < b ∧ 1 < n then
246+
have : (n + b - 1) / b < n := add_pred_div_lt h.1 h.2
247+
clog b ((n + b - 1) / b) + 1
248+
else 0
249+
#align nat.clog Nat.clog
250+
251+
theorem clog_of_left_le_one {b : ℕ} (hb : b ≤ 1) (n : ℕ) : clog b n = 0 := by
252+
rw [clog, dif_neg fun h : 1 < b ∧ 1 < n => h.1.not_le hb]
253+
#align nat.clog_of_left_le_one Nat.clog_of_left_le_one
254+
255+
theorem clog_of_right_le_one {n : ℕ} (hn : n ≤ 1) (b : ℕ) : clog b n = 0 := by
256+
rw [clog, dif_neg fun h : 1 < b ∧ 1 < n => h.2.not_le hn]
257+
#align nat.clog_of_right_le_one Nat.clog_of_right_le_one
258+
259+
@[simp]
260+
theorem clog_zero_left (n : ℕ) : clog 0 n = 0 :=
261+
clog_of_left_le_one zero_le_one _
262+
#align nat.clog_zero_left Nat.clog_zero_left
263+
264+
@[simp]
265+
theorem clog_zero_right (b : ℕ) : clog b 0 = 0 :=
266+
clog_of_right_le_one zero_le_one _
267+
#align nat.clog_zero_right Nat.clog_zero_right
268+
269+
@[simp]
270+
theorem clog_one_left (n : ℕ) : clog 1 n = 0 :=
271+
clog_of_left_le_one le_rfl _
272+
#align nat.clog_one_left Nat.clog_one_left
273+
274+
@[simp]
275+
theorem clog_one_right (b : ℕ) : clog b 1 = 0 :=
276+
clog_of_right_le_one le_rfl _
277+
#align nat.clog_one_right Nat.clog_one_right
278+
279+
theorem clog_of_two_le {b n : ℕ} (hb : 1 < b) (hn : 2 ≤ n) :
280+
clog b n = clog b ((n + b - 1) / b) + 1 := by rw [clog, dif_pos (⟨hb, hn⟩ : 1 < b ∧ 1 < n)]
281+
#align nat.clog_of_two_le Nat.clog_of_two_le
282+
283+
theorem clog_pos {b n : ℕ} (hb : 1 < b) (hn : 2 ≤ n) : 0 < clog b n := by
284+
rw [clog_of_two_le hb hn]
285+
exact zero_lt_succ _
286+
#align nat.clog_pos Nat.clog_pos
287+
288+
theorem clog_eq_one {b n : ℕ} (hn : 2 ≤ n) (h : n ≤ b) : clog b n = 1 := by
289+
rw [clog_of_two_le (hn.trans h) hn, clog_of_right_le_one]
290+
have n_pos : 0 < n := (zero_lt_two' ℕ).trans_le hn
291+
rw [← lt_succ_iff, Nat.div_lt_iff_lt_mul (n_pos.trans_le h), ← succ_le_iff, ← pred_eq_sub_one,
292+
succ_pred_eq_of_pos (add_pos n_pos (n_pos.trans_le h)), succ_mul, one_mul]
293+
exact add_le_add_right h _
294+
#align nat.clog_eq_one Nat.clog_eq_one
295+
296+
/-- `clog b` and `pow b` form a Galois connection. -/
297+
theorem le_pow_iff_clog_le {b : ℕ} (hb : 1 < b) {x y : ℕ} : x ≤ b ^ y ↔ clog b x ≤ y := by
298+
induction' x using Nat.strong_induction_on with x ih generalizing y
299+
cases y
300+
· rw [pow_zero]
301+
refine' ⟨fun h => (clog_of_right_le_one h b).le, _⟩
302+
simp_rw [← not_lt]
303+
contrapose!
304+
exact clog_pos hb
305+
have b_pos : 0 < b := (zero_lt_one' ℕ).trans hb
306+
rw [clog]; split_ifs with h
307+
· rw [succ_eq_add_one, add_le_add_iff_right, ← ih ((x + b - 1) / b) (add_pred_div_lt hb h.2),
308+
Nat.div_le_iff_le_mul_add_pred b_pos, mul_comm b, ← pow_succ,
309+
add_tsub_assoc_of_le (Nat.succ_le_of_lt b_pos), add_le_add_iff_right]
310+
· exact iff_of_true ((not_lt.1 (not_and.1 h hb)).trans <| succ_le_of_lt <| pow_pos b_pos _)
311+
(zero_le _)
312+
#align nat.le_pow_iff_clog_le Nat.le_pow_iff_clog_le
313+
314+
theorem pow_lt_iff_lt_clog {b : ℕ} (hb : 1 < b) {x y : ℕ} : b ^ y < x ↔ y < clog b x :=
315+
lt_iff_lt_of_le_iff_le (le_pow_iff_clog_le hb)
316+
#align nat.pow_lt_iff_lt_clog Nat.pow_lt_iff_lt_clog
317+
318+
theorem clog_pow (b x : ℕ) (hb : 1 < b) : clog b (b ^ x) = x :=
319+
eq_of_forall_ge_iff fun z => by
320+
rw [← le_pow_iff_clog_le hb]
321+
exact (pow_right_strictMono hb).le_iff_le
322+
#align nat.clog_pow Nat.clog_pow
323+
324+
theorem pow_pred_clog_lt_self {b : ℕ} (hb : 1 < b) {x : ℕ} (hx : 1 < x) :
325+
b ^ (clog b x).pred < x := by
326+
rw [← not_le, le_pow_iff_clog_le hb, not_le]
327+
exact pred_lt (clog_pos hb hx).ne'
328+
#align nat.pow_pred_clog_lt_self Nat.pow_pred_clog_lt_self
329+
330+
theorem le_pow_clog {b : ℕ} (hb : 1 < b) (x : ℕ) : x ≤ b ^ clog b x :=
331+
(le_pow_iff_clog_le hb).2 le_rfl
332+
#align nat.le_pow_clog Nat.le_pow_clog
333+
334+
--@[mono]
335+
theorem clog_mono_right (b : ℕ) {n m : ℕ} (h : n ≤ m) : clog b n ≤ clog b m := by
336+
cases' le_or_lt b 1 with hb hb
337+
· rw [clog_of_left_le_one hb]
338+
exact zero_le _
339+
· rw [← le_pow_iff_clog_le hb]
340+
exact h.trans (le_pow_clog hb _)
341+
#align nat.clog_mono_right Nat.clog_mono_right
342+
343+
--@[mono]
344+
theorem clog_anti_left {b c n : ℕ} (hc : 1 < c) (hb : c ≤ b) : clog b n ≤ clog c n := by
345+
rw [← le_pow_iff_clog_le (lt_of_lt_of_le hc hb)]
346+
calc
347+
n ≤ c ^ clog c n := le_pow_clog hc _
348+
_ ≤ b ^ clog c n := pow_le_pow_of_le_left hb _
349+
350+
#align nat.clog_anti_left Nat.clog_anti_left
351+
352+
theorem clog_monotone (b : ℕ) : Monotone (clog b) := fun _ _ => clog_mono_right _
353+
#align nat.clog_monotone Nat.clog_monotone
354+
355+
theorem clog_antitone_left {n : ℕ} : AntitoneOn (fun b : ℕ => clog b n) (Set.Ioi 1) :=
356+
fun _ hc _ _ hb => clog_anti_left (Set.mem_Iio.1 hc) hb
357+
#align nat.clog_antitone_left Nat.clog_antitone_left
358+
359+
theorem log_le_clog (b n : ℕ) : log b n ≤ clog b n := by
360+
obtain hb | hb := le_or_lt b 1
361+
· rw [log_of_left_le_one hb]
362+
exact zero_le _
363+
cases n with
364+
| zero =>
365+
rw [log_zero_right]
366+
exact zero_le _
367+
| succ n =>
368+
exact (pow_right_strictMono hb).le_iff_le.1
369+
((pow_log_le_self b n.succ_ne_zero).trans <| le_pow_clog hb _)
370+
#align nat.log_le_clog Nat.log_le_clog
371+
372+
end Nat

0 commit comments

Comments
 (0)