microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.25.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/paulimer/src/bits/bitblock.rs

261lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use std::ops::{BitAnd, BitAndAssign, BitXor, BitXorAssign, Index};
5
6use super::standard_types::{array_get_unchecked, array_set_unchecked, BitIterator};
7use super::{Bitwise, BitwiseNeutralElement, IndexAssignable, WORD_COUNT_DEFAULT};
8use crate::NeutralElement;
9
10pub type Word = u64;
11
12#[repr(C, align(64))]
13#[derive(Eq, Clone, Debug, Hash, PartialEq)]
14pub struct BitBlock<const WORD_COUNT: usize = WORD_COUNT_DEFAULT> {
15 pub blocks: [Word; WORD_COUNT],
16}
17
18#[derive(Clone, Debug, Hash, PartialEq)]
19pub struct BitAccessor<const WORD_COUNT: usize = WORD_COUNT_DEFAULT> {
20 word_index: usize,
21 bitmask: Word,
22}
23
24impl<const WORD_COUNT: usize> BitBlock<WORD_COUNT> {
25 pub const BITS: usize = WORD_COUNT * (Word::BITS as usize);
26
27 #[must_use]
28 pub fn zeros() -> Self {
29 Self {
30 blocks: [0; WORD_COUNT],
31 }
32 }
33
34 #[must_use]
35 pub fn ones() -> Self {
36 Self {
37 blocks: [Word::MAX; WORD_COUNT],
38 }
39 }
40
41 #[must_use]
42 pub const fn bits() -> usize {
43 Self::BITS
44 }
45
46 #[must_use]
47 pub fn array(&self) -> &[Word; WORD_COUNT] {
48 &self.blocks
49 }
50
51 pub fn array_mut(&mut self) -> &mut [Word; WORD_COUNT] {
52 &mut self.blocks
53 }
54
55 #[must_use]
56 pub fn all(value: bool) -> Self {
57 if value {
58 Self::ones()
59 } else {
60 Self::zeros()
61 }
62 }
63
64 /// # Panics
65 ///
66 /// Will panic when array is too big
67 #[must_use]
68 pub fn from_array<const ARRAY_SIZE: usize>(bits: [bool; ARRAY_SIZE]) -> Self {
69 assert!(ARRAY_SIZE <= Self::bits());
70 let mut block = Self::zeros();
71 for (index, bit) in bits.iter().enumerate() {
72 block.set(index, *bit);
73 }
74 block
75 }
76
77 /// # Panics
78 ///
79 /// Will panic if index out of range
80 #[must_use]
81 pub fn get(&self, index: usize) -> bool {
82 assert!(index < Self::BITS);
83 unsafe { self.get_unchecked(index) }
84 }
85
86 /// # Safety
87 /// Does not check if index is out of bounds
88 #[must_use]
89 pub unsafe fn get_unchecked(&self, index: usize) -> bool {
90 array_get_unchecked(self.array(), index)
91 }
92
93 /// # Panics
94 ///
95 /// Will panic if index out of range
96 pub fn set(&mut self, index: usize, to: bool) {
97 assert!(index < Self::BITS);
98 unsafe { self.set_unchecked(index, to) };
99 }
100
101 /// # Safety
102 /// Does not check if index is out of bounds
103 pub unsafe fn set_unchecked(&mut self, index: usize, to: bool) {
104 array_set_unchecked(self.array_mut(), index, to);
105 }
106
107 #[must_use]
108 pub fn parity(&self) -> bool {
109 self.blocks.parity()
110 }
111
112 #[must_use]
113 pub fn weight(&self) -> usize {
114 self.blocks.weight()
115 }
116
117 #[must_use]
118 pub fn is_zero(&self) -> bool {
119 self.blocks.is_zero()
120 }
121
122 #[must_use]
123 pub fn iter(&self) -> BitIterator<'_> {
124 BitIterator::from_bits(&self.blocks)
125 }
126}
127
128impl<'life, const WORD_COUNT: usize> IntoIterator for &'life BitBlock<WORD_COUNT> {
129 type Item = bool;
130 type IntoIter = BitIterator<'life>;
131 fn into_iter(self) -> Self::IntoIter {
132 self.iter()
133 }
134}
135
136impl<const WORD_COUNT: usize> NeutralElement for BitBlock<WORD_COUNT> {
137 type NeutralElementType = BitBlock<WORD_COUNT>;
138
139 fn neutral_element(&self) -> <Self as NeutralElement>::NeutralElementType {
140 Self::zeros()
141 }
142
143 fn default_size_neutral_element() -> <Self as NeutralElement>::NeutralElementType {
144 Self::zeros()
145 }
146
147 fn neutral_element_of_size(size: usize) -> <Self as NeutralElement>::NeutralElementType {
148 assert!(size <= BitBlock::<WORD_COUNT>::BITS);
149 Self::default_size_neutral_element()
150 }
151}
152
153impl<const WORD_COUNT: usize> BitwiseNeutralElement for BitBlock<WORD_COUNT> {}
154
155impl Index<usize> for BitBlock {
156 type Output = bool;
157
158 fn index(&self, index: usize) -> &Self::Output {
159 if Bitwise::index(&self.blocks, index) {
160 &true
161 } else {
162 &false
163 }
164 }
165}
166
167impl<const WORDCOUNT: usize> BitXorAssign<&BitBlock<WORDCOUNT>> for BitBlock<WORDCOUNT> {
168 fn bitxor_assign(&mut self, other: &Self) {
169 for index in 0..WORDCOUNT {
170 self.blocks[index] ^= other.blocks[index];
171 }
172 }
173}
174
175impl<const WORDCOUNT: usize> BitXor for &BitBlock<WORDCOUNT> {
176 type Output = BitBlock<WORDCOUNT>;
177
178 fn bitxor(self, other: Self) -> Self::Output {
179 let mut clone = (*self).clone();
180 clone ^= other;
181 clone
182 }
183}
184
185impl<const WORDCOUNT: usize> BitAndAssign<&BitBlock<WORDCOUNT>> for BitBlock<WORDCOUNT> {
186 fn bitand_assign(&mut self, other: &Self) {
187 for index in 0..WORDCOUNT {
188 self.blocks[index] &= other.blocks[index];
189 }
190 }
191}
192
193impl<const WORDCOUNT: usize> BitAnd for &BitBlock<WORDCOUNT> {
194 type Output = BitBlock<WORDCOUNT>;
195
196 fn bitand(self, other: Self) -> Self::Output {
197 let mut clone = (*self).clone();
198 clone &= other;
199 clone
200 }
201}
202
203impl<const WORD_COUNT: usize> FromIterator<bool> for BitBlock<WORD_COUNT> {
204 fn from_iter<Iterator: IntoIterator<Item = bool>>(iterator: Iterator) -> Self {
205 let mut res: BitBlock<WORD_COUNT> = BitBlock::<WORD_COUNT>::default_size_neutral_element();
206 for (index, bit) in iterator.into_iter().enumerate() {
207 res.assign_index(index, bit);
208 }
209 res
210 }
211}
212
213// Bit accessor for [Word; WORDCOUNT]
214
215impl<const WORDCOUNT: usize> BitAccessor<WORDCOUNT> {
216 /// # Panics
217 ///
218 /// Will panic index is out of range
219 #[must_use]
220 pub fn for_index(index: usize) -> Self {
221 assert!(index < BitBlock::<WORDCOUNT>::BITS);
222 unsafe { Self::for_index_unchecked(index) }
223 }
224
225 /// # Safety
226 /// Does not check if index is out of bounds
227 #[must_use]
228 pub unsafe fn for_index_unchecked(index: usize) -> Self {
229 let word_index = index / (Word::BITS as usize);
230 let bit_index = index % (Word::BITS as usize);
231 Self {
232 word_index,
233 bitmask: 1 << bit_index,
234 }
235 }
236
237 #[must_use]
238 pub fn array_value_of(&self, block: &[Word; WORDCOUNT]) -> bool {
239 let word = unsafe { block.get_unchecked(self.word_index) };
240 (*word & self.bitmask) != 0
241 }
242
243 pub fn array_bitxor(&self, block: &mut [Word; WORDCOUNT]) {
244 let word: &mut Word = unsafe { block.get_unchecked_mut(self.word_index) };
245 *word ^= self.bitmask;
246 }
247
248 pub fn array_set_value_of(&self, block: &mut [Word; WORDCOUNT], to: bool) {
249 let word = unsafe { block.get_unchecked_mut(self.word_index) };
250 // let mask = !self.bitmask;
251 // let bit_index = mask.trailing_ones();
252 // let bit_value = (to as Word) << bit_index;
253 // *word &= mask;
254 // *word |= bit_value;
255 if to {
256 *word |= self.bitmask;
257 } else {
258 *word &= !self.bitmask;
259 }
260 }
261}
262