lemmas.bend
bend-kit-lemmas@0.1.1.0 · 746 lines · 45 definitions
1
2import Base
3import bend-mathlib@0.7.4.0/nat.bend as MNat
4
5
6def pow2(n: Nat) -> Nat:
7 match n:
8 case 0n:
9 1n
10 case 1n+p:
11 Nat.double(pow2(p))
12
13
14def bit(x: Bool, t: Nat) -> Nat:
15 match x:
16 case False{}:
17 Nat.double(t)
18 case True{}:
19 1n+Nat.double(t)
20
21law to_nat_con:
22 for -p: Nat
23 for x: Bool
24 for -t: Word(p)
25 {bit(x, Word.to_nat(p, t)) == Word.to_nat(1n+p, WCon{x, t}) : Nat}
26
27def to_nat_con(p, x, t):
28 match x:
29 case False{}:
30 {==}
31 case True{}:
32 {==}
33
34law cmp_bit:
35 for a: Nat
36 for b: Nat
37 for x: Bool
38 for y: Bool
39 {Word.cmp.fin(x, y, Nat.cmp(a, b)) == Nat.cmp(bit(x, a), bit(y, b)) : Cmp}
40
41def cmp_bit(a, b, x, y):
42 match a b:
43 case 0n 0n:
44 match x y:
45 case False{} False{}:
46 {==}
47 case False{} True{}:
48 {==}
49 case True{} False{}:
50 {==}
51 case True{} True{}:
52 {==}
53 case 0n 1n+q:
54 match x y:
55 case False{} False{}:
56 {==}
57 case False{} True{}:
58 {==}
59 case True{} False{}:
60 {==}
61 case True{} True{}:
62 {==}
63 case 1n+p 0n:
64 match x y:
65 case False{} False{}:
66 {==}
67 case False{} True{}:
68 {==}
69 case True{} False{}:
70 {==}
71 case True{} True{}:
72 {==}
73 case 1n+p 1n+q:
74 match x y:
75 case False{} False{}:
76 cmp_bit(p, q, False{}, False{})
77 case False{} True{}:
78 cmp_bit(p, q, False{}, True{})
79 case True{} False{}:
80 cmp_bit(p, q, True{}, False{})
81 case True{} True{}:
82 cmp_bit(p, q, True{}, True{})
83
84
85law word_cmp_nat:
86 for n: Nat
87 for a: Word(n)
88 for b: Word(n)
89 {Word.cmp(n, a, b) == Nat.cmp(Word.to_nat(n, a), Word.to_nat(n, b)) : Cmp}
90
91def word_cmp_nat(n, a, b):
92 match n:
93 case 0n:
94 {==}
95 case 1n+ +p:
96 match a b:
97 case WCon{+x, +at} WCon{+y, +bt}:
98 %to_nat_con(p, x, at) : {Word.cmp.fin(x, y, Word.cmp(p, at, bt)) ==
99 Nat.cmp(_, Word.to_nat(1n+p, WCon{y, bt})) : Cmp}
100 %to_nat_con(p, y, bt) : {Word.cmp.fin(x, y, Word.cmp(p, at, bt)) ==
101 Nat.cmp(bit(x, Word.to_nat(p, at)), _) : Cmp}
102 %cmp_bit(Word.to_nat(p, at), Word.to_nat(p, bt), x, y) :
103 {Word.cmp.fin(x, y, Word.cmp(p, at, bt)) == _ : Cmp}
104 %word_cmp_nat(p, at, bt) : {Word.cmp.fin(x, y, Word.cmp(p, at, bt)) ==
105 Word.cmp.fin(x, y, _) : Cmp}
106 {==}
107
108law u32_cmp_nat:
109 for a: U32
110 for b: U32
111 {U32.cmp(a, b) == Nat.cmp(U32.to_nat(a), U32.to_nat(b)) : Cmp}
112
113def u32_cmp_nat(a, b):
114 match a b:
115 case U32{x} U32{y}:
116 word_cmp_nat(32n, x, y)
117
118law u32_is_lt_nat:
119 for a: U32
120 for b: U32
121 {U32.is_lt(a, b) == Nat.is_lt(U32.to_nat(a), U32.to_nat(b)) : Bool}
122
123def u32_is_lt_nat(a, b):
124 Equal.cong(Cmp, Bool, c => Cmp.is_lt(c), U32.cmp(a, b),
125 Nat.cmp(U32.to_nat(a), U32.to_nat(b)), u32_cmp_nat(a, b))
126
127law u32_is_le_nat:
128 for a: U32
129 for b: U32
130 {U32.is_le(a, b) == Nat.is_le(U32.to_nat(a), U32.to_nat(b)) : Bool}
131
132def u32_is_le_nat(a, b):
133 Equal.cong(Cmp, Bool, c => Cmp.is_le(c), U32.cmp(a, b),
134 Nat.cmp(U32.to_nat(a), U32.to_nat(b)), u32_cmp_nat(a, b))
135
136law u32_is_eq_nat:
137 for a: U32
138 for b: U32
139 {U32.is_eq(a, b) == Nat.is_eq(U32.to_nat(a), U32.to_nat(b)) : Bool}
140
141def u32_is_eq_nat(a, b):
142 Equal.cong(Cmp, Bool, c => Cmp.is_eq(c), U32.cmp(a, b),
143 Nat.cmp(U32.to_nat(a), U32.to_nat(b)), u32_cmp_nat(a, b))
144
145law odd_lt_double:
146 for a: Nat
147 for b: Nat
148 for h: MNat.lt(a, b)
149 MNat.lt(1n+Nat.double(a), Nat.double(b))
150
151def odd_lt_double(a, b, h):
152 match a b:
153 case 0n 0n:
154 Empty.absurd(MNat.lt(1n, 0n), MNat.lt_zero(0n)(h))
155 case 0n 1n+q:
156 {==}
157 case 1n+p 0n:
158 Empty.absurd(MNat.lt(1n+Nat.double(1n+p), 0n), MNat.lt_zero(1n+p)(h))
159 case 1n+p 1n+q:
160 odd_lt_double(p, q, h)
161
162
163law word_to_nat_lt:
164 for n: Nat
165 for w: Word(n)
166 MNat.lt(Word.to_nat(n, w), pow2(n))
167
168def word_to_nat_lt(n, w):
169 match n:
170 case 0n:
171 {==}
172 case 1n+ +p:
173 match w:
174 case WCon{False{}, +t}:
175 MNat.double_lt_double(Word.to_nat(p, t), pow2(p), word_to_nat_lt(p, t))
176 case WCon{True{}, +t}:
177 odd_lt_double(Word.to_nat(p, t), pow2(p), word_to_nat_lt(p, t))
178
179law u32_to_nat_word:
180 for -x: Word(32n)
181 {Word.to_nat(32n, x) == U32.to_nat(U32{x}) : Nat}
182
183def u32_to_nat_word(x):
184 {==}
185
186law u32_to_nat_lt:
187 for a: U32
188 MNat.lt(U32.to_nat(a), pow2(32n))
189
190def u32_to_nat_lt(a):
191 match a:
192 case U32{+x}:
193
194 %u32_to_nat_word(x) : MNat.lt(_, pow2(32n))
195 word_to_nat_lt(32n, x)
196
197law double_inj:
198 for a: Nat
199 for b: Nat
200 for h: {Nat.double(a) == Nat.double(b) : Nat}
201 {a == b : Nat}
202
203def double_inj(a, b, h):
204 match a b:
205 case 0n 0n:
206 {==}
207 case 0n 1n+q:
208 Empty.absurd({0n == 1n+q : Nat}, MNat.zero_ne_succ(1n+Nat.double(q))(h))
209 case 1n+p 0n:
210 Empty.absurd({1n+p == 0n : Nat}, MNat.succ_ne_zero(1n+Nat.double(p))(h))
211 case 1n+p 1n+q:
212 Equal.cong(Nat, Nat, k => 1n+k, p, q,
213 double_inj(p, q, MNat.succ_inj(Nat.double(p), Nat.double(q),
214 MNat.succ_inj(1n+Nat.double(p), 1n+Nat.double(q), h))))
215
216law double_ne_odd:
217 for a: Nat
218 for b: Nat
219 for h: {Nat.double(a) == 1n+Nat.double(b) : Nat}
220 Empty
221
222def double_ne_odd(a, b, h):
223 match a b:
224 case 0n 0n:
225 MNat.zero_ne_succ(0n)(h)
226 case 0n 1n+q:
227 MNat.zero_ne_succ(2n+Nat.double(q))(h)
228 case 1n+p 0n:
229 MNat.succ_ne_zero(Nat.double(p))(MNat.succ_inj(1n+Nat.double(p), 0n, h))
230 case 1n+p 1n+q:
231 double_ne_odd(p, q, MNat.succ_inj(Nat.double(p), 1n+Nat.double(q),
232 MNat.succ_inj(1n+Nat.double(p), 2n+Nat.double(q), h)))
233
234
235law word_to_nat_inj:
236 for n: Nat
237 for a: Word(n)
238 for b: Word(n)
239 for h: {Word.to_nat(n, a) == Word.to_nat(n, b) : Nat}
240 {a == b : Word(n)}
241
242def word_to_nat_inj(n, a, b, h):
243 match n:
244 case 0n:
245 match a b:
246 case WNil{} WNil{}:
247 {==}
248 case 1n+ +p:
249 match a b:
250 case WCon{False{}, +at} WCon{False{}, +bt}:
251 Equal.cong(Word(p), Word(1n+p), t => WCon{False{}, t}, at, bt,
252 word_to_nat_inj(p, at, bt, double_inj(Word.to_nat(p, at), Word.to_nat(p, bt), h)))
253 case WCon{True{}, +at} WCon{True{}, +bt}:
254 Equal.cong(Word(p), Word(1n+p), t => WCon{True{}, t}, at, bt,
255 word_to_nat_inj(p, at, bt, double_inj(Word.to_nat(p, at), Word.to_nat(p, bt),
256 MNat.succ_inj(Nat.double(Word.to_nat(p, at)), Nat.double(Word.to_nat(p, bt)), h))))
257 case WCon{False{}, +at} WCon{True{}, +bt}:
258 Empty.absurd({WCon{False{}, at} == WCon{True{}, bt} : Word(1n+p)},
259 double_ne_odd(Word.to_nat(p, at), Word.to_nat(p, bt), h))
260 case WCon{True{}, +at} WCon{False{}, +bt}:
261 Empty.absurd({WCon{True{}, at} == WCon{False{}, bt} : Word(1n+p)},
262 double_ne_odd(Word.to_nat(p, bt), Word.to_nat(p, at),
263 Equal.sym(Nat, 1n+Nat.double(Word.to_nat(p, at)), Nat.double(Word.to_nat(p, bt)), h)))
264
265law u32_to_nat_inj:
266 for a: U32
267 for b: U32
268 for h: {U32.to_nat(a) == U32.to_nat(b) : Nat}
269 {a == b : U32}
270
271def u32_to_nat_inj(a, b, h):
272 match a b:
273 case U32{+x} U32{+y}:
274 Equal.cong(Word(32n), U32, w => U32{w}, x, y, word_to_nat_inj(32n, x, y, h))
275
276def b2n(b: Bool) -> Nat:
277 match b:
278 case False{}:
279 0n
280 case True{}:
281 1n
282
283
284def scale(q: Bool, m: Nat) -> Nat:
285 match q:
286 case False{}:
287 0n
288 case True{}:
289 m
290
291
292def maj(x: Bool, y: Bool, c: Bool) -> Bool:
293 match x y:
294 case False{} False{}:
295 False{}
296 case True{} True{}:
297 True{}
298 case False{} True{}:
299 c
300 case True{} False{}:
301 c
302
303
304def carry(n: Nat, a: Word(n), b: Word(n), c: Bool) -> Bool:
305 match n:
306 case 0n:
307 c
308 case 1n+p:
309 match a b:
310 case WCon{x, at} WCon{y, bt}:
311 carry(p, at, bt, maj(x, y, c))
312
313law scale_double:
314 for q: Bool
315 for -m: Nat
316 {Nat.double(scale(q, m)) == scale(q, Nat.double(m)) : Nat}
317
318def scale_double(q, m):
319 match q:
320 case False{}:
321 {==}
322 case True{}:
323 {==}
324
325
326law adc_step:
327 for +s: Nat
328 for +x: Nat
329 for +y: Nat
330 for +c: Nat
331 for +k: Nat
332 for +r: Nat
333 for +q: Bool
334 for +m: Nat
335 for +a: Nat
336 for +b: Nat
337 for ih: {Nat.add(r, scale(q, m)) == Nat.add(k, Nat.add(a, b)) : Nat}
338 for fa: {Nat.add(c, Nat.add(x, y)) == Nat.add(s, Nat.double(k)) : Nat}
339 {Nat.add(Nat.add(s, Nat.double(r)), scale(q, Nat.double(m))) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
340
341def adc_step(s, x, y, c, k, r, q, m, a, b, ih, fa):
342 %scale_double(q, m) : {Nat.add(Nat.add(s, Nat.double(r)), _) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
343 %MNat.add_assoc_sym(s, Nat.double(r), Nat.double(scale(q, m))) : {_ == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
344 %MNat.double_add(r, scale(q, m)) : {Nat.add(s, _) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
345 %Equal.sym(Nat, Nat.add(r, scale(q, m)), Nat.add(k, Nat.add(a, b)), ih) :
346 {Nat.add(s, Nat.double(_)) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
347 %MNat.double_add_sym(k, Nat.add(a, b)) : {Nat.add(s, _) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
348 %MNat.double_add_sym(a, b) : {Nat.add(s, Nat.add(Nat.double(k), _)) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
349 %MNat.add_assoc(s, Nat.double(k), Nat.add(Nat.double(a), Nat.double(b))) : {_ == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
350 %fa : {Nat.add(_, Nat.add(Nat.double(a), Nat.double(b))) == Nat.add(c, Nat.add(Nat.add(x, Nat.double(a)), Nat.add(y, Nat.double(b)))) : Nat}
351 %MNat.add_add_add_comm(x, y, Nat.double(a), Nat.double(b)) : {Nat.add(Nat.add(c, Nat.add(x, y)), Nat.add(Nat.double(a), Nat.double(b))) == Nat.add(c, _) : Nat}
352 %MNat.add_assoc(c, Nat.add(x, y), Nat.add(Nat.double(a), Nat.double(b))) : {Nat.add(Nat.add(c, Nat.add(x, y)), Nat.add(Nat.double(a), Nat.double(b))) == _ : Nat}
353 {==}
354
355
356law word_adc_nat:
357 for n: Nat
358 for a: Word(n)
359 for b: Word(n)
360 for c: Bool
361 {Nat.add(Word.to_nat(n, Word.adc(n, a, b, False{}, c)),
362 scale(carry(n, a, b, c), pow2(n))) ==
363 Nat.add(b2n(c), Nat.add(Word.to_nat(n, a), Word.to_nat(n, b))) : Nat}
364
365def word_adc_nat(n, a, b, c):
366 match n:
367 case 0n:
368 match c:
369 case False{}:
370 {==}
371 case True{}:
372 {==}
373 case 1n+ +p:
374 match a b c:
375 case WCon{False{}, +at} WCon{False{}, +bt} False{}:
376 adc_step(0n, 0n, 0n, 0n, 0n,
377 Word.to_nat(p, Word.adc(p, at, bt, False{}, False{})), carry(p, at, bt, False{}), pow2(p),
378 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, False{}), {==})
379 case WCon{False{}, +at} WCon{False{}, +bt} True{}:
380 adc_step(1n, 0n, 0n, 1n, 0n,
381 Word.to_nat(p, Word.adc(p, at, bt, False{}, False{})), carry(p, at, bt, False{}), pow2(p),
382 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, False{}), {==})
383 case WCon{False{}, +at} WCon{True{}, +bt} False{}:
384 adc_step(1n, 0n, 1n, 0n, 0n,
385 Word.to_nat(p, Word.adc(p, at, bt, False{}, False{})), carry(p, at, bt, False{}), pow2(p),
386 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, False{}), {==})
387 case WCon{False{}, +at} WCon{True{}, +bt} True{}:
388 adc_step(0n, 0n, 1n, 1n, 1n,
389 Word.to_nat(p, Word.adc(p, at, bt, False{}, True{})), carry(p, at, bt, True{}), pow2(p),
390 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, True{}), {==})
391 case WCon{True{}, +at} WCon{False{}, +bt} False{}:
392 adc_step(1n, 1n, 0n, 0n, 0n,
393 Word.to_nat(p, Word.adc(p, at, bt, False{}, False{})), carry(p, at, bt, False{}), pow2(p),
394 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, False{}), {==})
395 case WCon{True{}, +at} WCon{False{}, +bt} True{}:
396 adc_step(0n, 1n, 0n, 1n, 1n,
397 Word.to_nat(p, Word.adc(p, at, bt, False{}, True{})), carry(p, at, bt, True{}), pow2(p),
398 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, True{}), {==})
399 case WCon{True{}, +at} WCon{True{}, +bt} False{}:
400 adc_step(0n, 1n, 1n, 0n, 1n,
401 Word.to_nat(p, Word.adc(p, at, bt, False{}, True{})), carry(p, at, bt, True{}), pow2(p),
402 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, True{}), {==})
403 case WCon{True{}, +at} WCon{True{}, +bt} True{}:
404 adc_step(1n, 1n, 1n, 1n, 1n,
405 Word.to_nat(p, Word.adc(p, at, bt, False{}, True{})), carry(p, at, bt, True{}), pow2(p),
406 Word.to_nat(p, at), Word.to_nat(p, bt), word_adc_nat(p, at, bt, True{}), {==})
407
408
409law lt_rw:
410 for -a: Nat
411 for -b: Nat
412 for -c: Nat
413 for e: {a == b : Nat}
414 for h: MNat.lt(b, c)
415 MNat.lt(a, c)
416
417def lt_rw(a, b, c, e, h):
418 %Equal.sym(Nat, a, b, e) : MNat.lt(_, c)
419 h
420
421law add_no_carry:
422 for q: Bool
423 for +r: Nat
424 for +m: Nat
425 for +s: Nat
426 for e: {Nat.add(r, scale(q, m)) == s : Nat}
427 for h: MNat.lt(s, m)
428 {r == s : Nat}
429
430def add_no_carry(q, r, m, s, e, h):
431 match q:
432 case False{}:
433 Equal.trans(Nat, r, Nat.add(r, 0n), s, MNat.add_zero_sym(r), e)
434 case True{}:
435 Empty.absurd({r == s : Nat}, MNat.lt_irrefl(m)(MNat.lt_of_le_of_lt(m, Nat.add(r, m), m,
436 MNat.le_add_left(m, r), lt_rw(Nat.add(r, m), s, m, e, h))))
437
438law add_mod_carry:
439 for q: Bool
440 for +r: Nat
441 for +m: Nat
442 for +s: Nat
443 for e: {Nat.add(r, scale(q, m)) == s : Nat}
444 for h: MNat.lt(r, m)
445 {r == Nat.mod(s, m) : Nat}
446
447def add_mod_carry(q, r, m, s, e, h):
448 match q:
449 case False{}:
450 %e : {r == Nat.mod(_, m) : Nat}
451 %MNat.add_zero_sym(r) : {r == Nat.mod(_, m) : Nat}
452 Equal.sym(Nat, Nat.mod(r, m), r, MNat.mod_eq_of_lt(r, m, h))
453 case True{}:
454 %e : {r == Nat.mod(_, m) : Nat}
455 %MNat.add_comm(m, r) : {r == Nat.mod(_, m) : Nat}
456 %MNat.add_mod_left_sym(r, m) : {r == _ : Nat}
457 Equal.sym(Nat, Nat.mod(r, m), r, MNat.mod_eq_of_lt(r, m, h))
458
459
460law word_add_nat:
461 for +n: Nat
462 for +a: Word(n)
463 for +b: Word(n)
464 for h: MNat.lt(Nat.add(Word.to_nat(n, a), Word.to_nat(n, b)), pow2(n))
465 {Word.to_nat(n, Word.add(n, a, b)) == Nat.add(Word.to_nat(n, a), Word.to_nat(n, b)) : Nat}
466
467def word_add_nat(n, a, b, h):
468 add_no_carry(carry(n, a, b, False{}), Word.to_nat(n, Word.adc(n, a, b, False{}, False{})), pow2(n),
469 Nat.add(Word.to_nat(n, a), Word.to_nat(n, b)), word_adc_nat(n, a, b, False{}), h)
470
471
472law word_add_mod:
473 for +n: Nat
474 for +a: Word(n)
475 for +b: Word(n)
476 {Word.to_nat(n, Word.add(n, a, b)) ==
477 Nat.mod(Nat.add(Word.to_nat(n, a), Word.to_nat(n, b)), pow2(n)) : Nat}
478
479def word_add_mod(n, a, b):
480 add_mod_carry(carry(n, a, b, False{}), Word.to_nat(n, Word.adc(n, a, b, False{}, False{})), pow2(n),
481 Nat.add(Word.to_nat(n, a), Word.to_nat(n, b)), word_adc_nat(n, a, b, False{}),
482 word_to_nat_lt(n, Word.adc(n, a, b, False{}, False{})))
483
484law u32_add_word:
485 for -x: Word(32n)
486 for -y: Word(32n)
487 {Word.to_nat(32n, Word.add(32n, x, y)) == U32.to_nat(U32.add(U32{x}, U32{y})) : Nat}
488
489def u32_add_word(x, y):
490 {==}
491
492law u32_add_nat:
493 for a: U32
494 for b: U32
495 for h: MNat.lt(Nat.add(U32.to_nat(a), U32.to_nat(b)), pow2(32n))
496 {U32.to_nat(U32.add(a, b)) == Nat.add(U32.to_nat(a), U32.to_nat(b)) : Nat}
497
498def u32_add_nat(a, b, h):
499 match a b:
500 case U32{+x} U32{+y}:
501 word_add_nat(32n, x, y, lt_rw(Nat.add(Word.to_nat(32n, x), Word.to_nat(32n, y)),
502 Nat.add(U32.to_nat(U32{x}), U32.to_nat(U32{y})), pow2(32n), {==}, h))
503
504law u32_add_mod:
505 for a: U32
506 for b: U32
507 {U32.to_nat(U32.add(a, b)) == Nat.mod(Nat.add(U32.to_nat(a), U32.to_nat(b)), pow2(32n)) : Nat}
508
509def u32_add_mod(a, b):
510 match a b:
511 case U32{+x} U32{+y}:
512 %u32_add_word(x, y) :
513 {_ == Nat.mod(Nat.add(U32.to_nat(U32{x}), U32.to_nat(U32{y})), pow2(32n)) : Nat}
514 %u32_to_nat_word(x) : {Word.to_nat(32n, Word.add(32n, x, y)) ==
515 Nat.mod(Nat.add(_, U32.to_nat(U32{y})), pow2(32n)) : Nat}
516 %u32_to_nat_word(y) : {Word.to_nat(32n, Word.add(32n, x, y)) ==
517 Nat.mod(Nat.add(Word.to_nat(32n, x), _), pow2(32n)) : Nat}
518 word_add_mod(32n, x, y)
519
520
521law word_not_nat:
522 for n: Nat
523 for w: Word(n)
524 {1n+Nat.add(Word.to_nat(n, Word.not(n, w)), Word.to_nat(n, w)) == pow2(n) : Nat}
525
526def word_not_nat(n, w):
527 match n:
528 case 0n:
529 {==}
530 case 1n+ +p:
531 match w:
532 case WCon{False{}, +t}:
533 %word_not_nat(p, t) : {2n+Nat.add(Nat.double(Word.to_nat(p, Word.not(p, t))), Nat.double(Word.to_nat(p, t))) == Nat.double(_) : Nat}
534 %MNat.double_add_sym(Word.to_nat(p, Word.not(p, t)), Word.to_nat(p, t)) : {2n+Nat.add(Nat.double(Word.to_nat(p, Word.not(p, t))), Nat.double(Word.to_nat(p, t))) == 2n+_ : Nat}
535 {==}
536 case WCon{True{}, +t}:
537 %MNat.add_succ_sym(Nat.double(Word.to_nat(p, Word.not(p, t))), Nat.double(Word.to_nat(p, t))) : {1n+_ == pow2(1n+p) : Nat}
538 %word_not_nat(p, t) : {2n+Nat.add(Nat.double(Word.to_nat(p, Word.not(p, t))), Nat.double(Word.to_nat(p, t))) == Nat.double(_) : Nat}
539 %MNat.double_add_sym(Word.to_nat(p, Word.not(p, t)), Word.to_nat(p, t)) : {2n+Nat.add(Nat.double(Word.to_nat(p, Word.not(p, t))), Nat.double(Word.to_nat(p, t))) == 2n+_ : Nat}
540 {==}
541
542
543law word_sub_not:
544 for n: Nat
545 for a: Word(n)
546 for b: Word(n)
547 for +c: Bool
548 {Word.adc(n, a, b, True{}, c) == Word.adc(n, a, Word.not(n, b), False{}, c) : Word(n)}
549
550def word_sub_not(n, a, b, c):
551 match n:
552 case 0n:
553 {==}
554 case 1n+ +p:
555 match a b:
556 case WCon{False{}, +at} WCon{+y, +bt}:
557 Equal.cong(Word(p), Word(1n+p), w => WCon{Bool.xor(Bool.not(y), c), w},
558 Word.adc(p, at, bt, True{}, Bool.and(Bool.not(y), c)),
559 Word.adc(p, at, Word.not(p, bt), False{}, Bool.and(Bool.not(y), c)),
560 word_sub_not(p, at, bt, Bool.and(Bool.not(y), c)))
561 case WCon{True{}, +at} WCon{+y, +bt}:
562 Equal.cong(Word(p), Word(1n+p), w => WCon{Bool.not(Bool.xor(Bool.not(y), c)), w},
563 Word.adc(p, at, bt, True{}, Bool.or(Bool.not(y), c)),
564 Word.adc(p, at, Word.not(p, bt), False{}, Bool.or(Bool.not(y), c)),
565 word_sub_not(p, at, bt, Bool.or(Bool.not(y), c)))
566
567law sub_arith:
568 for +a: Nat
569 for +b: Nat
570 for +nb: Nat
571 for +m: Nat
572 for h: MNat.le(b, a)
573 for hn: {1n+Nat.add(nb, b) == m : Nat}
574 {1n+Nat.add(a, nb) == Nat.add(Nat.sub(a, b), m) : Nat}
575
576def sub_arith(a, b, nb, m, h, hn):
577 %hn : {1n+Nat.add(a, nb) == Nat.add(Nat.sub(a, b), _) : Nat}
578 %MNat.add_succ_sym(Nat.sub(a, b), Nat.add(nb, b)) : {1n+Nat.add(a, nb) == _ : Nat}
579 %MNat.sub_add_cancel(a, b, h) : {1n+Nat.add(_, nb) == 1n+Nat.add(Nat.sub(a, b), Nat.add(nb, b)) : Nat}
580 %MNat.add_assoc_sym(Nat.sub(a, b), b, nb) : {1n+_ == 1n+Nat.add(Nat.sub(a, b), Nat.add(nb, b)) : Nat}
581 %MNat.add_comm(nb, b) : {1n+Nat.add(Nat.sub(a, b), _) == 1n+Nat.add(Nat.sub(a, b), Nat.add(nb, b)) : Nat}
582 {==}
583
584law sub_fin:
585 for q: Bool
586 for +r: Nat
587 for +d: Nat
588 for +m: Nat
589 for e: {Nat.add(r, scale(q, m)) == Nat.add(d, m) : Nat}
590 for h: MNat.lt(r, m)
591 {r == d : Nat}
592
593def sub_fin(q, r, d, m, e, h):
594 match q:
595 case False{}:
596 Empty.absurd({r == d : Nat}, MNat.lt_irrefl(m)(MNat.lt_of_le_of_lt(m, Nat.add(d, m), m,
597 MNat.le_add_left(m, d), lt_rw(Nat.add(d, m), r, m,
598 Equal.sym(Nat, r, Nat.add(d, m),
599 Equal.trans(Nat, r, Nat.add(r, 0n), Nat.add(d, m), MNat.add_zero_sym(r), e)), h))))
600 case True{}:
601 MNat.add_right_cancel(r, m, d, e)
602
603
604law word_sub_nat:
605 for +n: Nat
606 for +a: Word(n)
607 for +b: Word(n)
608 for h: MNat.le(Word.to_nat(n, b), Word.to_nat(n, a))
609 {Word.to_nat(n, Word.sub(n, a, b)) == Nat.sub(Word.to_nat(n, a), Word.to_nat(n, b)) : Nat}
610
611def word_sub_nat(n, a, b, h):
612 %Equal.sym(Word(n), Word.adc(n, a, b, True{}, True{}),
613 Word.adc(n, a, Word.not(n, b), False{}, True{}), word_sub_not(n, a, b, True{})) :
614 {Word.to_nat(n, _) == Nat.sub(Word.to_nat(n, a), Word.to_nat(n, b)) : Nat}
615 sub_fin(carry(n, a, Word.not(n, b), True{}),
616 Word.to_nat(n, Word.adc(n, a, Word.not(n, b), False{}, True{})),
617 Nat.sub(Word.to_nat(n, a), Word.to_nat(n, b)), pow2(n),
618 Equal.trans(Nat,
619 Nat.add(Word.to_nat(n, Word.adc(n, a, Word.not(n, b), False{}, True{})),
620 scale(carry(n, a, Word.not(n, b), True{}), pow2(n))),
621 1n+Nat.add(Word.to_nat(n, a), Word.to_nat(n, Word.not(n, b))),
622 Nat.add(Nat.sub(Word.to_nat(n, a), Word.to_nat(n, b)), pow2(n)),
623 word_adc_nat(n, a, Word.not(n, b), True{}),
624 sub_arith(Word.to_nat(n, a), Word.to_nat(n, b), Word.to_nat(n, Word.not(n, b)), pow2(n), h,
625 word_not_nat(n, b))),
626 word_to_nat_lt(n, Word.adc(n, a, Word.not(n, b), False{}, True{})))
627
628law u32_sub_nat:
629 for a: U32
630 for b: U32
631 for h: MNat.le(U32.to_nat(b), U32.to_nat(a))
632 {U32.to_nat(U32.sub(a, b)) == Nat.sub(U32.to_nat(a), U32.to_nat(b)) : Nat}
633
634def u32_sub_nat(a, b, h):
635 match a b:
636 case U32{x} U32{y}:
637 word_sub_nat(32n, x, y, h)
638
639law lt_of_double_lt:
640 for a: Nat
641 for b: Nat
642 for h: MNat.lt(Nat.double(a), Nat.double(b))
643 MNat.lt(a, b)
644
645def lt_of_double_lt(a, b, h):
646 match a b:
647 case 0n 0n:
648 Empty.absurd(MNat.lt(0n, 0n), MNat.lt_zero(0n)(h))
649 case 1n+p 0n:
650 Empty.absurd(MNat.lt(1n+p, 0n), MNat.lt_zero(2n+Nat.double(p))(h))
651 case 0n 1n+q:
652 {==}
653 case 1n+p 1n+q:
654 lt_of_double_lt(p, q, h)
655
656
657law word_inc_nat:
658 for n: Nat
659 for w: Word(n)
660 for h: MNat.lt(1n+Word.to_nat(n, w), pow2(n))
661 {Word.to_nat(n, Word.inc(n, w)) == 1n+Word.to_nat(n, w) : Nat}
662
663def word_inc_nat(n, w, h):
664 match n:
665 case 0n:
666 Empty.absurd({0n == 1n : Nat}, MNat.lt_irrefl(1n)(h))
667 case 1n+ +p:
668 match w:
669 case WCon{False{}, t}:
670 {==}
671 case WCon{True{}, +t}:
672 Equal.cong(Nat, Nat, v => Nat.double(v), Word.to_nat(p, Word.inc(p, t)),
673 1n+Word.to_nat(p, t),
674 word_inc_nat(p, t, lt_of_double_lt(1n+Word.to_nat(p, t), pow2(p), h)))
675
676law u32_inc_nat:
677 for a: U32
678 for h: MNat.lt(1n+U32.to_nat(a), pow2(32n))
679 {U32.to_nat(U32.inc(a)) == 1n+U32.to_nat(a) : Nat}
680
681def u32_inc_nat(a, h):
682 match a:
683 case U32{+x}:
684 word_inc_nat(32n, x, lt_rw(1n+Word.to_nat(32n, x), 1n+U32.to_nat(U32{x}), pow2(32n), {==}, h))
685
686law u32_to_from_nat:
687 for k: Nat
688 for +h: MNat.lt(k, pow2(32n))
689 {U32.to_nat(U32.from_nat(k)) == k : Nat}
690
691def u32_to_from_nat(k, h):
692 match k:
693 case 0n:
694 {==}
695 case 1n+ +j:
696 +ih = u32_to_from_nat(j, MNat.lt_trans(j, 1n+j, pow2(32n), MNat.lt_succ_self(j), h))
697 Equal.trans(Nat, U32.to_nat(U32.inc(U32.from_nat(j))), 1n+U32.to_nat(U32.from_nat(j)), 1n+j,
698 u32_inc_nat(U32.from_nat(j), lt_rw(1n+U32.to_nat(U32.from_nat(j)), 1n+j, pow2(32n),
699 Equal.cong(Nat, Nat, v => 1n+v, U32.to_nat(U32.from_nat(j)), j, ih), h)),
700 Equal.cong(Nat, Nat, v => 1n+v, U32.to_nat(U32.from_nat(j)), j, ih))
701
702law u32_from_to_nat:
703 for +a: U32
704 {U32.from_nat(U32.to_nat(a)) == a : U32}
705
706def u32_from_to_nat(a):
707 u32_to_nat_inj(U32.from_nat(U32.to_nat(a)), a, u32_to_from_nat(U32.to_nat(a), u32_to_nat_lt(a)))
708
709law and_le_sub:
710 for c: Bool
711 for +a: Nat
712 for +b: Nat
713 for +l: Nat
714 for -s: Nat
715 for +hc: {Nat.is_le(a, l) == c : Bool}
716 for hs: MNat.le(a, l) -> {s == Nat.sub(l, a) : Nat}
717 {Bool.and(c, Nat.is_le(b, s)) == Nat.is_le(Nat.add(a, b), l) : Bool}
718
719def and_le_sub(c, a, b, l, s, hc, hs):
720 match c:
721 case True{}:
722 %Equal.sym(Nat, s, Nat.sub(l, a), hs(hc)) :
723 {Bool.and(True{}, Nat.is_le(b, _)) == Nat.is_le(Nat.add(a, b), l) : Bool}
724 %hc : {Bool.and(_, Nat.is_le(b, Nat.sub(l, a))) == Nat.is_le(Nat.add(a, b), l) : Bool}
725 MNat.le_and_le_sub_iff_add_le(a, b, l)
726 case False{}:
727 %MNat.le_and_le_sub_iff_add_le(a, b, l) : {Bool.and(False{}, Nat.is_le(b, s)) == _ : Bool}
728 %Equal.sym(Bool, Nat.is_le(a, l), False{}, hc) :
729 {Bool.and(False{}, Nat.is_le(b, s)) == Bool.and(_, Nat.is_le(b, Nat.sub(l, a))) : Bool}
730 {==}
731
732
733law u32_fits_nat:
734 for +len: U32
735 for +i: U32
736 for +n: U32
737 {Bool.and(U32.is_le(n, len), U32.is_le(i, U32.sub(len, n))) == Nat.is_le(Nat.add(U32.to_nat(i), U32.to_nat(n)), U32.to_nat(len)) : Bool}
738
739def u32_fits_nat(len, i, n):
740 %Equal.sym(Bool, U32.is_le(n, len), Nat.is_le(U32.to_nat(n), U32.to_nat(len)), u32_is_le_nat(n, len)) :
741 {Bool.and(_, U32.is_le(i, U32.sub(len, n))) == Nat.is_le(Nat.add(U32.to_nat(i), U32.to_nat(n)), U32.to_nat(len)) : Bool}
742 %Equal.sym(Bool, U32.is_le(i, U32.sub(len, n)), Nat.is_le(U32.to_nat(i), U32.to_nat(U32.sub(len, n))), u32_is_le_nat(i, U32.sub(len, n))) :
743 {Bool.and(Nat.is_le(U32.to_nat(n), U32.to_nat(len)), _) == Nat.is_le(Nat.add(U32.to_nat(i), U32.to_nat(n)), U32.to_nat(len)) : Bool}
744 %MNat.add_comm(U32.to_nat(n), U32.to_nat(i)) :
745 {Bool.and(Nat.is_le(U32.to_nat(n), U32.to_nat(len)), Nat.is_le(U32.to_nat(i), U32.to_nat(U32.sub(len, n)))) == Nat.is_le(_, U32.to_nat(len)) : Bool}
746 and_le_sub(Nat.is_le(U32.to_nat(n), U32.to_nat(len)), U32.to_nat(n), U32.to_nat(i), U32.to_nat(len), U32.to_nat(U32.sub(len, n)), {==}, h => u32_sub_nat(len, n, h))