1use std::{
5 fmt::{Debug, Display, LowerHex},
6 hash::{Hash, Hasher},
7 mem::size_of,
8 ops::{Not, Shl, Shr},
9};
10
11use binius_utils::{
12 FixedSizeSerializeBytes, SerializationError, SerializeBytes,
13 bytes::{Buf, BufMut},
14 checked_arithmetics::checked_log_2,
15 serialization::DeserializeBytes,
16};
17use bytemuck::{NoUninit, Zeroable};
18use derive_more::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign};
19use rand::{
20 distr::{Distribution, StandardUniform},
21 prelude::*,
22};
23
24use super::Underlier;
25use crate::{
26 arch::{interleave_mask_even, interleave_with_mask},
27 divisible::{Divisible, impl_divisible_self, mapget},
28};
29
30#[derive(
32 Default,
33 Zeroable,
34 Clone,
35 Copy,
36 PartialEq,
37 Eq,
38 PartialOrd,
39 Ord,
40 BitAnd,
41 BitAndAssign,
42 BitOr,
43 BitOrAssign,
44 BitXor,
45 BitXorAssign,
46)]
47#[repr(transparent)]
48pub struct SmallU<const N: usize>(u8);
49
50impl<const N: usize> SmallU<N> {
51 const _CHECK_SIZE: () = {
52 assert!(N < 8);
53 };
54
55 pub const ONES: Self = Self((1u8 << N) - 1);
57
58 #[inline(always)]
59 pub const fn new(val: u8) -> Self {
60 Self(val & Self::ONES.0)
61 }
62
63 #[inline(always)]
64 pub const fn new_unchecked(val: u8) -> Self {
65 Self(val)
66 }
67
68 #[inline(always)]
69 pub const fn val(&self) -> u8 {
70 self.0
71 }
72}
73
74impl<const N: usize> Debug for SmallU<N> {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 Debug::fmt(&self.val(), f)
77 }
78}
79
80impl<const N: usize> Display for SmallU<N> {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 Display::fmt(&self.val(), f)
83 }
84}
85
86impl<const N: usize> LowerHex for SmallU<N> {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 LowerHex::fmt(&self.0, f)
89 }
90}
91impl<const N: usize> Hash for SmallU<N> {
92 #[inline]
93 fn hash<H: Hasher>(&self, state: &mut H) {
94 self.val().hash(state);
95 }
96}
97
98impl<const N: usize> Distribution<SmallU<N>> for StandardUniform {
99 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SmallU<N> {
100 SmallU(rng.random_range(0..1u8 << N))
101 }
102}
103
104impl<const N: usize> Shr<usize> for SmallU<N> {
105 type Output = Self;
106
107 #[inline(always)]
108 fn shr(self, rhs: usize) -> Self::Output {
109 Self(self.val() >> rhs)
110 }
111}
112
113impl<const N: usize> Shl<usize> for SmallU<N> {
114 type Output = Self;
115
116 #[inline(always)]
117 fn shl(self, rhs: usize) -> Self::Output {
118 Self(self.val() << rhs) & Self::ONES
119 }
120}
121
122impl<const N: usize> Not for SmallU<N> {
123 type Output = Self;
124
125 fn not(self) -> Self::Output {
126 self ^ Self::ONES
127 }
128}
129
130unsafe impl<const N: usize> NoUninit for SmallU<N> {}
131
132impl Underlier for U1 {
133 const LOG_BITS: usize = checked_log_2(1);
134
135 const ZERO: Self = Self(0);
136 const ONE: Self = Self(1);
137 const ONES: Self = Self(1);
138
139 fn interleave(self, _other: Self, _log_block_len: usize) -> (Self, Self) {
140 panic!("interleave not supported for U1")
141 }
142}
143
144impl Underlier for U2 {
145 const LOG_BITS: usize = checked_log_2(2);
146
147 const ZERO: Self = Self(0);
148 const ONE: Self = Self(1);
149 const ONES: Self = Self(0b11);
150
151 fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
152 const MASKS: &[U2] = &[U2::new(interleave_mask_even!(u8, 0))];
153 interleave_with_mask(self, other, log_block_len, MASKS)
154 }
155}
156
157impl Underlier for U4 {
158 const LOG_BITS: usize = checked_log_2(4);
159
160 const ZERO: Self = Self(0);
161 const ONE: Self = Self(1);
162 const ONES: Self = Self(0b1111);
163
164 fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
165 const MASKS: &[U4] = &[
166 U4::new(interleave_mask_even!(u8, 0)),
167 U4::new(interleave_mask_even!(u8, 1)),
168 ];
169 interleave_with_mask(self, other, log_block_len, MASKS)
170 }
171}
172
173impl<const N: usize> From<SmallU<N>> for u8 {
174 #[inline(always)]
175 fn from(value: SmallU<N>) -> Self {
176 value.val()
177 }
178}
179
180impl<const N: usize> From<SmallU<N>> for u16 {
181 #[inline(always)]
182 fn from(value: SmallU<N>) -> Self {
183 u8::from(value) as _
184 }
185}
186
187impl<const N: usize> From<SmallU<N>> for u32 {
188 #[inline(always)]
189 fn from(value: SmallU<N>) -> Self {
190 u8::from(value) as _
191 }
192}
193
194impl<const N: usize> From<SmallU<N>> for u64 {
195 #[inline(always)]
196 fn from(value: SmallU<N>) -> Self {
197 u8::from(value) as _
198 }
199}
200
201impl<const N: usize> From<SmallU<N>> for usize {
202 #[inline(always)]
203 fn from(value: SmallU<N>) -> Self {
204 u8::from(value) as _
205 }
206}
207
208impl<const N: usize> From<SmallU<N>> for u128 {
209 #[inline(always)]
210 fn from(value: SmallU<N>) -> Self {
211 u8::from(value) as _
212 }
213}
214
215impl From<SmallU<1>> for SmallU<2> {
216 #[inline(always)]
217 fn from(value: SmallU<1>) -> Self {
218 Self(value.val())
219 }
220}
221
222impl From<SmallU<1>> for SmallU<4> {
223 #[inline(always)]
224 fn from(value: SmallU<1>) -> Self {
225 Self(value.val())
226 }
227}
228
229impl From<SmallU<2>> for SmallU<4> {
230 #[inline(always)]
231 fn from(value: SmallU<2>) -> Self {
232 Self(value.val())
233 }
234}
235
236pub type U1 = SmallU<1>;
237pub type U2 = SmallU<2>;
238pub type U4 = SmallU<4>;
239
240impl From<bool> for U1 {
241 fn from(value: bool) -> Self {
242 Self::new_unchecked(value as u8)
243 }
244}
245
246impl From<U1> for bool {
247 fn from(value: U1) -> Self {
248 value == U1::ONE
249 }
250}
251
252impl<const N: usize> SerializeBytes for SmallU<N> {
253 fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
254 self.val().serialize(write_buf)
255 }
256}
257
258impl<const N: usize> DeserializeBytes for SmallU<N> {
259 fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError>
260 where
261 Self: Sized,
262 {
263 Ok(Self::new(DeserializeBytes::deserialize(read_buf)?))
264 }
265}
266
267impl<const N: usize> FixedSizeSerializeBytes for SmallU<N> {
268 const BYTE_SIZE: usize = 1;
269}
270
271pub mod bitmask {
276 use super::{Divisible, SmallU};
277
278 #[inline]
284 pub unsafe fn get<Big, const BITS: usize>(value: &Big, index: usize) -> SmallU<BITS>
285 where
286 Big: Divisible<u8>,
287 {
288 let elems_per_byte = 8 / BITS;
289 let byte_index = index / elems_per_byte;
290 let sub_index = index % elems_per_byte;
291 let byte = unsafe { Divisible::<u8>::get_unchecked(value, byte_index) };
293 let shift = sub_index * BITS;
294 SmallU::<BITS>::new(byte >> shift)
295 }
296
297 #[inline]
304 pub unsafe fn set<Big, const BITS: usize>(
305 mut value: Big,
306 index: usize,
307 val: SmallU<BITS>,
308 ) -> Big
309 where
310 Big: Divisible<u8>,
311 {
312 let elems_per_byte = 8 / BITS;
313 let byte_index = index / elems_per_byte;
314 let sub_index = index % elems_per_byte;
315 let byte = unsafe { Divisible::<u8>::get_unchecked(&value, byte_index) };
317 let shift = sub_index * BITS;
318 let mask = (1u8 << BITS) - 1;
319 let new_byte = (byte & !(mask << shift)) | (val.val() << shift);
320 unsafe { Divisible::<u8>::set_unchecked(&mut value, byte_index, new_byte) };
322 value
323 }
324}
325
326#[derive(Clone)]
331pub struct SmallUDivisIter<I, const N: usize> {
332 byte_iter: I,
333 current_byte: Option<u8>,
334 sub_idx: usize,
335}
336
337impl<I: Iterator<Item = u8>, const N: usize> SmallUDivisIter<I, N> {
338 const ELEMS_PER_BYTE: usize = 8 / N;
339
340 pub fn new(mut byte_iter: I) -> Self {
341 let current_byte = byte_iter.next();
342 Self {
343 byte_iter,
344 current_byte,
345 sub_idx: 0,
346 }
347 }
348}
349
350impl<I: ExactSizeIterator<Item = u8>, const N: usize> Iterator for SmallUDivisIter<I, N> {
351 type Item = SmallU<N>;
352
353 #[inline]
354 fn next(&mut self) -> Option<Self::Item> {
355 let byte = self.current_byte?;
356 let shift = self.sub_idx * N;
357 let result = SmallU::<N>::new(byte >> shift);
358
359 self.sub_idx += 1;
360 if self.sub_idx >= Self::ELEMS_PER_BYTE {
361 self.sub_idx = 0;
362 self.current_byte = self.byte_iter.next();
363 }
364
365 Some(result)
366 }
367
368 #[inline]
369 fn size_hint(&self) -> (usize, Option<usize>) {
370 let remaining_in_current = if self.current_byte.is_some() {
371 Self::ELEMS_PER_BYTE - self.sub_idx
372 } else {
373 0
374 };
375 let remaining_bytes = self.byte_iter.len();
376 let total = remaining_in_current + remaining_bytes * Self::ELEMS_PER_BYTE;
377 (total, Some(total))
378 }
379}
380
381impl<I: ExactSizeIterator<Item = u8>, const N: usize> ExactSizeIterator for SmallUDivisIter<I, N> {}
382
383macro_rules! impl_divisible_bitmask {
388 (u8, $($bits:expr),+) => {
390 $(
391 impl $crate::divisible::Divisible<$crate::underlier::SmallU<$bits>> for u8 {
392 const LOG_N: usize = (8usize / $bits).ilog2() as usize;
393
394 #[inline]
395 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone {
396 $crate::underlier::SmallUDivisIter::new(std::iter::once(value))
397 }
398
399 #[inline]
400 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
401 $crate::underlier::SmallUDivisIter::new(std::iter::once(*value))
402 }
403
404 #[inline]
405 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
406 $crate::underlier::SmallUDivisIter::new(slice.iter().copied())
407 }
408
409 #[inline]
410 unsafe fn get_unchecked(&self, index: usize) -> $crate::underlier::SmallU<$bits> {
411 let shift = index * $bits;
412 $crate::underlier::SmallU::<$bits>::new(*self >> shift)
413 }
414
415 #[inline]
416 unsafe fn set_unchecked(&mut self, index: usize, val: $crate::underlier::SmallU<$bits>) {
417 let shift = index * $bits;
418 let mask = (1u8 << $bits) - 1;
419 *self = (*self & !(mask << shift)) | (val.val() << shift);
420 }
421
422 #[inline]
423 fn broadcast(val: $crate::underlier::SmallU<$bits>) -> Self {
424 if $bits == 1 {
425 val.val().wrapping_neg()
427 } else {
428 let mut result = val.val();
429 let mut current_bits = $bits;
431 while current_bits < 8 {
432 result |= result << current_bits;
433 current_bits *= 2;
434 }
435 result
436 }
437 }
438
439 #[inline]
440 fn from_iter(iter: impl Iterator<Item = $crate::underlier::SmallU<$bits>>) -> Self {
441 const N: usize = 8 / $bits;
442 let mut result: Self = 0;
443 for (i, val) in iter.take(N).enumerate() {
444 $crate::divisible::Divisible::<$crate::underlier::SmallU<$bits>>::set(&mut result, i, val);
445 }
446 result
447 }
448 }
449 )+
450 };
451
452 ($big:ty, $($bits:expr),+) => {
454 $(
455 impl $crate::divisible::Divisible<$crate::underlier::SmallU<$bits>> for $big {
456 const LOG_N: usize = (8 * size_of::<$big>() / $bits).ilog2() as usize;
457
458 #[inline]
459 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone {
460 $crate::underlier::SmallUDivisIter::new(
461 $crate::divisible::Divisible::<u8>::value_iter(value)
462 )
463 }
464
465 #[inline]
466 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
467 $crate::underlier::SmallUDivisIter::new(
468 $crate::divisible::Divisible::<u8>::ref_iter(value)
469 )
470 }
471
472 #[inline]
473 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
474 $crate::underlier::SmallUDivisIter::new(
475 $crate::divisible::Divisible::<u8>::slice_iter(slice)
476 )
477 }
478
479 #[inline]
480 unsafe fn get_unchecked(&self, index: usize) -> $crate::underlier::SmallU<$bits> {
481 unsafe { $crate::underlier::bitmask::get::<Self, $bits>(self, index) }
483 }
484
485 #[inline]
486 unsafe fn set_unchecked(&mut self, index: usize, val: $crate::underlier::SmallU<$bits>) {
487 *self = unsafe { $crate::underlier::bitmask::set::<Self, $bits>(*self, index, val) };
489 }
490
491 #[inline]
492 fn broadcast(val: $crate::underlier::SmallU<$bits>) -> Self {
493 let byte = $crate::divisible::Divisible::<$crate::underlier::SmallU<$bits>>::broadcast(val);
495 $crate::divisible::Divisible::<u8>::broadcast(byte)
496 }
497
498 #[inline]
499 fn from_iter(iter: impl Iterator<Item = $crate::underlier::SmallU<$bits>>) -> Self {
500 const N: usize = 8 * size_of::<$big>() / $bits;
501 let mut result: Self = bytemuck::Zeroable::zeroed();
502 for (i, val) in iter.take(N).enumerate() {
503 $crate::divisible::Divisible::<$crate::underlier::SmallU<$bits>>::set(&mut result, i, val);
504 }
505 result
506 }
507 }
508 )+
509 };
510}
511
512#[allow(unused)]
513pub(crate) use impl_divisible_bitmask;
514
515impl_divisible_bitmask!(u8, 1, 2, 4);
517impl_divisible_bitmask!(u16, 1, 2, 4);
518impl_divisible_bitmask!(u32, 1, 2, 4);
519impl_divisible_bitmask!(u64, 1, 2, 4);
520impl_divisible_bitmask!(u128, 1, 2, 4);
521
522impl_divisible_self!(SmallU<1>, SmallU<2>, SmallU<4>);
523
524impl Divisible<SmallU<1>> for SmallU<2> {
526 const LOG_N: usize = 1;
527
528 #[inline]
529 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone {
530 mapget::value_iter(value)
531 }
532
533 #[inline]
534 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
535 mapget::value_iter(*value)
536 }
537
538 #[inline]
539 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
540 mapget::slice_iter(slice)
541 }
542
543 #[inline]
544 unsafe fn get_unchecked(&self, index: usize) -> SmallU<1> {
545 SmallU::<1>::new(self.val() >> index)
546 }
547
548 #[inline]
549 unsafe fn set_unchecked(&mut self, index: usize, val: SmallU<1>) {
550 let mask = 1u8 << index;
551 *self = SmallU::<2>::new((self.val() & !mask) | (val.val() << index));
552 }
553
554 #[inline]
555 fn broadcast(val: SmallU<1>) -> Self {
556 let v = val.val();
558 SmallU::<2>::new(v | (v << 1))
559 }
560
561 #[inline]
562 fn from_iter(iter: impl Iterator<Item = SmallU<1>>) -> Self {
563 iter.chain(std::iter::repeat(SmallU::<1>::new(0)))
564 .take(2)
565 .enumerate()
566 .fold(SmallU::<2>::new(0), |mut acc, (i, val)| {
567 acc.set(i, val);
568 acc
569 })
570 }
571}
572
573impl Divisible<SmallU<1>> for SmallU<4> {
574 const LOG_N: usize = 2;
575
576 #[inline]
577 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone {
578 mapget::value_iter(value)
579 }
580
581 #[inline]
582 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
583 mapget::value_iter(*value)
584 }
585
586 #[inline]
587 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
588 mapget::slice_iter(slice)
589 }
590
591 #[inline]
592 unsafe fn get_unchecked(&self, index: usize) -> SmallU<1> {
593 SmallU::<1>::new(self.val() >> index)
594 }
595
596 #[inline]
597 unsafe fn set_unchecked(&mut self, index: usize, val: SmallU<1>) {
598 let mask = 1u8 << index;
599 *self = SmallU::<4>::new((self.val() & !mask) | (val.val() << index));
600 }
601
602 #[inline]
603 fn broadcast(val: SmallU<1>) -> Self {
604 let mut v = val.val();
606 v |= v << 1;
607 v |= v << 2;
608 SmallU::<4>::new(v)
609 }
610
611 #[inline]
612 fn from_iter(iter: impl Iterator<Item = SmallU<1>>) -> Self {
613 iter.chain(std::iter::repeat(SmallU::<1>::new(0)))
614 .take(4)
615 .enumerate()
616 .fold(SmallU::<4>::new(0), |mut acc, (i, val)| {
617 acc.set(i, val);
618 acc
619 })
620 }
621}
622
623impl Divisible<SmallU<2>> for SmallU<4> {
624 const LOG_N: usize = 1;
625
626 #[inline]
627 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone {
628 mapget::value_iter(value)
629 }
630
631 #[inline]
632 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone + '_ {
633 mapget::value_iter(*value)
634 }
635
636 #[inline]
637 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone + '_ {
638 mapget::slice_iter(slice)
639 }
640
641 #[inline]
642 unsafe fn get_unchecked(&self, index: usize) -> SmallU<2> {
643 SmallU::<2>::new(self.val() >> (index * 2))
644 }
645
646 #[inline]
647 unsafe fn set_unchecked(&mut self, index: usize, val: SmallU<2>) {
648 let shift = index * 2;
649 let mask = 0b11u8 << shift;
650 *self = SmallU::<4>::new((self.val() & !mask) | (val.val() << shift));
651 }
652
653 #[inline]
654 fn broadcast(val: SmallU<2>) -> Self {
655 let v = val.val();
657 SmallU::<4>::new(v | (v << 2))
658 }
659
660 #[inline]
661 fn from_iter(iter: impl Iterator<Item = SmallU<2>>) -> Self {
662 iter.chain(std::iter::repeat(SmallU::<2>::new(0)))
663 .take(2)
664 .enumerate()
665 .fold(SmallU::<4>::new(0), |mut acc, (i, val)| {
666 acc.set(i, val);
667 acc
668 })
669 }
670}
671
672#[cfg(test)]
673impl<const N: usize> proptest::arbitrary::Arbitrary for SmallU<N> {
674 type Parameters = ();
675 type Strategy = proptest::strategy::BoxedStrategy<Self>;
676
677 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
678 use proptest::strategy::Strategy;
679
680 (0u8..(1u8 << N)).prop_map(Self::new_unchecked).boxed()
681 }
682}
683
684#[cfg(test)]
685mod tests {
686 use proptest::{arbitrary::any, proptest};
687
688 use super::*;
689
690 #[test]
691 fn test_divisible_u8_u4() {
692 let val: u8 = 0x34;
693
694 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(0x4));
696 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(0x3));
697
698 let mut modified = val;
700 Divisible::<U4>::set(&mut modified, 0, U4::new(0xF));
701 assert_eq!(modified, 0x3F);
702 let mut modified = val;
703 Divisible::<U4>::set(&mut modified, 1, U4::new(0xA));
704 assert_eq!(modified, 0xA4);
705
706 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
708 assert_eq!(parts.len(), 2);
709 assert_eq!(parts[0], U4::new(0x4));
710 assert_eq!(parts[1], U4::new(0x3));
711
712 let parts: Vec<U4> = Divisible::<U4>::value_iter(val).collect();
714 assert_eq!(parts.len(), 2);
715 assert_eq!(parts[0], U4::new(0x4));
716 assert_eq!(parts[1], U4::new(0x3));
717
718 let vals = [0x34u8, 0x56u8];
720 let parts: Vec<U4> = Divisible::<U4>::slice_iter(&vals).collect();
721 assert_eq!(parts.len(), 4);
722 assert_eq!(parts[0], U4::new(0x4));
723 assert_eq!(parts[1], U4::new(0x3));
724 assert_eq!(parts[2], U4::new(0x6));
725 assert_eq!(parts[3], U4::new(0x5));
726 }
727
728 #[test]
729 fn test_divisible_u16_u4() {
730 let val: u16 = 0x1234;
731
732 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(0x4));
734 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(0x3));
735 assert_eq!(Divisible::<U4>::get(&val, 2), U4::new(0x2));
736 assert_eq!(Divisible::<U4>::get(&val, 3), U4::new(0x1));
737
738 let mut modified = val;
740 Divisible::<U4>::set(&mut modified, 1, U4::new(0xF));
741 assert_eq!(modified, 0x12F4);
742
743 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
745 assert_eq!(parts.len(), 4);
746 assert_eq!(parts[0], U4::new(0x4));
747 assert_eq!(parts[3], U4::new(0x1));
748 }
749
750 #[test]
751 fn test_divisible_u16_u2() {
752 let val: u16 = 0b1011001011010011;
754
755 assert_eq!(Divisible::<U2>::get(&val, 0), U2::new(0b11)); assert_eq!(Divisible::<U2>::get(&val, 1), U2::new(0b00)); assert_eq!(Divisible::<U2>::get(&val, 7), U2::new(0b10)); let parts: Vec<U2> = Divisible::<U2>::ref_iter(&val).collect();
762 assert_eq!(parts.len(), 8);
763 assert_eq!(parts[0], U2::new(0b11));
764 assert_eq!(parts[7], U2::new(0b10));
765 }
766
767 #[test]
768 fn test_divisible_u16_u1() {
769 let val: u16 = 0b1010110000110101;
771
772 assert_eq!(Divisible::<U1>::get(&val, 0), U1::new(1)); assert_eq!(Divisible::<U1>::get(&val, 1), U1::new(0)); assert_eq!(Divisible::<U1>::get(&val, 15), U1::new(1)); let mut modified = val;
779 Divisible::<U1>::set(&mut modified, 0, U1::new(0));
780 assert_eq!(modified, 0b1010110000110100);
781
782 let parts: Vec<U1> = Divisible::<U1>::ref_iter(&val).collect();
784 assert_eq!(parts.len(), 16);
785 assert_eq!(parts[0], U1::new(1));
786 assert_eq!(parts[15], U1::new(1));
787 }
788
789 #[test]
790 fn test_divisible_u64_u4() {
791 let val: u64 = 0x123456789ABCDEF0;
792
793 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(0x0));
795 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(0xF));
796 assert_eq!(Divisible::<U4>::get(&val, 15), U4::new(0x1));
797
798 assert_eq!(Divisible::<U4>::ref_iter(&val).count(), 16);
800 }
801
802 #[test]
803 fn test_broadcast_u8_u4() {
804 let result: u8 = Divisible::<U4>::broadcast(U4::new(0x5));
805 assert_eq!(result, 0x55);
806 }
807
808 #[test]
809 fn test_broadcast_u16_u4() {
810 let result: u16 = Divisible::<U4>::broadcast(U4::new(0xA));
811 assert_eq!(result, 0xAAAA);
812 }
813
814 #[test]
815 fn test_broadcast_u8_u2() {
816 let result: u8 = Divisible::<U2>::broadcast(U2::new(0b11));
817 assert_eq!(result, 0xFF);
818 let result: u8 = Divisible::<U2>::broadcast(U2::new(0b01));
819 assert_eq!(result, 0x55);
820 }
821
822 #[test]
823 fn test_broadcast_u8_u1() {
824 let result: u8 = Divisible::<U1>::broadcast(U1::new(0));
825 assert_eq!(result, 0x00);
826 let result: u8 = Divisible::<U1>::broadcast(U1::new(1));
827 assert_eq!(result, 0xFF);
828 }
829
830 #[test]
831 fn test_broadcast_smallu2_from_smallu1() {
832 let result: SmallU<2> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(0));
833 assert_eq!(result.val(), 0b00);
834 let result: SmallU<2> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(1));
835 assert_eq!(result.val(), 0b11);
836 }
837
838 #[test]
839 fn test_broadcast_smallu4_from_smallu1() {
840 let result: SmallU<4> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(0));
841 assert_eq!(result.val(), 0b0000);
842 let result: SmallU<4> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(1));
843 assert_eq!(result.val(), 0b1111);
844 }
845
846 #[test]
847 fn test_broadcast_smallu4_from_smallu2() {
848 let result: SmallU<4> = Divisible::<SmallU<2>>::broadcast(SmallU::<2>::new(0b10));
849 assert_eq!(result.val(), 0b1010);
850 }
851
852 #[test]
853 fn test_from_iter_smallu() {
854 let result: u8 = Divisible::<U4>::from_iter([U4::new(0xA), U4::new(0xB)].into_iter());
855 assert_eq!(result, 0xBA);
856 }
857
858 #[test]
859 fn test_divisible_u32_smallu() {
860 let val = 0xab12cd34u32;
861
862 assert_eq!(Divisible::<U1>::get(&val, 0), U1::new(0));
863 assert_eq!(Divisible::<U1>::get(&val, 1), U1::new(0));
864 assert_eq!(Divisible::<U1>::get(&val, 2), U1::new(1));
865 assert_eq!(Divisible::<U1>::get(&val, 31), U1::new(1));
866
867 assert_eq!(Divisible::<U2>::get(&val, 0), U2::new(0));
868 assert_eq!(Divisible::<U2>::get(&val, 1), U2::new(1));
869 assert_eq!(Divisible::<U2>::get(&val, 2), U2::new(3));
870 assert_eq!(Divisible::<U2>::get(&val, 15), U2::new(2));
871
872 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(4));
873 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(3));
874 assert_eq!(Divisible::<U4>::get(&val, 2), U4::new(13));
875 assert_eq!(Divisible::<U4>::get(&val, 7), U4::new(10));
876 }
877
878 proptest! {
879 #[test]
880 fn test_set_get_u32_u1(mut val in any::<u32>(), i in 0usize..32, elem in any::<U1>()) {
881 Divisible::<U1>::set(&mut val, i, elem);
882 assert_eq!(Divisible::<U1>::get(&val, i), elem);
883 }
884
885 #[test]
886 fn test_set_get_u32_u2(mut val in any::<u32>(), i in 0usize..16, elem in any::<U2>()) {
887 Divisible::<U2>::set(&mut val, i, elem);
888 assert_eq!(Divisible::<U2>::get(&val, i), elem);
889 }
890
891 #[test]
892 fn test_set_get_u32_u4(mut val in any::<u32>(), i in 0usize..8, elem in any::<U4>()) {
893 Divisible::<U4>::set(&mut val, i, elem);
894 assert_eq!(Divisible::<U4>::get(&val, i), elem);
895 }
896 }
897}