1use std::mem::size_of;
4
5pub trait Divisible<T>: Copy {
23 const LOG_N: usize;
25
26 const N: usize = 1 << Self::LOG_N;
28
29 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = T> + Send + Clone;
31
32 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = T> + Send + Clone + '_;
34
35 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = T> + Send + Clone + '_;
37
38 fn get(self, index: usize) -> T;
44
45 fn set(self, index: usize, val: T) -> Self;
51
52 fn broadcast(val: T) -> Self;
54
55 fn from_iter(iter: impl Iterator<Item = T>) -> Self;
60}
61
62pub mod memcast {
66 use bytemuck::{Pod, Zeroable};
67
68 #[cfg(target_endian = "little")]
70 #[inline]
71 pub fn value_iter<Big, Small, const N: usize>(
72 value: Big,
73 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone
74 where
75 Big: Pod,
76 Small: Pod + Send,
77 {
78 bytemuck::must_cast::<Big, [Small; N]>(value).into_iter()
79 }
80
81 #[cfg(target_endian = "big")]
83 #[inline]
84 pub fn value_iter<Big, Small, const N: usize>(
85 value: Big,
86 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone
87 where
88 Big: Pod,
89 Small: Pod + Send,
90 {
91 bytemuck::must_cast::<Big, [Small; N]>(value)
92 .into_iter()
93 .rev()
94 }
95
96 #[cfg(target_endian = "little")]
98 #[inline]
99 pub fn ref_iter<Big, Small, const N: usize>(
100 value: &Big,
101 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
102 where
103 Big: Pod,
104 Small: Pod + Send + Sync,
105 {
106 bytemuck::must_cast_ref::<Big, [Small; N]>(value)
107 .iter()
108 .copied()
109 }
110
111 #[cfg(target_endian = "big")]
113 #[inline]
114 pub fn ref_iter<Big, Small, const N: usize>(
115 value: &Big,
116 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
117 where
118 Big: Pod,
119 Small: Pod + Send + Sync,
120 {
121 bytemuck::must_cast_ref::<Big, [Small; N]>(value)
122 .iter()
123 .rev()
124 .copied()
125 }
126
127 #[cfg(target_endian = "little")]
129 #[inline]
130 pub fn slice_iter<Big, Small>(
131 slice: &[Big],
132 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
133 where
134 Big: Pod,
135 Small: Pod + Send + Sync,
136 {
137 bytemuck::must_cast_slice::<Big, Small>(slice)
138 .iter()
139 .copied()
140 }
141
142 #[cfg(target_endian = "big")]
147 #[inline]
148 pub fn slice_iter<Big, Small, const LOG_N: usize>(
149 slice: &[Big],
150 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
151 where
152 Big: Pod,
153 Small: Pod + Send + Sync,
154 {
155 const N: usize = 1 << LOG_N;
156 let raw_slice = bytemuck::must_cast_slice::<Big, Small>(slice);
157 (0..raw_slice.len()).map(move |i| {
158 let element_idx = i >> LOG_N;
159 let sub_idx = i & (N - 1);
160 let reversed_sub_idx = N - 1 - sub_idx;
161 let raw_idx = element_idx * N + reversed_sub_idx;
162 raw_slice[raw_idx]
163 })
164 }
165
166 #[cfg(target_endian = "little")]
168 #[inline]
169 pub fn get<Big, Small, const N: usize>(value: &Big, index: usize) -> Small
170 where
171 Big: Pod,
172 Small: Pod,
173 {
174 bytemuck::must_cast_ref::<Big, [Small; N]>(value)[index]
175 }
176
177 #[cfg(target_endian = "big")]
179 #[inline]
180 pub fn get<Big, Small, const N: usize>(value: &Big, index: usize) -> Small
181 where
182 Big: Pod,
183 Small: Pod,
184 {
185 bytemuck::must_cast_ref::<Big, [Small; N]>(value)[N - 1 - index]
186 }
187
188 #[cfg(target_endian = "little")]
190 #[inline]
191 pub fn set<Big, Small, const N: usize>(value: &Big, index: usize, val: Small) -> Big
192 where
193 Big: Pod,
194 Small: Pod,
195 {
196 let mut arr = *bytemuck::must_cast_ref::<Big, [Small; N]>(value);
197 arr[index] = val;
198 bytemuck::must_cast(arr)
199 }
200
201 #[cfg(target_endian = "big")]
203 #[inline]
204 pub fn set<Big, Small, const N: usize>(value: &Big, index: usize, val: Small) -> Big
205 where
206 Big: Pod,
207 Small: Pod,
208 {
209 let mut arr = *bytemuck::must_cast_ref::<Big, [Small; N]>(value);
210 arr[N - 1 - index] = val;
211 bytemuck::must_cast(arr)
212 }
213
214 #[inline]
216 pub fn broadcast<Big, Small, const N: usize>(val: Small) -> Big
217 where
218 Big: Pod,
219 Small: Pod + Copy,
220 {
221 bytemuck::must_cast::<[Small; N], Big>([val; N])
222 }
223
224 #[cfg(target_endian = "little")]
226 #[inline]
227 pub fn from_iter<Big, Small, const N: usize>(iter: impl Iterator<Item = Small>) -> Big
228 where
229 Big: Pod,
230 Small: Pod,
231 {
232 let mut arr: [Small; N] = Zeroable::zeroed();
233 for (i, val) in iter.take(N).enumerate() {
234 arr[i] = val;
235 }
236 bytemuck::must_cast(arr)
237 }
238
239 #[cfg(target_endian = "big")]
241 #[inline]
242 pub fn from_iter<Big, Small, const N: usize>(iter: impl Iterator<Item = Small>) -> Big
243 where
244 Big: Pod,
245 Small: Pod,
246 {
247 let mut arr: [Small; N] = Zeroable::zeroed();
248 for (i, val) in iter.take(N).enumerate() {
249 arr[N - 1 - i] = val;
250 }
251 bytemuck::must_cast(arr)
252 }
253}
254
255pub mod bitmask {
260 use super::{Divisible, SmallU};
261
262 #[inline]
264 pub fn get<Big, const BITS: usize>(value: Big, index: usize) -> SmallU<BITS>
265 where
266 Big: Divisible<u8>,
267 {
268 let elems_per_byte = 8 / BITS;
269 let byte_index = index / elems_per_byte;
270 let sub_index = index % elems_per_byte;
271 let byte = Divisible::<u8>::get(value, byte_index);
272 let shift = sub_index * BITS;
273 SmallU::<BITS>::new(byte >> shift)
274 }
275
276 #[inline]
278 pub fn set<Big, const BITS: usize>(value: Big, index: usize, val: SmallU<BITS>) -> Big
279 where
280 Big: Divisible<u8>,
281 {
282 let elems_per_byte = 8 / BITS;
283 let byte_index = index / elems_per_byte;
284 let sub_index = index % elems_per_byte;
285 let byte = Divisible::<u8>::get(value, byte_index);
286 let shift = sub_index * BITS;
287 let mask = (1u8 << BITS) - 1;
288 let new_byte = (byte & !(mask << shift)) | (val.val() << shift);
289 Divisible::<u8>::set(value, byte_index, new_byte)
290 }
291}
292
293pub mod mapget {
298 use binius_utils::iter::IterExtensions;
299
300 use super::Divisible;
301
302 #[inline]
304 pub fn value_iter<Big, Small>(value: Big) -> impl ExactSizeIterator<Item = Small> + Send + Clone
305 where
306 Big: Divisible<Small> + Send,
307 Small: Send,
308 {
309 (0..Big::N).map_skippable(move |i| Divisible::<Small>::get(value, i))
310 }
311
312 #[inline]
314 pub fn slice_iter<Big, Small>(
315 slice: &[Big],
316 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
317 where
318 Big: Divisible<Small> + Send + Sync,
319 Small: Send,
320 {
321 let total = slice.len() * Big::N;
322 (0..total).map_skippable(move |global_idx| {
323 let elem_idx = global_idx / Big::N;
324 let sub_idx = global_idx % Big::N;
325 Divisible::<Small>::get(slice[elem_idx], sub_idx)
326 })
327 }
328}
329
330#[derive(Clone)]
335pub struct SmallUDivisIter<I, const N: usize> {
336 byte_iter: I,
337 current_byte: Option<u8>,
338 sub_idx: usize,
339}
340
341impl<I: Iterator<Item = u8>, const N: usize> SmallUDivisIter<I, N> {
342 const ELEMS_PER_BYTE: usize = 8 / N;
343
344 pub fn new(mut byte_iter: I) -> Self {
345 let current_byte = byte_iter.next();
346 Self {
347 byte_iter,
348 current_byte,
349 sub_idx: 0,
350 }
351 }
352}
353
354impl<I: ExactSizeIterator<Item = u8>, const N: usize> Iterator for SmallUDivisIter<I, N> {
355 type Item = SmallU<N>;
356
357 #[inline]
358 fn next(&mut self) -> Option<Self::Item> {
359 let byte = self.current_byte?;
360 let shift = self.sub_idx * N;
361 let result = SmallU::<N>::new(byte >> shift);
362
363 self.sub_idx += 1;
364 if self.sub_idx >= Self::ELEMS_PER_BYTE {
365 self.sub_idx = 0;
366 self.current_byte = self.byte_iter.next();
367 }
368
369 Some(result)
370 }
371
372 #[inline]
373 fn size_hint(&self) -> (usize, Option<usize>) {
374 let remaining_in_current = if self.current_byte.is_some() {
375 Self::ELEMS_PER_BYTE - self.sub_idx
376 } else {
377 0
378 };
379 let remaining_bytes = self.byte_iter.len();
380 let total = remaining_in_current + remaining_bytes * Self::ELEMS_PER_BYTE;
381 (total, Some(total))
382 }
383}
384
385impl<I: ExactSizeIterator<Item = u8>, const N: usize> ExactSizeIterator for SmallUDivisIter<I, N> {}
386
387macro_rules! impl_divisible_memcast {
392 ($big:ty, $($small:ty),+) => {
393 $(
394 impl $crate::underlier::Divisible<$small> for $big {
395 const LOG_N: usize = (size_of::<$big>() / size_of::<$small>()).ilog2() as usize;
396
397 #[inline]
398 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $small> + Send + Clone {
399 const N: usize = size_of::<$big>() / size_of::<$small>();
400 $crate::underlier::memcast::value_iter::<$big, $small, N>(value)
401 }
402
403 #[inline]
404 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $small> + Send + Clone + '_ {
405 const N: usize = size_of::<$big>() / size_of::<$small>();
406 $crate::underlier::memcast::ref_iter::<$big, $small, N>(value)
407 }
408
409 #[inline]
410 #[cfg(target_endian = "little")]
411 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $small> + Send + Clone + '_ {
412 $crate::underlier::memcast::slice_iter::<$big, $small>(slice)
413 }
414
415 #[inline]
416 #[cfg(target_endian = "big")]
417 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $small> + Send + Clone + '_ {
418 const LOG_N: usize = (size_of::<$big>() / size_of::<$small>()).ilog2() as usize;
419 $crate::underlier::memcast::slice_iter::<$big, $small, LOG_N>(slice)
420 }
421
422 #[inline]
423 fn get(self, index: usize) -> $small {
424 const N: usize = size_of::<$big>() / size_of::<$small>();
425 $crate::underlier::memcast::get::<$big, $small, N>(&self, index)
426 }
427
428 #[inline]
429 fn set(self, index: usize, val: $small) -> Self {
430 const N: usize = size_of::<$big>() / size_of::<$small>();
431 $crate::underlier::memcast::set::<$big, $small, N>(&self, index, val)
432 }
433
434 #[inline]
435 fn broadcast(val: $small) -> Self {
436 const N: usize = size_of::<$big>() / size_of::<$small>();
437 $crate::underlier::memcast::broadcast::<$big, $small, N>(val)
438 }
439
440 #[inline]
441 fn from_iter(iter: impl Iterator<Item = $small>) -> Self {
442 const N: usize = size_of::<$big>() / size_of::<$small>();
443 $crate::underlier::memcast::from_iter::<$big, $small, N>(iter)
444 }
445 }
446 )+
447 };
448}
449
450#[allow(unused)]
451pub(crate) use impl_divisible_memcast;
452
453macro_rules! impl_divisible_bitmask {
458 (u8, $($bits:expr),+) => {
460 $(
461 impl $crate::underlier::Divisible<$crate::underlier::SmallU<$bits>> for u8 {
462 const LOG_N: usize = (8usize / $bits).ilog2() as usize;
463
464 #[inline]
465 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone {
466 $crate::underlier::SmallUDivisIter::new(std::iter::once(value))
467 }
468
469 #[inline]
470 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
471 $crate::underlier::SmallUDivisIter::new(std::iter::once(*value))
472 }
473
474 #[inline]
475 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
476 $crate::underlier::SmallUDivisIter::new(slice.iter().copied())
477 }
478
479 #[inline]
480 fn get(self, index: usize) -> $crate::underlier::SmallU<$bits> {
481 let shift = index * $bits;
482 $crate::underlier::SmallU::<$bits>::new(self >> shift)
483 }
484
485 #[inline]
486 fn set(self, index: usize, val: $crate::underlier::SmallU<$bits>) -> Self {
487 let shift = index * $bits;
488 let mask = (1u8 << $bits) - 1;
489 (self & !(mask << shift)) | (val.val() << shift)
490 }
491
492 #[inline]
493 fn broadcast(val: $crate::underlier::SmallU<$bits>) -> Self {
494 if $bits == 1 {
495 val.val().wrapping_neg()
497 } else {
498 let mut result = val.val();
499 let mut current_bits = $bits;
501 while current_bits < 8 {
502 result |= result << current_bits;
503 current_bits *= 2;
504 }
505 result
506 }
507 }
508
509 #[inline]
510 fn from_iter(iter: impl Iterator<Item = $crate::underlier::SmallU<$bits>>) -> Self {
511 const N: usize = 8 / $bits;
512 let mut result: Self = 0;
513 for (i, val) in iter.take(N).enumerate() {
514 result = $crate::underlier::Divisible::<$crate::underlier::SmallU<$bits>>::set(result, i, val);
515 }
516 result
517 }
518 }
519 )+
520 };
521
522 ($big:ty, $($bits:expr),+) => {
524 $(
525 impl $crate::underlier::Divisible<$crate::underlier::SmallU<$bits>> for $big {
526 const LOG_N: usize = (8 * size_of::<$big>() / $bits).ilog2() as usize;
527
528 #[inline]
529 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone {
530 $crate::underlier::SmallUDivisIter::new(
531 $crate::underlier::Divisible::<u8>::value_iter(value)
532 )
533 }
534
535 #[inline]
536 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
537 $crate::underlier::SmallUDivisIter::new(
538 $crate::underlier::Divisible::<u8>::ref_iter(value)
539 )
540 }
541
542 #[inline]
543 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
544 $crate::underlier::SmallUDivisIter::new(
545 $crate::underlier::Divisible::<u8>::slice_iter(slice)
546 )
547 }
548
549 #[inline]
550 fn get(self, index: usize) -> $crate::underlier::SmallU<$bits> {
551 $crate::underlier::bitmask::get::<Self, $bits>(self, index)
552 }
553
554 #[inline]
555 fn set(self, index: usize, val: $crate::underlier::SmallU<$bits>) -> Self {
556 $crate::underlier::bitmask::set::<Self, $bits>(self, index, val)
557 }
558
559 #[inline]
560 fn broadcast(val: $crate::underlier::SmallU<$bits>) -> Self {
561 let byte = $crate::underlier::Divisible::<$crate::underlier::SmallU<$bits>>::broadcast(val);
563 $crate::underlier::Divisible::<u8>::broadcast(byte)
564 }
565
566 #[inline]
567 fn from_iter(iter: impl Iterator<Item = $crate::underlier::SmallU<$bits>>) -> Self {
568 const N: usize = 8 * size_of::<$big>() / $bits;
569 let mut result: Self = bytemuck::Zeroable::zeroed();
570 for (i, val) in iter.take(N).enumerate() {
571 result = $crate::underlier::Divisible::<$crate::underlier::SmallU<$bits>>::set(result, i, val);
572 }
573 result
574 }
575 }
576 )+
577 };
578}
579
580#[allow(unused)]
581pub(crate) use impl_divisible_bitmask;
582
583use super::small_uint::SmallU;
584
585impl_divisible_memcast!(u128, u64, u32, u16, u8);
587impl_divisible_memcast!(u64, u32, u16, u8);
588impl_divisible_memcast!(u32, u16, u8);
589impl_divisible_memcast!(u16, u8);
590
591impl_divisible_bitmask!(u8, 1, 2, 4);
593impl_divisible_bitmask!(u16, 1, 2, 4);
594impl_divisible_bitmask!(u32, 1, 2, 4);
595impl_divisible_bitmask!(u64, 1, 2, 4);
596impl_divisible_bitmask!(u128, 1, 2, 4);
597
598impl Divisible<SmallU<1>> for SmallU<2> {
600 const LOG_N: usize = 1;
601
602 #[inline]
603 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone {
604 mapget::value_iter(value)
605 }
606
607 #[inline]
608 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
609 mapget::value_iter(*value)
610 }
611
612 #[inline]
613 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
614 mapget::slice_iter(slice)
615 }
616
617 #[inline]
618 fn get(self, index: usize) -> SmallU<1> {
619 SmallU::<1>::new(self.val() >> index)
620 }
621
622 #[inline]
623 fn set(self, index: usize, val: SmallU<1>) -> Self {
624 let mask = 1u8 << index;
625 SmallU::<2>::new((self.val() & !mask) | (val.val() << index))
626 }
627
628 #[inline]
629 fn broadcast(val: SmallU<1>) -> Self {
630 let v = val.val();
632 SmallU::<2>::new(v | (v << 1))
633 }
634
635 #[inline]
636 fn from_iter(iter: impl Iterator<Item = SmallU<1>>) -> Self {
637 iter.chain(std::iter::repeat(SmallU::<1>::new(0)))
638 .take(2)
639 .enumerate()
640 .fold(SmallU::<2>::new(0), |acc, (i, val)| acc.set(i, val))
641 }
642}
643
644impl Divisible<SmallU<1>> for SmallU<4> {
645 const LOG_N: usize = 2;
646
647 #[inline]
648 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone {
649 mapget::value_iter(value)
650 }
651
652 #[inline]
653 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
654 mapget::value_iter(*value)
655 }
656
657 #[inline]
658 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
659 mapget::slice_iter(slice)
660 }
661
662 #[inline]
663 fn get(self, index: usize) -> SmallU<1> {
664 SmallU::<1>::new(self.val() >> index)
665 }
666
667 #[inline]
668 fn set(self, index: usize, val: SmallU<1>) -> Self {
669 let mask = 1u8 << index;
670 SmallU::<4>::new((self.val() & !mask) | (val.val() << index))
671 }
672
673 #[inline]
674 fn broadcast(val: SmallU<1>) -> Self {
675 let mut v = val.val();
677 v |= v << 1;
678 v |= v << 2;
679 SmallU::<4>::new(v)
680 }
681
682 #[inline]
683 fn from_iter(iter: impl Iterator<Item = SmallU<1>>) -> Self {
684 iter.chain(std::iter::repeat(SmallU::<1>::new(0)))
685 .take(4)
686 .enumerate()
687 .fold(SmallU::<4>::new(0), |acc, (i, val)| acc.set(i, val))
688 }
689}
690
691impl Divisible<SmallU<2>> for SmallU<4> {
692 const LOG_N: usize = 1;
693
694 #[inline]
695 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone {
696 mapget::value_iter(value)
697 }
698
699 #[inline]
700 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone + '_ {
701 mapget::value_iter(*value)
702 }
703
704 #[inline]
705 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone + '_ {
706 mapget::slice_iter(slice)
707 }
708
709 #[inline]
710 fn get(self, index: usize) -> SmallU<2> {
711 SmallU::<2>::new(self.val() >> (index * 2))
712 }
713
714 #[inline]
715 fn set(self, index: usize, val: SmallU<2>) -> Self {
716 let shift = index * 2;
717 let mask = 0b11u8 << shift;
718 SmallU::<4>::new((self.val() & !mask) | (val.val() << shift))
719 }
720
721 #[inline]
722 fn broadcast(val: SmallU<2>) -> Self {
723 let v = val.val();
725 SmallU::<4>::new(v | (v << 2))
726 }
727
728 #[inline]
729 fn from_iter(iter: impl Iterator<Item = SmallU<2>>) -> Self {
730 iter.chain(std::iter::repeat(SmallU::<2>::new(0)))
731 .take(2)
732 .enumerate()
733 .fold(SmallU::<4>::new(0), |acc, (i, val)| acc.set(i, val))
734 }
735}
736
737macro_rules! impl_divisible_self {
739 ($($ty:ty),+) => {
740 $(
741 impl Divisible<$ty> for $ty {
742 const LOG_N: usize = 0;
743
744 #[inline]
745 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $ty> + Send + Clone {
746 std::iter::once(value)
747 }
748
749 #[inline]
750 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $ty> + Send + Clone + '_ {
751 std::iter::once(*value)
752 }
753
754 #[inline]
755 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $ty> + Send + Clone + '_ {
756 slice.iter().copied()
757 }
758
759 #[inline]
760 fn get(self, index: usize) -> $ty {
761 debug_assert_eq!(index, 0);
762 self
763 }
764
765 #[inline]
766 fn set(self, index: usize, val: $ty) -> Self {
767 debug_assert_eq!(index, 0);
768 val
769 }
770
771 #[inline]
772 fn broadcast(val: $ty) -> Self {
773 val
774 }
775
776 #[inline]
777 fn from_iter(mut iter: impl Iterator<Item = $ty>) -> Self {
778 iter.next().unwrap_or_else(bytemuck::Zeroable::zeroed)
779 }
780 }
781 )+
782 };
783}
784
785impl_divisible_self!(u8, u16, u32, u64, u128, SmallU<1>, SmallU<2>, SmallU<4>);
786
787#[cfg(test)]
788mod tests {
789 use super::*;
790 use crate::underlier::small_uint::{U1, U2, U4};
791
792 #[test]
793 fn test_divisible_u8_u4() {
794 let val: u8 = 0x34;
795
796 assert_eq!(Divisible::<U4>::get(val, 0), U4::new(0x4));
798 assert_eq!(Divisible::<U4>::get(val, 1), U4::new(0x3));
799
800 let modified = Divisible::<U4>::set(val, 0, U4::new(0xF));
802 assert_eq!(modified, 0x3F);
803 let modified = Divisible::<U4>::set(val, 1, U4::new(0xA));
804 assert_eq!(modified, 0xA4);
805
806 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
808 assert_eq!(parts.len(), 2);
809 assert_eq!(parts[0], U4::new(0x4));
810 assert_eq!(parts[1], U4::new(0x3));
811
812 let parts: Vec<U4> = Divisible::<U4>::value_iter(val).collect();
814 assert_eq!(parts.len(), 2);
815 assert_eq!(parts[0], U4::new(0x4));
816 assert_eq!(parts[1], U4::new(0x3));
817
818 let vals = [0x34u8, 0x56u8];
820 let parts: Vec<U4> = Divisible::<U4>::slice_iter(&vals).collect();
821 assert_eq!(parts.len(), 4);
822 assert_eq!(parts[0], U4::new(0x4));
823 assert_eq!(parts[1], U4::new(0x3));
824 assert_eq!(parts[2], U4::new(0x6));
825 assert_eq!(parts[3], U4::new(0x5));
826 }
827
828 #[test]
829 fn test_divisible_u16_u4() {
830 let val: u16 = 0x1234;
831
832 assert_eq!(Divisible::<U4>::get(val, 0), U4::new(0x4));
834 assert_eq!(Divisible::<U4>::get(val, 1), U4::new(0x3));
835 assert_eq!(Divisible::<U4>::get(val, 2), U4::new(0x2));
836 assert_eq!(Divisible::<U4>::get(val, 3), U4::new(0x1));
837
838 let modified = Divisible::<U4>::set(val, 1, U4::new(0xF));
840 assert_eq!(modified, 0x12F4);
841
842 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
844 assert_eq!(parts.len(), 4);
845 assert_eq!(parts[0], U4::new(0x4));
846 assert_eq!(parts[3], U4::new(0x1));
847 }
848
849 #[test]
850 fn test_divisible_u16_u2() {
851 let val: u16 = 0b1011001011010011;
853
854 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();
861 assert_eq!(parts.len(), 8);
862 assert_eq!(parts[0], U2::new(0b11));
863 assert_eq!(parts[7], U2::new(0b10));
864 }
865
866 #[test]
867 fn test_divisible_u16_u1() {
868 let val: u16 = 0b1010110000110101;
870
871 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 modified = Divisible::<U1>::set(val, 0, U1::new(0));
878 assert_eq!(modified, 0b1010110000110100);
879
880 let parts: Vec<U1> = Divisible::<U1>::ref_iter(&val).collect();
882 assert_eq!(parts.len(), 16);
883 assert_eq!(parts[0], U1::new(1));
884 assert_eq!(parts[15], U1::new(1));
885 }
886
887 #[test]
888 fn test_divisible_u64_u4() {
889 let val: u64 = 0x123456789ABCDEF0;
890
891 assert_eq!(Divisible::<U4>::get(val, 0), U4::new(0x0));
893 assert_eq!(Divisible::<U4>::get(val, 1), U4::new(0xF));
894 assert_eq!(Divisible::<U4>::get(val, 15), U4::new(0x1));
895
896 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
898 assert_eq!(parts.len(), 16);
899 }
900
901 #[test]
902 fn test_divisible_u32_u8_slice() {
903 let vals: [u32; 2] = [0x04030201, 0x08070605];
904
905 let parts: Vec<u8> = Divisible::<u8>::slice_iter(&vals).collect();
907 assert_eq!(parts.len(), 8);
908 assert_eq!(parts[0], 0x01);
910 assert_eq!(parts[1], 0x02);
911 assert_eq!(parts[2], 0x03);
912 assert_eq!(parts[3], 0x04);
913 assert_eq!(parts[4], 0x05);
914 assert_eq!(parts[5], 0x06);
915 assert_eq!(parts[6], 0x07);
916 assert_eq!(parts[7], 0x08);
917 }
918
919 #[test]
920 fn test_broadcast_u32_u8() {
921 let result: u32 = Divisible::<u8>::broadcast(0xAB);
922 assert_eq!(result, 0xABABABAB);
923 }
924
925 #[test]
926 fn test_broadcast_u64_u16() {
927 let result: u64 = Divisible::<u16>::broadcast(0x1234);
928 assert_eq!(result, 0x1234123412341234);
929 }
930
931 #[test]
932 fn test_broadcast_u128_u32() {
933 let result: u128 = Divisible::<u32>::broadcast(0xDEADBEEF);
934 assert_eq!(result, 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF);
935 }
936
937 #[test]
938 fn test_broadcast_u8_u4() {
939 let result: u8 = Divisible::<U4>::broadcast(U4::new(0x5));
940 assert_eq!(result, 0x55);
941 }
942
943 #[test]
944 fn test_broadcast_u16_u4() {
945 let result: u16 = Divisible::<U4>::broadcast(U4::new(0xA));
946 assert_eq!(result, 0xAAAA);
947 }
948
949 #[test]
950 fn test_broadcast_u8_u2() {
951 let result: u8 = Divisible::<U2>::broadcast(U2::new(0b11));
952 assert_eq!(result, 0xFF);
953 let result: u8 = Divisible::<U2>::broadcast(U2::new(0b01));
954 assert_eq!(result, 0x55);
955 }
956
957 #[test]
958 fn test_broadcast_u8_u1() {
959 let result: u8 = Divisible::<U1>::broadcast(U1::new(0));
960 assert_eq!(result, 0x00);
961 let result: u8 = Divisible::<U1>::broadcast(U1::new(1));
962 assert_eq!(result, 0xFF);
963 }
964
965 #[test]
966 fn test_broadcast_smallu2_from_smallu1() {
967 let result: SmallU<2> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(0));
968 assert_eq!(result.val(), 0b00);
969 let result: SmallU<2> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(1));
970 assert_eq!(result.val(), 0b11);
971 }
972
973 #[test]
974 fn test_broadcast_smallu4_from_smallu1() {
975 let result: SmallU<4> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(0));
976 assert_eq!(result.val(), 0b0000);
977 let result: SmallU<4> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(1));
978 assert_eq!(result.val(), 0b1111);
979 }
980
981 #[test]
982 fn test_broadcast_smallu4_from_smallu2() {
983 let result: SmallU<4> = Divisible::<SmallU<2>>::broadcast(SmallU::<2>::new(0b10));
984 assert_eq!(result.val(), 0b1010);
985 }
986
987 #[test]
988 fn test_broadcast_reflexive() {
989 let result: u64 = Divisible::<u64>::broadcast(0x123456789ABCDEF0);
990 assert_eq!(result, 0x123456789ABCDEF0);
991 }
992
993 #[test]
994 fn test_from_iter_full() {
995 let result: u32 = Divisible::<u8>::from_iter([0x01, 0x02, 0x03, 0x04].into_iter());
996 assert_eq!(result, 0x04030201);
997 }
998
999 #[test]
1000 fn test_from_iter_partial() {
1001 let result: u32 = Divisible::<u8>::from_iter([0xAB, 0xCD].into_iter());
1003 assert_eq!(result, 0x0000CDAB);
1004 }
1005
1006 #[test]
1007 fn test_from_iter_empty() {
1008 let result: u32 = Divisible::<u8>::from_iter(std::iter::empty());
1009 assert_eq!(result, 0);
1010 }
1011
1012 #[test]
1013 fn test_from_iter_excess() {
1014 let result: u32 =
1016 Divisible::<u8>::from_iter([0x01, 0x02, 0x03, 0x04, 0x05, 0x06].into_iter());
1017 assert_eq!(result, 0x04030201);
1018 }
1019
1020 #[test]
1021 fn test_from_iter_u64_u16() {
1022 let result: u64 = Divisible::<u16>::from_iter([0x1234, 0x5678, 0x9ABC].into_iter());
1023 assert_eq!(result, 0x0000_9ABC_5678_1234);
1025 }
1026
1027 #[test]
1028 fn test_from_iter_smallu() {
1029 let result: u8 = Divisible::<U4>::from_iter([U4::new(0xA), U4::new(0xB)].into_iter());
1030 assert_eq!(result, 0xBA);
1031 }
1032}