Skip to content

Commit 4375ff5

Browse files
committed
Squashed commit of the following:
commit c2e5939 Author: Yuyang Zhao 赵雨扬 <[email protected]> Date: Mon Apr 7 19:04:43 2025 +0800 Update BinaryRec.lean commit a54cb48 Merge: 45680ee 978f30b Author: Yuyang Zhao 赵雨扬 <[email protected]> Date: Mon Apr 7 19:02:15 2025 +0800 Merge remote-tracking branch 'upstream/main' into binaryRec commit 45680ee Author: Yuyang Zhao 赵雨扬 <[email protected]> Date: Mon Apr 7 19:00:30 2025 +0800 Revert "Merge branch 'main' into binaryRec" This reverts commit 2469752, reversing changes made to 0d1047b. commit 2469752 Merge: 0d1047b 1a4afaf Author: Yuyang Zhao 赵雨扬 <[email protected]> Date: Mon Apr 7 18:59:45 2025 +0800 Merge branch 'main' into binaryRec commit 0d1047b Author: Yuyang Zhao 赵雨扬 <[email protected]> Date: Wed Apr 2 19:59:16 2025 +0800 Update BinaryRec.lean commit 0c1b7da Author: FR-vdash-bot <[email protected]> Date: Mon Dec 2 03:25:00 2024 +0800 Update BinaryRec.lean commit c78364c Merge: c50c429 f46c044 Author: FR-vdash-bot <[email protected]> Date: Mon Dec 2 03:24:40 2024 +0800 Merge branch 'main' into binaryRec commit c50c429 Author: negiizhao <[email protected]> Date: Sun Jun 9 08:58:48 2024 +0800 Squashed commit of the following: commit 1a4afaf Author: negiizhao <[email protected]> Date: Sat Dec 3 12:38:15 2022 +0800 fix names of theorems commit 96818f2 Author: negiizhao <[email protected]> Date: Sat Dec 3 10:26:36 2022 +0800 change the naming commit a2742a9 Author: negiizhao <[email protected]> Date: Sat Dec 3 10:09:57 2022 +0800 forgot to edit copyright info commit 1ee4d5f Author: negiizhao <[email protected]> Date: Fri Dec 2 14:18:08 2022 +0800 Update Std.lean commit 758d2fd Author: negiizhao <[email protected]> Date: Fri Dec 2 14:14:19 2022 +0800 golf commit a164def Merge: bae939f e58f162 Author: negiizhao <[email protected]> Date: Fri Dec 2 13:20:28 2022 +0800 Merge branch 'main' of https://github.com/negiizhao/std4 commit bae939f Author: negiizhao <[email protected]> Date: Fri Dec 2 13:18:12 2022 +0800 feat: pairing heaps
1 parent 978f30b commit 4375ff5

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

Batteries/Data/Nat.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Batteries.Data.Nat.Basic
2+
import Batteries.Data.Nat.BinaryRec
23
import Batteries.Data.Nat.Bisect
34
import Batteries.Data.Nat.Gcd
45
import Batteries.Data.Nat.Lemmas

Batteries/Data/Nat/BinaryRec.lean

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/-
2+
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Mario Carneiro, Praneeth Kolichala, Yuyang Zhao
5+
-/
6+
7+
/-!
8+
# Binary recursion on `Nat`
9+
10+
This file defines binary recursion on `Nat`.
11+
12+
## Main results
13+
* `Nat.binaryRec`: A recursion principle for `bit` representations of natural numbers.
14+
* `Nat.binaryRec'`: The same as `binaryRec`, but the induction step can assume that if `n=0`,
15+
the bit being appended is `true`.
16+
* `Nat.binaryRecFromOne`: The same as `binaryRec`, but special casing both 0 and 1 as base cases.
17+
-/
18+
19+
universe u
20+
21+
namespace Nat
22+
23+
/-- `bit b` appends the digit `b` to the little end of the binary representation of
24+
its natural number input. -/
25+
def bit (b : Bool) (n : Nat) : Nat :=
26+
cond b (2 * n + 1) (2 * n)
27+
28+
theorem shiftRight_one (n) : n >>> 1 = n / 2 := rfl
29+
30+
@[simp]
31+
theorem bit_decide_mod_two_eq_one_shiftRight_one (n : Nat) : bit (n % 2 = 1) (n >>> 1) = n := by
32+
simp only [bit, shiftRight_one]
33+
cases mod_two_eq_zero_or_one n with | _ h => simpa [h] using Nat.div_add_mod n 2
34+
35+
theorem bit_testBit_zero_shiftRight_one (n : Nat) : bit (n.testBit 0) (n >>> 1) = n := by
36+
simp
37+
38+
@[simp]
39+
theorem bit_eq_zero_iff {n : Nat} {b : Bool} : bit b n = 0 ↔ n = 0 ∧ b = false := by
40+
cases n <;> cases b <;> simp [bit, Nat.shiftLeft_succ, Nat.two_mul, ← Nat.add_assoc]
41+
42+
/-- For a predicate `motive : Nat → Sort u`, if instances can be
43+
constructed for natural numbers of the form `bit b n`,
44+
they can be constructed for any given natural number. -/
45+
@[inline]
46+
def bitCasesOn {motive : Nat → Sort u} (n) (h : ∀ b n, motive (bit b n)) : motive n :=
47+
-- `1 &&& n != 0` is faster than `n.testBit 0`. This may change when we have faster `testBit`.
48+
let x := h (1 &&& n != 0) (n >>> 1)
49+
-- `congrArg motive _ ▸ x` is defeq to `x` in non-dependent case
50+
congrArg motive n.bit_testBit_zero_shiftRight_one ▸ x
51+
52+
/-- A recursion principle for `bit` representations of natural numbers.
53+
For a predicate `motive : Nat → Sort u`, if instances can be
54+
constructed for natural numbers of the form `bit b n`,
55+
they can be constructed for all natural numbers. -/
56+
@[elab_as_elim, specialize]
57+
def binaryRec {motive : Nat → Sort u} (z : motive 0) (f : ∀ b n, motive n → motive (bit b n))
58+
(n : Nat) : motive n :=
59+
if n0 : n = 0 then congrArg motive n0 ▸ z
60+
else
61+
let x := f (1 &&& n != 0) (n >>> 1) (binaryRec z f (n >>> 1))
62+
congrArg motive n.bit_testBit_zero_shiftRight_one ▸ x
63+
decreasing_by exact bitwise_rec_lemma n0
64+
65+
/-- The same as `binaryRec`, but the induction step can assume that if `n=0`,
66+
the bit being appended is `true` -/
67+
@[elab_as_elim, specialize]
68+
def binaryRec' {motive : Nat → Sort u} (z : motive 0)
69+
(f : ∀ b n, (n = 0 → b = true) → motive n → motive (bit b n)) :
70+
∀ n, motive n :=
71+
binaryRec z fun b n ih =>
72+
if h : n = 0 → b = true then f b n h ih
73+
else
74+
have : bit b n = 0 := by
75+
rw [bit_eq_zero_iff]
76+
cases n <;> cases b <;> simp at h ⊢
77+
congrArg motive this ▸ z
78+
79+
/-- The same as `binaryRec`, but special casing both 0 and 1 as base cases -/
80+
@[elab_as_elim, specialize]
81+
def binaryRecFromOne {motive : Nat → Sort u} (z₀ : motive 0) (z₁ : motive 1)
82+
(f : ∀ b n, n ≠ 0 → motive n → motive (bit b n)) :
83+
∀ n, motive n :=
84+
binaryRec' z₀ fun b n h ih =>
85+
if h' : n = 0 then
86+
have : bit b n = bit true 0 := by
87+
rw [h', h h']
88+
congrArg motive this ▸ z₁
89+
else f b n h' ih
90+
91+
theorem bit_val (b n) : bit b n = 2 * n + b.toNat := by
92+
cases b <;> rfl
93+
94+
@[simp]
95+
theorem bit_div_two (b n) : bit b n / 2 = n := by
96+
rw [bit_val, Nat.add_comm, add_mul_div_left, div_eq_of_lt, Nat.zero_add]
97+
· cases b <;> decide
98+
· decide
99+
100+
@[simp]
101+
theorem bit_mod_two (b n) : bit b n % 2 = b.toNat := by
102+
cases b <;> simp [bit_val, mul_add_mod]
103+
104+
@[simp]
105+
theorem bit_shiftRight_one (b n) : bit b n >>> 1 = n :=
106+
bit_div_two b n
107+
108+
theorem testBit_bit_zero (b n) : (bit b n).testBit 0 = b := by
109+
simp
110+
111+
variable {motive : Nat → Sort u}
112+
113+
@[simp]
114+
theorem bitCasesOn_bit (h : ∀ b n, motive (bit b n)) (b : Bool) (n : Nat) :
115+
bitCasesOn (bit b n) h = h b n := by
116+
change congrArg motive (bit b n).bit_testBit_zero_shiftRight_one ▸ h _ _ = h b n
117+
generalize congrArg motive (bit b n).bit_testBit_zero_shiftRight_one = e; revert e
118+
rw [testBit_bit_zero, bit_shiftRight_one]
119+
intros; rfl
120+
121+
@[simp]
122+
theorem binaryRec_zero (z : motive 0) (f : ∀ b n, motive n → motive (bit b n)) :
123+
binaryRec z f 0 = z := by
124+
rw [binaryRec]
125+
simp
126+
127+
@[simp]
128+
theorem binaryRec_one (z : motive 0) (f : ∀ b n, motive n → motive (bit b n)) :
129+
binaryRec (motive := motive) z f 1 = f true 0 z := by
130+
rw [binaryRec]
131+
simp only [add_one_ne_zero, ↓reduceDIte, Nat.reduceShiftRight, binaryRec_zero]
132+
rfl
133+
134+
theorem binaryRec_eq {z : motive 0} {f : ∀ b n, motive n → motive (bit b n)}
135+
(b n) (h : f false 0 z = z ∨ (n = 0 → b = true)) :
136+
binaryRec z f (bit b n) = f b n (binaryRec z f n) := by
137+
by_cases h' : bit b n = 0
138+
case pos =>
139+
obtain ⟨rfl, rfl⟩ := bit_eq_zero_iff.mp h'
140+
simp only [Bool.false_eq_true, imp_false, not_true_eq_false, or_false] at h
141+
unfold binaryRec
142+
exact h.symm
143+
case neg =>
144+
rw [binaryRec, dif_neg h']
145+
change congrArg motive (bit b n).bit_testBit_zero_shiftRight_one ▸ f _ _ _ = _
146+
generalize congrArg motive (bit b n).bit_testBit_zero_shiftRight_one = e; revert e
147+
rw [testBit_bit_zero, bit_shiftRight_one]
148+
intros; rfl
149+
150+
end Nat

0 commit comments

Comments
 (0)