1#[allow(unused_imports)]
15use super::super::prelude::*;
16
17verus! {
18
19#[cfg(verus_keep_ghost)]
20use super::power::{
21 pow,
22 lemma_pow0,
23 lemma_pow_positive,
24 lemma_pow_adds,
25 lemma_pow_strictly_increases,
26 lemma_pow_subtracts,
27};
28
29pub open spec fn pow2(e: nat) -> nat {
33 pow(2, e) as nat
34}
35
36#[verifier::opaque]
38pub open spec fn is_pow2(n: int) -> bool
39 decreases n,
40{
41 if n <= 0 {
42 false
43 } else if n == 1 {
44 true
45 } else {
46 n % 2 == 0 && is_pow2(n / 2)
47 }
48}
49
50pub open spec fn is_pow2_exists(n: int) -> bool {
53 exists|i: nat| pow(2, i) == n
54}
55
56pub broadcast proof fn is_pow2_equiv(n: int)
58 ensures
59 #![trigger is_pow2(n)]
60 #![trigger is_pow2_exists(n)]
61 is_pow2(n) <==> is_pow2_exists(n),
62{
63 if is_pow2(n) {
64 assert(is_pow2_exists(n)) by {
65 is_pow2_equiv_forward(n);
66 }
67 }
68 if is_pow2_exists(n) {
69 assert(is_pow2(n)) by {
70 broadcast use lemma_pow_positive;
71
72 is_pow2_equiv_reverse(n);
73 }
74 }
75}
76
77proof fn is_pow2_equiv_forward(n: int)
78 requires
79 is_pow2(n),
80 ensures
81 is_pow2_exists(n),
82 decreases n,
83{
84 reveal(is_pow2);
85 reveal(pow);
86
87 if n == 1 {
88 broadcast use lemma_pow0;
89
90 assert(pow(2, 0) == n);
91 } else {
92 is_pow2_equiv_forward(n / 2);
93 let exp = choose|i: nat| pow(2, i) == n / 2;
94 assert(pow(2, exp + 1) == 2 * pow(2, exp));
95 }
96}
97
98proof fn is_pow2_equiv_reverse(n: int)
99 requires
100 n > 0,
101 is_pow2_exists(n),
102 ensures
103 is_pow2(n),
104 decreases n,
105{
106 reveal(is_pow2);
107 reveal(pow);
108
109 let exp = choose|i: nat| pow(2, i) == n;
110
111 if exp == 0 {
112 broadcast use lemma_pow0;
113
114 } else {
115 assert(pow(2, (exp - 1) as nat) == n / 2);
116 is_pow2_equiv_reverse(n / 2);
117 }
118}
119
120pub broadcast proof fn lemma_pow2_pos(e: nat)
123 ensures
124 #[trigger] pow2(e) > 0,
125{
126 lemma_pow_positive(2, e);
127}
128
129pub broadcast proof fn lemma_pow2(e: nat)
131 ensures
132 #[trigger] pow2(e) == pow(2, e) as int,
133 decreases e,
134{
135 reveal(pow);
136 if e != 0 {
137 lemma_pow2((e - 1) as nat);
138 }
139}
140
141pub broadcast proof fn lemma_pow2_unfold(e: nat)
143 requires
144 e > 0,
145 ensures
146 #[trigger] pow2(e) == 2 * pow2((e - 1) as nat),
147{
148 reveal(pow);
149 lemma_pow2(e);
150 lemma_pow2((e - 1) as nat);
151}
152
153pub broadcast proof fn lemma_pow2_adds(e1: nat, e2: nat)
155 ensures
156 #[trigger] pow2(e1 + e2) == pow2(e1) * pow2(e2),
157{
158 lemma_pow2(e1);
159 lemma_pow2(e2);
160 lemma_pow2(e1 + e2);
161 lemma_pow_adds(2, e1, e2);
162}
163
164pub broadcast proof fn lemma_pow2_subtracts(e1: nat, e2: nat)
166 requires
167 e1 <= e2,
168 ensures
169 #[trigger] pow2((e2 - e1) as nat) == pow2(e2) / pow2(e1) > 0,
170{
171 lemma_pow2(e1);
172 lemma_pow2(e2);
173 lemma_pow2((e2 - e1) as nat);
174 lemma_pow_subtracts(2, e1, e2);
175}
176
177pub broadcast proof fn lemma_pow2_strictly_increases(e1: nat, e2: nat)
179 requires
180 e1 < e2,
181 ensures
182 #[trigger] pow2(e1) < #[trigger] pow2(e2),
183{
184 lemma_pow2(e1);
185 lemma_pow2(e2);
186 lemma_pow_strictly_increases(2, e1, e2);
187}
188
189pub proof fn lemma2_to64()
191 ensures
192 pow2(0) == 0x1,
193 pow2(1) == 0x2,
194 pow2(2) == 0x4,
195 pow2(3) == 0x8,
196 pow2(4) == 0x10,
197 pow2(5) == 0x20,
198 pow2(6) == 0x40,
199 pow2(7) == 0x80,
200 pow2(8) == 0x100,
201 pow2(9) == 0x200,
202 pow2(10) == 0x400,
203 pow2(11) == 0x800,
204 pow2(12) == 0x1000,
205 pow2(13) == 0x2000,
206 pow2(14) == 0x4000,
207 pow2(15) == 0x8000,
208 pow2(16) == 0x10000,
209 pow2(17) == 0x20000,
210 pow2(18) == 0x40000,
211 pow2(19) == 0x80000,
212 pow2(20) == 0x100000,
213 pow2(21) == 0x200000,
214 pow2(22) == 0x400000,
215 pow2(23) == 0x800000,
216 pow2(24) == 0x1000000,
217 pow2(25) == 0x2000000,
218 pow2(26) == 0x4000000,
219 pow2(27) == 0x8000000,
220 pow2(28) == 0x10000000,
221 pow2(29) == 0x20000000,
222 pow2(30) == 0x40000000,
223 pow2(31) == 0x80000000,
224 pow2(32) == 0x100000000,
225 pow2(64) == 0x10000000000000000,
226{
227 reveal(pow);
228 #[verusfmt::skip]
229 assert(
230 pow2(0) == 0x1 &&
231 pow2(1) == 0x2 &&
232 pow2(2) == 0x4 &&
233 pow2(3) == 0x8 &&
234 pow2(4) == 0x10 &&
235 pow2(5) == 0x20 &&
236 pow2(6) == 0x40 &&
237 pow2(7) == 0x80 &&
238 pow2(8) == 0x100 &&
239 pow2(9) == 0x200 &&
240 pow2(10) == 0x400 &&
241 pow2(11) == 0x800 &&
242 pow2(12) == 0x1000 &&
243 pow2(13) == 0x2000 &&
244 pow2(14) == 0x4000 &&
245 pow2(15) == 0x8000 &&
246 pow2(16) == 0x10000 &&
247 pow2(17) == 0x20000 &&
248 pow2(18) == 0x40000 &&
249 pow2(19) == 0x80000 &&
250 pow2(20) == 0x100000 &&
251 pow2(21) == 0x200000 &&
252 pow2(22) == 0x400000 &&
253 pow2(23) == 0x800000 &&
254 pow2(24) == 0x1000000 &&
255 pow2(25) == 0x2000000 &&
256 pow2(26) == 0x4000000 &&
257 pow2(27) == 0x8000000 &&
258 pow2(28) == 0x10000000 &&
259 pow2(29) == 0x20000000 &&
260 pow2(30) == 0x40000000 &&
261 pow2(31) == 0x80000000 &&
262 pow2(32) == 0x100000000 &&
263 pow2(64) == 0x10000000000000000
264 ) by(compute_only);
265}
266
267pub proof fn lemma2_to64_rest()
271 ensures
272 pow2(33) == 0x200000000,
273 pow2(34) == 0x400000000,
274 pow2(35) == 0x800000000,
275 pow2(36) == 0x1000000000,
276 pow2(37) == 0x2000000000,
277 pow2(38) == 0x4000000000,
278 pow2(39) == 0x8000000000,
279 pow2(40) == 0x10000000000,
280 pow2(41) == 0x20000000000,
281 pow2(42) == 0x40000000000,
282 pow2(43) == 0x80000000000,
283 pow2(44) == 0x100000000000,
284 pow2(45) == 0x200000000000,
285 pow2(46) == 0x400000000000,
286 pow2(47) == 0x800000000000,
287 pow2(48) == 0x1000000000000,
288 pow2(49) == 0x2000000000000,
289 pow2(50) == 0x4000000000000,
290 pow2(51) == 0x8000000000000,
291 pow2(52) == 0x10000000000000,
292 pow2(53) == 0x20000000000000,
293 pow2(54) == 0x40000000000000,
294 pow2(55) == 0x80000000000000,
295 pow2(56) == 0x100000000000000,
296 pow2(57) == 0x200000000000000,
297 pow2(58) == 0x400000000000000,
298 pow2(59) == 0x800000000000000,
299 pow2(60) == 0x1000000000000000,
300 pow2(61) == 0x2000000000000000,
301 pow2(62) == 0x4000000000000000,
302 pow2(63) == 0x8000000000000000,
303 pow2(64) == 0x10000000000000000,
304{
305 reveal(pow);
306 #[verusfmt::skip]
307 assert(
308 pow2(33) == 0x200000000 &&
309 pow2(34) == 0x400000000 &&
310 pow2(35) == 0x800000000 &&
311 pow2(36) == 0x1000000000 &&
312 pow2(37) == 0x2000000000 &&
313 pow2(38) == 0x4000000000 &&
314 pow2(39) == 0x8000000000 &&
315 pow2(40) == 0x10000000000 &&
316 pow2(41) == 0x20000000000 &&
317 pow2(42) == 0x40000000000 &&
318 pow2(43) == 0x80000000000 &&
319 pow2(44) == 0x100000000000 &&
320 pow2(45) == 0x200000000000 &&
321 pow2(46) == 0x400000000000 &&
322 pow2(47) == 0x800000000000 &&
323 pow2(48) == 0x1000000000000 &&
324 pow2(49) == 0x2000000000000 &&
325 pow2(50) == 0x4000000000000 &&
326 pow2(51) == 0x8000000000000 &&
327 pow2(52) == 0x10000000000000 &&
328 pow2(53) == 0x20000000000000 &&
329 pow2(54) == 0x40000000000000 &&
330 pow2(55) == 0x80000000000000 &&
331 pow2(56) == 0x100000000000000 &&
332 pow2(57) == 0x200000000000000 &&
333 pow2(58) == 0x400000000000000 &&
334 pow2(59) == 0x800000000000000 &&
335 pow2(60) == 0x1000000000000000 &&
336 pow2(61) == 0x2000000000000000 &&
337 pow2(62) == 0x4000000000000000 &&
338 pow2(63) == 0x8000000000000000 &&
339 pow2(64) == 0x10000000000000000
340 ) by(compute_only);
341}
342
343}