|
| 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 ≠ 0 ∨ 1 < 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