|
| 1 | +/- |
| 2 | +Copyright (c) 2022 Praneeth Kolichala. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Praneeth Kolichala |
| 5 | +-/ |
| 6 | +import tactic.generalize_proofs |
| 7 | +import tactic.norm_num |
| 8 | + |
| 9 | +/-! |
| 10 | +# Additional properties of binary recursion on `nat` |
| 11 | +
|
| 12 | +This file documents additional properties of binary recursion, |
| 13 | +which allows us to more easily work with operations which do depend |
| 14 | +on the number of leading zeros in the binary representation of `n`. |
| 15 | +For example, we can more easily work with `nat.bits` and `nat.size`. |
| 16 | +
|
| 17 | +See also: `nat.bitwise`, `nat.pow` (for various lemmas about `size` and `shiftl`/`shiftr`), |
| 18 | +and `nat.digits`. |
| 19 | +-/ |
| 20 | + |
| 21 | +namespace nat |
| 22 | + |
| 23 | +lemma bit_eq_zero_iff {n : ℕ} {b : bool} : bit b n = 0 ↔ n = 0 ∧ b = ff := |
| 24 | +by { split, { cases b; simp [nat.bit], }, rintro ⟨rfl, rfl⟩, refl, } |
| 25 | + |
| 26 | +/-- The same as binary_rec_eq, but that one unfortunately requires `f` to be the identity when |
| 27 | + appending `ff` to `0`. Here, we allow you to explicitly say that that case is not happening, i.e. |
| 28 | + supplying `n = 0 → b = tt`. -/ |
| 29 | +lemma binary_rec_eq' {C : ℕ → Sort*} {z : C 0} {f : ∀ b n, C n → C (bit b n)} |
| 30 | + (b n) (h : f ff 0 z = z ∨ (n = 0 → b = tt)) : |
| 31 | + binary_rec z f (bit b n) = f b n (binary_rec z f n) := |
| 32 | +begin |
| 33 | + rw [binary_rec], |
| 34 | + split_ifs with h', |
| 35 | + { rcases bit_eq_zero_iff.mp h' with ⟨rfl, rfl⟩, |
| 36 | + rw binary_rec_zero, |
| 37 | + simp only [imp_false, or_false, eq_self_iff_true, not_true] at h, |
| 38 | + exact h.symm }, |
| 39 | + { generalize_proofs e, revert e, |
| 40 | + rw [bodd_bit, div2_bit], |
| 41 | + intros, refl, } |
| 42 | +end |
| 43 | + |
| 44 | +/-- The same as `binary_rec`, but the induction step can assume that if `n=0`, |
| 45 | + the bit being appended is `tt`-/ |
| 46 | +@[elab_as_eliminator] |
| 47 | +def binary_rec' {C : ℕ → Sort*} (z : C 0) (f : ∀ b n, (n = 0 → b = tt) → C n → C (bit b n)) : |
| 48 | + ∀ n, C n := |
| 49 | +binary_rec z (λ b n ih, if h : n = 0 → b = tt then f b n h ih else |
| 50 | + by { convert z, rw bit_eq_zero_iff, simpa using h, }) |
| 51 | + |
| 52 | +/-- The same as `binary_rec`, but special casing both 0 and 1 as base cases -/ |
| 53 | +@[elab_as_eliminator] |
| 54 | +def binary_rec_from_one {C : ℕ → Sort*} (z₀ : C 0) (z₁ : C 1) |
| 55 | + (f : ∀ b n, n ≠ 0 → C n → C (bit b n)) : ∀ n, C n := |
| 56 | +binary_rec' z₀ (λ b n h ih, if h' : n = 0 then by { rw [h', h h'], exact z₁ } else f b n h' ih) |
| 57 | + |
| 58 | +@[simp] lemma zero_bits : bits 0 = [] := by simp [nat.bits] |
| 59 | + |
| 60 | +@[simp] lemma bits_append_bit (n : ℕ) (b : bool) (hn : n = 0 → b = tt) : |
| 61 | + (bit b n).bits = b :: n.bits := |
| 62 | +by { rw [nat.bits, binary_rec_eq'], simpa, } |
| 63 | + |
| 64 | +@[simp] lemma bit0_bits (n : ℕ) (hn : n ≠ 0) : (bit0 n).bits = ff :: n.bits := |
| 65 | +bits_append_bit n ff (λ hn', absurd hn' hn) |
| 66 | + |
| 67 | +@[simp] lemma bit1_bits (n : ℕ) : (bit1 n).bits = tt :: n.bits := |
| 68 | +bits_append_bit n tt (λ _, rfl) |
| 69 | + |
| 70 | +@[simp] lemma one_bits : nat.bits 1 = [tt] := by { convert bit1_bits 0, simp, } |
| 71 | + |
| 72 | +example : bits 3423 = [tt, tt, tt, tt, tt, ff, tt, ff, tt, ff, tt, tt] := by norm_num |
| 73 | + |
| 74 | +lemma bodd_eq_bits_head (n : ℕ) : n.bodd = n.bits.head := |
| 75 | +begin |
| 76 | + induction n using nat.binary_rec' with b n h ih, { simp, }, |
| 77 | + simp [bodd_bit, bits_append_bit _ _ h], |
| 78 | +end |
| 79 | + |
| 80 | +lemma div2_bits_eq_tail (n : ℕ) : n.div2.bits = n.bits.tail := |
| 81 | +begin |
| 82 | + induction n using nat.binary_rec' with b n h ih, { simp, }, |
| 83 | + simp [div2_bit, bits_append_bit _ _ h], |
| 84 | +end |
| 85 | + |
| 86 | +lemma size_eq_bits_len (n : ℕ) : n.bits.length = n.size := |
| 87 | +begin |
| 88 | + induction n using nat.binary_rec' with b n h ih, { simp, }, |
| 89 | + rw [size_bit, bits_append_bit _ _ h], |
| 90 | + { simp [ih], }, |
| 91 | + { simpa [bit_eq_zero_iff], } |
| 92 | +end |
| 93 | + |
| 94 | +end nat |
0 commit comments