finality_grandpa/
bitfield.rs

1// Copyright 2018-2019 Parity Technologies (UK) Ltd
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Dynamically sized, write-once, lazily allocating bitfields,
16//! e.g. for compact accumulation of votes cast on a block while
17//! retaining information on the type of vote and identity of the
18//! voter within a voter set.
19
20use crate::std::{cmp::Ordering, iter, ops::BitOr, vec::Vec};
21use either::Either;
22
23/// A dynamically sized, write-once (per bit), lazily allocating bitfield.
24#[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	/// Create a new empty bitfield.
37	///
38	/// Does not allocate.
39	pub fn new() -> Bitfield {
40		Bitfield { bits: Vec::new() }
41	}
42
43	/// Whether the bitfield is blank / empty.
44	pub fn is_blank(&self) -> bool {
45		self.bits.is_empty()
46	}
47
48	/// Merge another bitfield into this bitfield.
49	///
50	/// As a result, this bitfield has all bits set that are set in either bitfield.
51	///
52	/// This function only allocates if this bitfield is shorter than the other
53	/// bitfield, in which case it is resized accordingly to accomodate for all
54	/// bits of the other bitfield.
55	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	/// Set a bit in the bitfield at the specified position.
69	///
70	/// If the bitfield is not large enough to accomodate for a bit set
71	/// at the specified position, it is resized accordingly.
72	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	/// Test if the bit at the specified position is set.
86	#[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	/// Get an iterator over all bits that are set (i.e. 1) at even bit positions.
98	pub fn iter1s_even(&self) -> impl Iterator<Item = Bit1> + '_ {
99		self.iter1s(0, 1)
100	}
101
102	/// Get an iterator over all bits that are set (i.e. 1) at odd bit positions.
103	pub fn iter1s_odd(&self) -> impl Iterator<Item = Bit1> + '_ {
104		self.iter1s(1, 1)
105	}
106
107	/// Get an iterator over all bits that are set (i.e. 1) at even bit positions
108	/// when merging this bitfield with another bitfield, without modifying
109	/// either bitfield.
110	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	/// Get an iterator over all bits that are set (i.e. 1) at odd bit positions
115	/// when merging this bitfield with another bitfield, without modifying
116	/// either bitfield.
117	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	/// Get an iterator over all bits that are set (i.e. 1) in the bitfield,
122	/// starting at bit position `start` and moving in steps of size `2^step`
123	/// per word.
124	fn iter1s(&self, start: usize, step: usize) -> impl Iterator<Item = Bit1> + '_ {
125		iter1s(self.bits.iter().cloned(), start, step)
126	}
127
128	/// Get an iterator over all bits that are set (i.e. 1) when merging
129	/// this bitfield with another bitfield, without modifying either
130	/// bitfield, starting at bit position `start` and moving in steps
131	/// of size `2^step` per word.
132	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
161/// Turn an iterator over u64 words into an iterator over bits that
162/// are set (i.e. `1`) in these words, starting at bit position `start`
163/// and moving in steps of size `2^step` per word.
164fn 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/// A bit that is set (i.e. 1) in a `Bitfield`.
198#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
199pub struct Bit1 {
200	/// The position of the bit in the bitfield.
201	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			// we need to make sure we don't add empty words at the end of the
216			// bitfield otherwise it would break equality on some of the tests
217			// below.
218			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's bound the max bitfield index at 2^24. this is needed because when calling
230			// `set_bit` we will extend the backing vec to accomodate the given bitfield size, this
231			// way we restrict the maximum allocation size to 16MB.
232			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}