1#[allow(unused_imports)]
6use vstd::arithmetic::power2::*;
7#[allow(unused_imports)]
8use vstd::bits::*;
9#[allow(unused_imports)]
10use vstd::prelude::*;
11
12verus! {
13
14pub const LIMIT: u64 = 0x1_0000_0000_0000;
16
17pub fn and(a: u64, b: u64) -> (r: u64)
19 requires
20 a < LIMIT,
21 b < LIMIT,
22 ensures
23 r == a & b,
24 r < LIMIT,
25 r <= a,
26 r <= b,
27{
28 assert(a & b <= a && a & b <= b) by (bit_vector);
29 a & b
30}
31
32pub fn or(a: u64, b: u64) -> (r: u64)
34 requires
35 a < LIMIT,
36 b < LIMIT,
37 ensures
38 r == a | b,
39 r < LIMIT,
40 r >= a,
41 r >= b,
42{
43 assert(a | b < 0x1_0000_0000_0000 && a | b >= a && a | b >= b) by (bit_vector)
44 requires
45 a < 0x1_0000_0000_0000,
46 b < 0x1_0000_0000_0000,
47 ;
48 a | b
49}
50
51pub fn xor(a: u64, b: u64) -> (r: u64)
53 requires
54 a < LIMIT,
55 b < LIMIT,
56 ensures
57 r == a ^ b,
58 r < LIMIT,
59{
60 assert(a ^ b < 0x1_0000_0000_0000) by (bit_vector)
61 requires
62 a < 0x1_0000_0000_0000,
63 b < 0x1_0000_0000_0000,
64 ;
65 a ^ b
66}
67
68pub fn shl(x: u64, n: u32) -> (r: u128)
70 requires
71 x < LIMIT,
72 n <= 53,
73 ensures
74 r == x * pow2(n as nat),
75 r < 0x20_0000_0000_0000_0000_0000_0000,
76{
77 proof {
78 lemma2_to64_rest();
79 if n < 53 {
80 lemma_pow2_strictly_increases(n as nat, 53);
81 }
82 let p = pow2(n as nat);
83 assert(x * p < 0x20_0000_0000_0000_0000_0000_0000) by (nonlinear_arith)
84 requires
85 x < 0x1_0000_0000_0000,
86 p <= 0x20_0000_0000_0000,
87 ;
88 lemma_u64_pow2_no_overflow(n as nat);
89 lemma_u64_shl_is_mul(1, n as u64);
90 }
91 let p = 1u64 << (n as u64);
92 (x as u128) * (p as u128)
93}
94
95pub fn shr(x: u64, n: u32) -> (r: u64)
97 requires
98 n <= 53,
99 ensures
100 r as nat == x as nat / pow2(n as nat),
101 r <= x,
102{
103 proof {
104 lemma_u64_shr_is_div(x, n as u64);
105 }
106 let s = n as u64;
107 assert(x >> s <= x) by (bit_vector);
108 x >> s
109}
110
111} #[cfg(test)]
114#[cfg_attr(coverage_nightly, coverage(off))]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn bit_ops() {
120 assert_eq!(and(0b1100, 0b1010), 0b1000);
121 assert_eq!(or(0b1100, 0b1010), 0b1110);
122 assert_eq!(xor(0b1100, 0b1010), 0b0110);
123 assert_eq!(shl(LIMIT - 1, 53), u128::from(LIMIT - 1) << 53);
124 assert_eq!(shr(LIMIT - 1, 47), 1);
125 assert_eq!(shr(5, 53), 0);
126 }
127}