finality_grandpa/
bitfield.rs1use crate::std::{cmp::Ordering, iter, ops::BitOr, vec::Vec};
21use either::Either;
22
23#[derive(Eq, PartialEq, Clone, Debug, Default)]
25pub struct Bitfield {
26 bits: Vec<u64>,
27}
28
29impl From<Vec<u64>> for Bitfield {
30 fn from(bits: Vec<u64>) -> Bitfield {
31 Bitfield { bits }
32 }
33}
34
35impl Bitfield {
36 pub fn new() -> Bitfield {
40 Bitfield { bits: Vec::new() }
41 }
42
43 pub fn is_blank(&self) -> bool {
45 self.bits.is_empty()
46 }
47
48 pub fn merge(&mut self, other: &Self) -> &mut Self {
56 if self.bits.len() < other.bits.len() {
57 let new_len = other.bits.len();
58 self.bits.resize(new_len, 0);
59 }
60
61 for (i, word) in other.bits.iter().enumerate() {
62 self.bits[i] |= word;
63 }
64
65 self
66 }
67
68 pub fn set_bit(&mut self, position: usize) -> &mut Self {
73 let word_off = position / 64;
74 let bit_off = position % 64;
75
76 if word_off >= self.bits.len() {
77 let new_len = word_off + 1;
78 self.bits.resize(new_len, 0);
79 }
80
81 self.bits[word_off] |= 1 << (63 - bit_off);
82 self
83 }
84
85 #[cfg(test)]
87 pub fn test_bit(&self, position: usize) -> bool {
88 let word_off = position / 64;
89
90 if word_off >= self.bits.len() {
91 return false
92 }
93
94 test_bit(self.bits[word_off], position % 64)
95 }
96
97 pub fn iter1s_even(&self) -> impl Iterator<Item = Bit1> + '_ {
99 self.iter1s(0, 1)
100 }
101
102 pub fn iter1s_odd(&self) -> impl Iterator<Item = Bit1> + '_ {
104 self.iter1s(1, 1)
105 }
106
107 pub fn iter1s_merged_even<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = Bit1> + 'a {
111 self.iter1s_merged(other, 0, 1)
112 }
113
114 pub fn iter1s_merged_odd<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = Bit1> + 'a {
118 self.iter1s_merged(other, 1, 1)
119 }
120
121 fn iter1s(&self, start: usize, step: usize) -> impl Iterator<Item = Bit1> + '_ {
125 iter1s(self.bits.iter().cloned(), start, step)
126 }
127
128 fn iter1s_merged<'a>(
133 &'a self,
134 other: &'a Self,
135 start: usize,
136 step: usize,
137 ) -> impl Iterator<Item = Bit1> + 'a {
138 match self.bits.len().cmp(&other.bits.len()) {
139 Ordering::Equal => Either::Left(iter1s(
140 self.bits.iter().zip(&other.bits).map(|(a, b)| a | b),
141 start,
142 step,
143 )),
144 Ordering::Less => Either::Right(Either::Left(iter1s(
145 self.bits.iter().chain(iter::repeat(&0)).zip(&other.bits).map(|(a, b)| a | b),
146 start,
147 step,
148 ))),
149 Ordering::Greater => Either::Right(Either::Right(iter1s(
150 self.bits
151 .iter()
152 .zip(other.bits.iter().chain(iter::repeat(&0)))
153 .map(|(a, b)| a | b),
154 start,
155 step,
156 ))),
157 }
158 }
159}
160
161fn iter1s<'a, I>(iter: I, start: usize, step: usize) -> impl Iterator<Item = Bit1> + 'a
165where
166 I: Iterator<Item = u64> + 'a,
167{
168 debug_assert!(start < 64 && step < 7);
169 let steps = (64 >> step) - (start >> step);
170 iter.enumerate().flat_map(move |(i, word)| {
171 let n = if word == 0 { 0 } else { steps };
172 (0..n).filter_map(move |j| {
173 let bit_pos = start + (j << step);
174 if test_bit(word, bit_pos) {
175 Some(Bit1 { position: i * 64 + bit_pos })
176 } else {
177 None
178 }
179 })
180 })
181}
182
183fn test_bit(word: u64, position: usize) -> bool {
184 let mask = 1 << (63 - position);
185 word & mask == mask
186}
187
188impl BitOr<&Bitfield> for Bitfield {
189 type Output = Bitfield;
190
191 fn bitor(mut self, rhs: &Bitfield) -> Self::Output {
192 self.merge(rhs);
193 self
194 }
195}
196
197#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
199pub struct Bit1 {
200 pub position: usize,
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207 use crate::std::iter;
208 use quickcheck::*;
209
210 impl Arbitrary for Bitfield {
211 fn arbitrary(g: &mut Gen) -> Bitfield {
212 let n = usize::arbitrary(g) % g.size();
213 let mut b = iter::from_fn(|| Some(u64::arbitrary(g))).take(n).collect::<Vec<_>>();
214
215 while let Some(0) = b.last() {
219 b.pop();
220 }
221
222 Bitfield::from(b)
223 }
224 }
225
226 #[test]
227 fn set_bit() {
228 fn prop(mut a: Bitfield, idx: usize) -> bool {
229 let idx = idx.min(1 << 24);
233
234 a.set_bit(idx).test_bit(idx)
235 }
236
237 quickcheck(prop as fn(_, _) -> _)
238 }
239
240 #[test]
241 fn bitor() {
242 fn prop(a: Bitfield, b: Bitfield) -> bool {
243 let c = a.clone() | &b;
244 let mut c_bits = c.iter1s(0, 0);
245 c_bits.all(|bit| a.test_bit(bit.position) || b.test_bit(bit.position))
246 }
247
248 quickcheck(prop as fn(_, _) -> _)
249 }
250
251 #[test]
252 fn bitor_commutative() {
253 fn prop(a: Bitfield, b: Bitfield) -> bool {
254 a.clone() | &b == b | &a
255 }
256
257 quickcheck(prop as fn(_, _) -> _)
258 }
259
260 #[test]
261 fn bitor_associative() {
262 fn prop(a: Bitfield, b: Bitfield, c: Bitfield) -> bool {
263 (a.clone() | &b) | &c == a | &(b | &c)
264 }
265
266 quickcheck(prop as fn(_, _, _) -> _)
267 }
268
269 #[test]
270 fn iter1s() {
271 fn all(a: Bitfield) {
272 let mut b = Bitfield::new();
273 for Bit1 { position } in a.iter1s(0, 0) {
274 b.set_bit(position);
275 }
276 assert_eq!(a, b);
277 }
278
279 fn even_odd(a: Bitfield) {
280 let mut b = Bitfield::new();
281 for Bit1 { position } in a.iter1s_even() {
282 assert!(!b.test_bit(position));
283 assert!(position % 2 == 0);
284 b.set_bit(position);
285 }
286 for Bit1 { position } in a.iter1s_odd() {
287 assert!(!b.test_bit(position));
288 assert!(position % 2 == 1);
289 b.set_bit(position);
290 }
291 assert_eq!(a, b);
292 }
293
294 quickcheck(all as fn(_));
295 quickcheck(even_odd as fn(_));
296 }
297
298 #[test]
299 fn iter1s_merged() {
300 fn all(mut a: Bitfield, b: Bitfield) {
301 let mut c = Bitfield::new();
302 for bit1 in a.iter1s_merged(&b, 0, 0) {
303 c.set_bit(bit1.position);
304 }
305 assert_eq!(&c, a.merge(&b))
306 }
307
308 fn even_odd(mut a: Bitfield, b: Bitfield) {
309 let mut c = Bitfield::new();
310 for Bit1 { position } in a.iter1s_merged_even(&b) {
311 assert!(!c.test_bit(position));
312 assert!(position % 2 == 0);
313 c.set_bit(position);
314 }
315 for Bit1 { position } in a.iter1s_merged_odd(&b) {
316 assert!(!c.test_bit(position));
317 assert!(position % 2 == 1);
318 c.set_bit(position);
319 }
320 assert_eq!(&c, a.merge(&b));
321 }
322
323 quickcheck(all as fn(_, _));
324 quickcheck(even_odd as fn(_, _));
325 }
326}