1extern crate core;
7use core::ffi::*;
8use core::cmp::{PartialOrd, Ordering};
9use core::cell::UnsafeCell;
10use core::ops::*;
11use core::fmt;
12
13use crate::types::*;
14
15extern "C" {
16 pub(crate) fn xwbmpop_cmp(bmp: *mut c_void, opt: *mut c_void, num: XwSz) -> XwSsq;
17 pub(crate) fn xwbmpop_s1all(bmp: *mut c_void, num: XwSz);
18 pub(crate) fn xwbmpop_c0all(bmp: *mut c_void, num: XwSz);
19 pub(crate) fn xwbmpop_s1i(bmp: *mut c_void, n: XwSq);
20 pub(crate) fn xwbmpop_s1m(bmp: *mut c_void, msk: *mut c_void, num: XwSz);
21 pub(crate) fn xwbmpop_c0i(bmp: *mut c_void, n: XwSq);
22 pub(crate) fn xwbmpop_c0m(bmp: *mut c_void, msk: *mut c_void, num: XwSz);
23 pub(crate) fn xwbmpop_x1i(bmp: *mut c_void, n: XwSq);
24 pub(crate) fn xwbmpop_x1m(bmp: *mut c_void, msk: *mut c_void, num: XwSz);
25 pub(crate) fn xwbmpop_t1i(bmp: *mut c_void, n: XwSq) -> bool;
26 pub(crate) fn xwbmpop_t1ma(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
27 pub(crate) fn xwbmpop_t1ma_then_c0m(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
28 pub(crate) fn xwbmpop_t1mo(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
29 pub(crate) fn xwbmpop_t1mo_then_c0m(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
30 pub(crate) fn xwbmpop_t0ma(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
31 pub(crate) fn xwbmpop_t0ma_then_s1m(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
32 pub(crate) fn xwbmpop_t0mo(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
33 pub(crate) fn xwbmpop_t0mo_then_s1m(bmp: *mut c_void, msk: *mut c_void, num: XwSz) -> bool;
34 pub(crate) fn xwbmpop_not(bmp: *mut c_void, num: XwSz);
35 pub(crate) fn xwbmpop_and(bmp: *mut c_void, msk: *mut c_void, num: XwSz);
36 pub(crate) fn xwbmpop_or(bmp: *mut c_void, msk: *mut c_void, num: XwSz);
37 pub(crate) fn xwbmpop_xor(bmp: *mut c_void, msk: *mut c_void, num: XwSz);
38 pub(crate) fn xwbmpop_ffs(bmp: *mut c_void, num: XwSz) -> XwSsq;
39 pub(crate) fn xwbmpop_ffz(bmp: *mut c_void, num: XwSz) -> XwSsq;
40 pub(crate) fn xwbmpop_fls(bmp: *mut c_void, num: XwSz) -> XwSsq;
41 pub(crate) fn xwbmpop_flz(bmp: *mut c_void, num: XwSz) -> XwSsq;
42 pub(crate) fn xwbmpop_weight(bmp: *mut c_void, num: XwSz) -> XwSz;
43}
44
45#[repr(C)]
46#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
47#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
48pub(crate) struct BmpArray<const N: XwSz>
49where
50 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
51{
52 #[doc(hidden)]
53 pub(crate) array: [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize],
54}
55
56pub struct Bmp<const N: XwSz>
60where
61 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
62{
63 #[doc(hidden)]
64 pub(crate) bmp: UnsafeCell<BmpArray<N>>,
65}
66
67unsafe impl<const N: XwSz> Send for Bmp<N>
68where
69 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
70{}
71
72unsafe impl<const N: XwSz> Sync for Bmp<N>
73where
74 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
75{}
76
77impl<const N: XwSz> Bmp<N>
78where
79 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
80{
81 pub const fn new() -> Self {
121 Self {
122 bmp: UnsafeCell::new(BmpArray {
123 array: [0; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize],
124 }),
125 }
126 }
127
128 pub const fn bits(&self) -> XwSz {
130 N
131 }
132
133 pub fn weight(&self) -> XwSz {
135 unsafe {
136 xwbmpop_weight(self.bmp.get() as _ , N)
137 }
138 }
139
140 pub fn s1all(&self) {
142 unsafe {
143 xwbmpop_s1all(self.bmp.get() as _ , N);
144 }
145 }
146
147 pub fn c0all(&self) {
149 unsafe {
150 xwbmpop_c0all(self.bmp.get() as _ , N);
151 }
152 }
153
154 pub fn s1i(&self, n: XwSq) {
156 unsafe {
157 xwbmpop_s1i(self.bmp.get() as _ , n);
158 }
159 }
160
161 pub fn s1m(&self, msk: &Self) {
163 unsafe {
164 xwbmpop_s1m(self.bmp.get() as _ , msk.bmp.get() as _, N);
165 }
166 }
167
168 pub fn c0i(&self, n: XwSq) {
170 unsafe {
171 xwbmpop_c0i(self.bmp.get() as _ , n);
172 }
173 }
174
175 pub fn c0m(&self, msk: &Self) {
177 unsafe {
178 xwbmpop_c0m(self.bmp.get() as _ , msk.bmp.get() as _, N);
179 }
180 }
181
182 pub fn x1i(&self, n: XwSq) {
184 unsafe {
185 xwbmpop_x1i(self.bmp.get() as _ , n);
186 }
187 }
188
189 pub fn x1m(&self, msk: &Self) {
191 unsafe {
192 xwbmpop_x1m(self.bmp.get() as _ , msk.bmp.get() as _, N);
193 }
194 }
195
196 pub fn t1i(&self, n: XwSq) -> bool {
198 unsafe {
199 xwbmpop_t1i(self.bmp.get() as _ , n)
200 }
201 }
202
203 pub fn t1ma(&self, msk: &Self) -> bool {
205 unsafe {
206 xwbmpop_t1ma(self.bmp.get() as _ , msk.bmp.get() as _, N)
207 }
208 }
209
210 pub fn t1mo(&self, msk: &Self) -> bool {
212 unsafe {
213 xwbmpop_t1mo(self.bmp.get() as _ , msk.bmp.get() as _, N)
214 }
215 }
216
217 pub fn t1ma_then_c0m(&self, msk: &Self) -> bool {
219 unsafe {
220 xwbmpop_t1ma_then_c0m(self.bmp.get() as _ , msk.bmp.get() as _, N)
221 }
222 }
223
224 pub fn t1mo_then_c0m(&self, msk: &Self) -> bool {
226 unsafe {
227 xwbmpop_t1mo_then_c0m(self.bmp.get() as _ , msk.bmp.get() as _, N)
228 }
229 }
230
231 pub fn t0ma_then_s1m(&self, msk: &Self) -> bool {
233 unsafe {
234 xwbmpop_t0ma_then_s1m(self.bmp.get() as _ , msk.bmp.get() as _, N)
235 }
236 }
237
238 pub fn t0mo_then_s1m(&self, msk: &Self) -> bool {
240 unsafe {
241 xwbmpop_t0mo_then_s1m(self.bmp.get() as _ , msk.bmp.get() as _, N)
242 }
243 }
244
245 pub fn ffs(&self) -> XwSsq {
247 unsafe {
248 xwbmpop_ffs(self.bmp.get() as _ , N)
249 }
250 }
251
252 pub fn ffz(&self) -> XwSsq {
254 unsafe {
255 xwbmpop_ffz(self.bmp.get() as _ , N)
256 }
257 }
258
259 pub fn fls(&self) -> XwSsq {
261 unsafe {
262 xwbmpop_fls(self.bmp.get() as _ , N)
263 }
264 }
265
266 pub fn flz(&self) -> XwSsq {
268 unsafe {
269 xwbmpop_flz(self.bmp.get() as _ , N)
270 }
271 }
272}
273
274impl<const N: XwSz> PartialEq for Bmp<N>
275where
276 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
277{
278 fn eq(&self, other: &Self) -> bool {
279 unsafe {
280 let rc = xwbmpop_cmp(self.bmp.get() as _, other.bmp.get() as _, N);
281 rc == 0
282 }
283 }
284}
285
286impl<const N: XwSz> PartialOrd for Bmp<N>
287where
288 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
289{
290 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
291 unsafe {
292 let rc = xwbmpop_cmp(self.bmp.get() as _, other.bmp.get() as _, N);
293 if rc < 0 {
294 Some(Ordering::Less)
295 } else if rc > 0 {
296 Some(Ordering::Greater)
297 } else {
298 Some(Ordering::Equal)
299 }
300 }
301 }
302}
303
304impl<const N: XwSz> BitAnd for Bmp<N>
305where
306 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
307{
308 type Output = Self;
309
310 fn bitand(self, other: Self) -> Self {
311 unsafe {
312 xwbmpop_and(self.bmp.get() as _, other.bmp.get() as _, N);
313 self
314 }
315 }
316}
317
318impl<const N: XwSz> BitAndAssign for Bmp<N>
319where
320 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
321{
322 fn bitand_assign(&mut self, other: Self) {
323 unsafe {
324 xwbmpop_and(self.bmp.get() as _, other.bmp.get() as _, N);
325 }
326 }
327}
328
329impl<const N: XwSz> BitOr for Bmp<N>
330where
331 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
332{
333 type Output = Self;
334
335 fn bitor(self, other: Self) -> Self {
336 unsafe {
337 xwbmpop_or(self.bmp.get() as _, other.bmp.get() as _, N);
338 self
339 }
340 }
341}
342
343impl<const N: XwSz> BitOrAssign for Bmp<N>
344where
345 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
346{
347 fn bitor_assign(&mut self, other: Self) {
348 unsafe {
349 xwbmpop_or(self.bmp.get() as _, other.bmp.get() as _, N);
350 }
351 }
352}
353
354impl<const N: XwSz> BitXor for Bmp<N>
355where
356 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
357{
358 type Output = Self;
359
360 fn bitxor(self, other: Self) -> Self {
361 unsafe {
362 xwbmpop_xor(self.bmp.get() as _, other.bmp.get() as _, N);
363 self
364 }
365 }
366}
367
368impl<const N: XwSz> BitXorAssign for Bmp<N>
369where
370 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
371{
372 fn bitxor_assign(&mut self, other: Self) {
373 unsafe {
374 xwbmpop_xor(self.bmp.get() as _, other.bmp.get() as _, N);
375 }
376 }
377}
378
379impl<const N: XwSz> Neg for Bmp<N>
380where
381 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
382{
383 type Output = Self;
384
385 fn neg(self) -> Self{
386 unsafe {
387 xwbmpop_not(self.bmp.get() as _, N);
388 self
389 }
390 }
391}
392
393impl<const N: XwSz> fmt::Debug for Bmp<N>
394where
395 [XwBmp; (N + XwBmp::BITS as usize - 1) / XwBmp::BITS as usize]: Sized
396{
397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 unsafe {
399 f.debug_struct("Bmp")
400 .field("bits", &self.bits())
401 .field("array", &(*(self.bmp.get())).array)
402 .finish()
403 }
404 }
405}