1use std::mem::size_of;
5
6pub trait Divisible<T>: Sized {
24 const LOG_N: usize;
26
27 const N: usize = 1 << Self::LOG_N;
29
30 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = T> + Send + Clone;
32
33 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = T> + Send + Clone + '_;
35
36 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = T> + Send + Clone + '_;
38
39 #[inline]
45 fn get(&self, index: usize) -> T {
46 assert!(index < Self::N, "index {index} out of bounds (N = {})", Self::N);
47 unsafe { self.get_unchecked(index) }
49 }
50
51 #[inline]
57 fn set(&mut self, index: usize, val: T) {
58 assert!(index < Self::N, "index {index} out of bounds (N = {})", Self::N);
59 unsafe { self.set_unchecked(index, val) };
61 }
62
63 unsafe fn get_unchecked(&self, index: usize) -> T;
69
70 unsafe fn set_unchecked(&mut self, index: usize, val: T);
76
77 fn broadcast(val: T) -> Self;
79
80 fn from_iter(iter: impl Iterator<Item = T>) -> Self;
85}
86
87pub mod memcast {
91 use bytemuck::{Pod, Zeroable};
92
93 #[cfg(target_endian = "little")]
95 #[inline]
96 pub fn value_iter<Big, Small, const N: usize>(
97 value: Big,
98 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone
99 where
100 Big: Pod,
101 Small: Pod + Send,
102 {
103 bytemuck::must_cast::<Big, [Small; N]>(value).into_iter()
104 }
105
106 #[cfg(target_endian = "big")]
108 #[inline]
109 pub fn value_iter<Big, Small, const N: usize>(
110 value: Big,
111 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone
112 where
113 Big: Pod,
114 Small: Pod + Send,
115 {
116 bytemuck::must_cast::<Big, [Small; N]>(value)
117 .into_iter()
118 .rev()
119 }
120
121 #[cfg(target_endian = "little")]
123 #[inline]
124 pub fn ref_iter<Big, Small, const N: usize>(
125 value: &Big,
126 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
127 where
128 Big: Pod,
129 Small: Pod + Send + Sync,
130 {
131 bytemuck::must_cast_ref::<Big, [Small; N]>(value)
132 .iter()
133 .copied()
134 }
135
136 #[cfg(target_endian = "big")]
138 #[inline]
139 pub fn ref_iter<Big, Small, const N: usize>(
140 value: &Big,
141 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
142 where
143 Big: Pod,
144 Small: Pod + Send + Sync,
145 {
146 bytemuck::must_cast_ref::<Big, [Small; N]>(value)
147 .iter()
148 .rev()
149 .copied()
150 }
151
152 #[cfg(target_endian = "little")]
154 #[inline]
155 pub fn slice_iter<Big, Small>(
156 slice: &[Big],
157 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
158 where
159 Big: Pod,
160 Small: Pod + Send + Sync,
161 {
162 bytemuck::must_cast_slice::<Big, Small>(slice)
163 .iter()
164 .copied()
165 }
166
167 #[cfg(target_endian = "big")]
172 #[inline]
173 pub fn slice_iter<Big, Small, const LOG_N: usize>(
174 slice: &[Big],
175 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
176 where
177 Big: Pod,
178 Small: Pod + Send + Sync,
179 {
180 const N: usize = 1 << LOG_N;
181 let raw_slice = bytemuck::must_cast_slice::<Big, Small>(slice);
182 (0..raw_slice.len()).map(move |i| {
183 let element_idx = i >> LOG_N;
184 let sub_idx = i & (N - 1);
185 let reversed_sub_idx = N - 1 - sub_idx;
186 let raw_idx = element_idx * N + reversed_sub_idx;
187 raw_slice[raw_idx]
188 })
189 }
190
191 #[cfg(target_endian = "little")]
197 #[inline]
198 pub unsafe fn get<Big, Small, const N: usize>(value: &Big, index: usize) -> Small
199 where
200 Big: Pod,
201 Small: Pod,
202 {
203 unsafe { *bytemuck::must_cast_ref::<Big, [Small; N]>(value).get_unchecked(index) }
205 }
206
207 #[cfg(target_endian = "big")]
213 #[inline]
214 pub unsafe fn get<Big, Small, const N: usize>(value: &Big, index: usize) -> Small
215 where
216 Big: Pod,
217 Small: Pod,
218 {
219 unsafe { *bytemuck::must_cast_ref::<Big, [Small; N]>(value).get_unchecked(N - 1 - index) }
221 }
222
223 #[cfg(target_endian = "little")]
230 #[inline]
231 pub unsafe fn set<Big, Small, const N: usize>(value: &Big, index: usize, val: Small) -> Big
232 where
233 Big: Pod,
234 Small: Pod,
235 {
236 let mut arr = *bytemuck::must_cast_ref::<Big, [Small; N]>(value);
237 unsafe {
239 *arr.get_unchecked_mut(index) = val;
240 }
241 bytemuck::must_cast(arr)
242 }
243
244 #[cfg(target_endian = "big")]
251 #[inline]
252 pub unsafe fn set<Big, Small, const N: usize>(value: &Big, index: usize, val: Small) -> Big
253 where
254 Big: Pod,
255 Small: Pod,
256 {
257 let mut arr = *bytemuck::must_cast_ref::<Big, [Small; N]>(value);
258 unsafe {
260 *arr.get_unchecked_mut(N - 1 - index) = val;
261 }
262 bytemuck::must_cast(arr)
263 }
264
265 #[inline]
267 pub fn broadcast<Big, Small, const N: usize>(val: Small) -> Big
268 where
269 Big: Pod,
270 Small: Pod + Copy,
271 {
272 bytemuck::must_cast::<[Small; N], Big>([val; N])
273 }
274
275 #[cfg(target_endian = "little")]
277 #[inline]
278 pub fn from_iter<Big, Small, const N: usize>(iter: impl Iterator<Item = Small>) -> Big
279 where
280 Big: Pod,
281 Small: Pod,
282 {
283 let mut arr: [Small; N] = Zeroable::zeroed();
284 for (i, val) in iter.take(N).enumerate() {
285 arr[i] = val;
286 }
287 bytemuck::must_cast(arr)
288 }
289
290 #[cfg(target_endian = "big")]
292 #[inline]
293 pub fn from_iter<Big, Small, const N: usize>(iter: impl Iterator<Item = Small>) -> Big
294 where
295 Big: Pod,
296 Small: Pod,
297 {
298 let mut arr: [Small; N] = Zeroable::zeroed();
299 for (i, val) in iter.take(N).enumerate() {
300 arr[N - 1 - i] = val;
301 }
302 bytemuck::must_cast(arr)
303 }
304}
305
306pub mod bitmask {
311 use super::{Divisible, SmallU};
312
313 #[inline]
319 pub unsafe fn get<Big, const BITS: usize>(value: Big, index: usize) -> SmallU<BITS>
320 where
321 Big: Divisible<u8>,
322 {
323 let elems_per_byte = 8 / BITS;
324 let byte_index = index / elems_per_byte;
325 let sub_index = index % elems_per_byte;
326 let byte = unsafe { Divisible::<u8>::get_unchecked(&value, byte_index) };
328 let shift = sub_index * BITS;
329 SmallU::<BITS>::new(byte >> shift)
330 }
331
332 #[inline]
339 pub unsafe fn set<Big, const BITS: usize>(
340 mut value: Big,
341 index: usize,
342 val: SmallU<BITS>,
343 ) -> Big
344 where
345 Big: Divisible<u8>,
346 {
347 let elems_per_byte = 8 / BITS;
348 let byte_index = index / elems_per_byte;
349 let sub_index = index % elems_per_byte;
350 let byte = unsafe { Divisible::<u8>::get_unchecked(&value, byte_index) };
352 let shift = sub_index * BITS;
353 let mask = (1u8 << BITS) - 1;
354 let new_byte = (byte & !(mask << shift)) | (val.val() << shift);
355 unsafe { Divisible::<u8>::set_unchecked(&mut value, byte_index, new_byte) };
357 value
358 }
359}
360
361pub mod mapget {
366 use binius_utils::iter::IterExtensions;
367
368 use super::Divisible;
369
370 #[inline]
372 pub fn value_iter<Big, Small>(value: Big) -> impl ExactSizeIterator<Item = Small> + Send + Clone
373 where
374 Big: Divisible<Small> + Send + Clone,
375 Small: Send,
376 {
377 (0..Big::N).map_skippable(move |i| Divisible::<Small>::get(&value, i))
378 }
379
380 #[inline]
382 pub fn slice_iter<Big, Small>(
383 slice: &[Big],
384 ) -> impl ExactSizeIterator<Item = Small> + Send + Clone + '_
385 where
386 Big: Divisible<Small> + Send + Sync,
387 Small: Send,
388 {
389 let total = slice.len() * Big::N;
390 (0..total).map_skippable(move |global_idx| {
391 let elem_idx = global_idx / Big::N;
392 let sub_idx = global_idx % Big::N;
393 Divisible::<Small>::get(&slice[elem_idx], sub_idx)
394 })
395 }
396}
397
398#[derive(Clone)]
403pub struct SmallUDivisIter<I, const N: usize> {
404 byte_iter: I,
405 current_byte: Option<u8>,
406 sub_idx: usize,
407}
408
409impl<I: Iterator<Item = u8>, const N: usize> SmallUDivisIter<I, N> {
410 const ELEMS_PER_BYTE: usize = 8 / N;
411
412 pub fn new(mut byte_iter: I) -> Self {
413 let current_byte = byte_iter.next();
414 Self {
415 byte_iter,
416 current_byte,
417 sub_idx: 0,
418 }
419 }
420}
421
422impl<I: ExactSizeIterator<Item = u8>, const N: usize> Iterator for SmallUDivisIter<I, N> {
423 type Item = SmallU<N>;
424
425 #[inline]
426 fn next(&mut self) -> Option<Self::Item> {
427 let byte = self.current_byte?;
428 let shift = self.sub_idx * N;
429 let result = SmallU::<N>::new(byte >> shift);
430
431 self.sub_idx += 1;
432 if self.sub_idx >= Self::ELEMS_PER_BYTE {
433 self.sub_idx = 0;
434 self.current_byte = self.byte_iter.next();
435 }
436
437 Some(result)
438 }
439
440 #[inline]
441 fn size_hint(&self) -> (usize, Option<usize>) {
442 let remaining_in_current = if self.current_byte.is_some() {
443 Self::ELEMS_PER_BYTE - self.sub_idx
444 } else {
445 0
446 };
447 let remaining_bytes = self.byte_iter.len();
448 let total = remaining_in_current + remaining_bytes * Self::ELEMS_PER_BYTE;
449 (total, Some(total))
450 }
451}
452
453impl<I: ExactSizeIterator<Item = u8>, const N: usize> ExactSizeIterator for SmallUDivisIter<I, N> {}
454
455macro_rules! impl_divisible_memcast {
460 ($big:ty, $($small:ty),+) => {
461 $(
462 impl $crate::underlier::Divisible<$small> for $big {
463 const LOG_N: usize = (size_of::<$big>() / size_of::<$small>()).ilog2() as usize;
464
465 #[inline]
466 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $small> + Send + Clone {
467 const N: usize = size_of::<$big>() / size_of::<$small>();
468 $crate::underlier::memcast::value_iter::<$big, $small, N>(value)
469 }
470
471 #[inline]
472 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $small> + Send + Clone + '_ {
473 const N: usize = size_of::<$big>() / size_of::<$small>();
474 $crate::underlier::memcast::ref_iter::<$big, $small, N>(value)
475 }
476
477 #[inline]
478 #[cfg(target_endian = "little")]
479 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $small> + Send + Clone + '_ {
480 $crate::underlier::memcast::slice_iter::<$big, $small>(slice)
481 }
482
483 #[inline]
484 #[cfg(target_endian = "big")]
485 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $small> + Send + Clone + '_ {
486 const LOG_N: usize = (size_of::<$big>() / size_of::<$small>()).ilog2() as usize;
487 $crate::underlier::memcast::slice_iter::<$big, $small, LOG_N>(slice)
488 }
489
490 #[inline]
491 unsafe fn get_unchecked(&self, index: usize) -> $small {
492 const N: usize = size_of::<$big>() / size_of::<$small>();
493 unsafe { $crate::underlier::memcast::get::<$big, $small, N>(self, index) }
495 }
496
497 #[inline]
498 unsafe fn set_unchecked(&mut self, index: usize, val: $small) {
499 const N: usize = size_of::<$big>() / size_of::<$small>();
500 *self = unsafe { $crate::underlier::memcast::set::<$big, $small, N>(&*self, index, val) };
502 }
503
504 #[inline]
505 fn broadcast(val: $small) -> Self {
506 const N: usize = size_of::<$big>() / size_of::<$small>();
507 $crate::underlier::memcast::broadcast::<$big, $small, N>(val)
508 }
509
510 #[inline]
511 fn from_iter(iter: impl Iterator<Item = $small>) -> Self {
512 const N: usize = size_of::<$big>() / size_of::<$small>();
513 $crate::underlier::memcast::from_iter::<$big, $small, N>(iter)
514 }
515 }
516 )+
517 };
518}
519
520#[allow(unused)]
521pub(crate) use impl_divisible_memcast;
522
523macro_rules! impl_divisible_bitmask {
528 (u8, $($bits:expr),+) => {
530 $(
531 impl $crate::underlier::Divisible<$crate::underlier::SmallU<$bits>> for u8 {
532 const LOG_N: usize = (8usize / $bits).ilog2() as usize;
533
534 #[inline]
535 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone {
536 $crate::underlier::SmallUDivisIter::new(std::iter::once(value))
537 }
538
539 #[inline]
540 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
541 $crate::underlier::SmallUDivisIter::new(std::iter::once(*value))
542 }
543
544 #[inline]
545 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
546 $crate::underlier::SmallUDivisIter::new(slice.iter().copied())
547 }
548
549 #[inline]
550 unsafe fn get_unchecked(&self, index: usize) -> $crate::underlier::SmallU<$bits> {
551 let shift = index * $bits;
552 $crate::underlier::SmallU::<$bits>::new(*self >> shift)
553 }
554
555 #[inline]
556 unsafe fn set_unchecked(&mut self, index: usize, val: $crate::underlier::SmallU<$bits>) {
557 let shift = index * $bits;
558 let mask = (1u8 << $bits) - 1;
559 *self = (*self & !(mask << shift)) | (val.val() << shift);
560 }
561
562 #[inline]
563 fn broadcast(val: $crate::underlier::SmallU<$bits>) -> Self {
564 if $bits == 1 {
565 val.val().wrapping_neg()
567 } else {
568 let mut result = val.val();
569 let mut current_bits = $bits;
571 while current_bits < 8 {
572 result |= result << current_bits;
573 current_bits *= 2;
574 }
575 result
576 }
577 }
578
579 #[inline]
580 fn from_iter(iter: impl Iterator<Item = $crate::underlier::SmallU<$bits>>) -> Self {
581 const N: usize = 8 / $bits;
582 let mut result: Self = 0;
583 for (i, val) in iter.take(N).enumerate() {
584 $crate::underlier::Divisible::<$crate::underlier::SmallU<$bits>>::set(&mut result, i, val);
585 }
586 result
587 }
588 }
589 )+
590 };
591
592 ($big:ty, $($bits:expr),+) => {
594 $(
595 impl $crate::underlier::Divisible<$crate::underlier::SmallU<$bits>> for $big {
596 const LOG_N: usize = (8 * size_of::<$big>() / $bits).ilog2() as usize;
597
598 #[inline]
599 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone {
600 $crate::underlier::SmallUDivisIter::new(
601 $crate::underlier::Divisible::<u8>::value_iter(value)
602 )
603 }
604
605 #[inline]
606 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
607 $crate::underlier::SmallUDivisIter::new(
608 $crate::underlier::Divisible::<u8>::ref_iter(value)
609 )
610 }
611
612 #[inline]
613 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $crate::underlier::SmallU<$bits>> + Send + Clone + '_ {
614 $crate::underlier::SmallUDivisIter::new(
615 $crate::underlier::Divisible::<u8>::slice_iter(slice)
616 )
617 }
618
619 #[inline]
620 unsafe fn get_unchecked(&self, index: usize) -> $crate::underlier::SmallU<$bits> {
621 unsafe { $crate::underlier::bitmask::get::<Self, $bits>(*self, index) }
623 }
624
625 #[inline]
626 unsafe fn set_unchecked(&mut self, index: usize, val: $crate::underlier::SmallU<$bits>) {
627 *self = unsafe { $crate::underlier::bitmask::set::<Self, $bits>(*self, index, val) };
629 }
630
631 #[inline]
632 fn broadcast(val: $crate::underlier::SmallU<$bits>) -> Self {
633 let byte = $crate::underlier::Divisible::<$crate::underlier::SmallU<$bits>>::broadcast(val);
635 $crate::underlier::Divisible::<u8>::broadcast(byte)
636 }
637
638 #[inline]
639 fn from_iter(iter: impl Iterator<Item = $crate::underlier::SmallU<$bits>>) -> Self {
640 const N: usize = 8 * size_of::<$big>() / $bits;
641 let mut result: Self = bytemuck::Zeroable::zeroed();
642 for (i, val) in iter.take(N).enumerate() {
643 $crate::underlier::Divisible::<$crate::underlier::SmallU<$bits>>::set(&mut result, i, val);
644 }
645 result
646 }
647 }
648 )+
649 };
650}
651
652#[allow(unused)]
653pub(crate) use impl_divisible_bitmask;
654
655use super::small_uint::SmallU;
656
657impl_divisible_memcast!(u128, u64, u32, u16, u8);
659impl_divisible_memcast!(u64, u32, u16, u8);
660impl_divisible_memcast!(u32, u16, u8);
661impl_divisible_memcast!(u16, u8);
662
663impl_divisible_bitmask!(u8, 1, 2, 4);
665impl_divisible_bitmask!(u16, 1, 2, 4);
666impl_divisible_bitmask!(u32, 1, 2, 4);
667impl_divisible_bitmask!(u64, 1, 2, 4);
668impl_divisible_bitmask!(u128, 1, 2, 4);
669
670impl Divisible<SmallU<1>> for SmallU<2> {
672 const LOG_N: usize = 1;
673
674 #[inline]
675 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone {
676 mapget::value_iter(value)
677 }
678
679 #[inline]
680 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
681 mapget::value_iter(*value)
682 }
683
684 #[inline]
685 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
686 mapget::slice_iter(slice)
687 }
688
689 #[inline]
690 unsafe fn get_unchecked(&self, index: usize) -> SmallU<1> {
691 SmallU::<1>::new(self.val() >> index)
692 }
693
694 #[inline]
695 unsafe fn set_unchecked(&mut self, index: usize, val: SmallU<1>) {
696 let mask = 1u8 << index;
697 *self = SmallU::<2>::new((self.val() & !mask) | (val.val() << index));
698 }
699
700 #[inline]
701 fn broadcast(val: SmallU<1>) -> Self {
702 let v = val.val();
704 SmallU::<2>::new(v | (v << 1))
705 }
706
707 #[inline]
708 fn from_iter(iter: impl Iterator<Item = SmallU<1>>) -> Self {
709 iter.chain(std::iter::repeat(SmallU::<1>::new(0)))
710 .take(2)
711 .enumerate()
712 .fold(SmallU::<2>::new(0), |mut acc, (i, val)| {
713 acc.set(i, val);
714 acc
715 })
716 }
717}
718
719impl Divisible<SmallU<1>> for SmallU<4> {
720 const LOG_N: usize = 2;
721
722 #[inline]
723 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone {
724 mapget::value_iter(value)
725 }
726
727 #[inline]
728 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
729 mapget::value_iter(*value)
730 }
731
732 #[inline]
733 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<1>> + Send + Clone + '_ {
734 mapget::slice_iter(slice)
735 }
736
737 #[inline]
738 unsafe fn get_unchecked(&self, index: usize) -> SmallU<1> {
739 SmallU::<1>::new(self.val() >> index)
740 }
741
742 #[inline]
743 unsafe fn set_unchecked(&mut self, index: usize, val: SmallU<1>) {
744 let mask = 1u8 << index;
745 *self = SmallU::<4>::new((self.val() & !mask) | (val.val() << index));
746 }
747
748 #[inline]
749 fn broadcast(val: SmallU<1>) -> Self {
750 let mut v = val.val();
752 v |= v << 1;
753 v |= v << 2;
754 SmallU::<4>::new(v)
755 }
756
757 #[inline]
758 fn from_iter(iter: impl Iterator<Item = SmallU<1>>) -> Self {
759 iter.chain(std::iter::repeat(SmallU::<1>::new(0)))
760 .take(4)
761 .enumerate()
762 .fold(SmallU::<4>::new(0), |mut acc, (i, val)| {
763 acc.set(i, val);
764 acc
765 })
766 }
767}
768
769impl Divisible<SmallU<2>> for SmallU<4> {
770 const LOG_N: usize = 1;
771
772 #[inline]
773 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone {
774 mapget::value_iter(value)
775 }
776
777 #[inline]
778 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone + '_ {
779 mapget::value_iter(*value)
780 }
781
782 #[inline]
783 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = SmallU<2>> + Send + Clone + '_ {
784 mapget::slice_iter(slice)
785 }
786
787 #[inline]
788 unsafe fn get_unchecked(&self, index: usize) -> SmallU<2> {
789 SmallU::<2>::new(self.val() >> (index * 2))
790 }
791
792 #[inline]
793 unsafe fn set_unchecked(&mut self, index: usize, val: SmallU<2>) {
794 let shift = index * 2;
795 let mask = 0b11u8 << shift;
796 *self = SmallU::<4>::new((self.val() & !mask) | (val.val() << shift));
797 }
798
799 #[inline]
800 fn broadcast(val: SmallU<2>) -> Self {
801 let v = val.val();
803 SmallU::<4>::new(v | (v << 2))
804 }
805
806 #[inline]
807 fn from_iter(iter: impl Iterator<Item = SmallU<2>>) -> Self {
808 iter.chain(std::iter::repeat(SmallU::<2>::new(0)))
809 .take(2)
810 .enumerate()
811 .fold(SmallU::<4>::new(0), |mut acc, (i, val)| {
812 acc.set(i, val);
813 acc
814 })
815 }
816}
817
818macro_rules! impl_divisible_self {
820 ($($ty:ty),+) => {
821 $(
822 impl Divisible<$ty> for $ty {
823 const LOG_N: usize = 0;
824
825 #[inline]
826 fn value_iter(value: Self) -> impl ExactSizeIterator<Item = $ty> + Send + Clone {
827 std::iter::once(value)
828 }
829
830 #[inline]
831 fn ref_iter(value: &Self) -> impl ExactSizeIterator<Item = $ty> + Send + Clone + '_ {
832 std::iter::once(*value)
833 }
834
835 #[inline]
836 fn slice_iter(slice: &[Self]) -> impl ExactSizeIterator<Item = $ty> + Send + Clone + '_ {
837 slice.iter().copied()
838 }
839
840 #[inline]
841 unsafe fn get_unchecked(&self, _index: usize) -> $ty {
842 *self
843 }
844
845 #[inline]
846 unsafe fn set_unchecked(&mut self, _index: usize, val: $ty) {
847 *self = val;
848 }
849
850 #[inline]
851 fn broadcast(val: $ty) -> Self {
852 val
853 }
854
855 #[inline]
856 fn from_iter(mut iter: impl Iterator<Item = $ty>) -> Self {
857 iter.next().unwrap_or_else(bytemuck::Zeroable::zeroed)
858 }
859 }
860 )+
861 };
862}
863
864#[allow(unused)]
865pub(crate) use impl_divisible_self;
866
867impl_divisible_self!(u8, u16, u32, u64, u128, SmallU<1>, SmallU<2>, SmallU<4>);
868
869#[cfg(test)]
870mod tests {
871 use super::*;
872 use crate::underlier::small_uint::{U1, U2, U4};
873
874 #[test]
875 fn test_divisible_u8_u4() {
876 let val: u8 = 0x34;
877
878 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(0x4));
880 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(0x3));
881
882 let mut modified = val;
884 Divisible::<U4>::set(&mut modified, 0, U4::new(0xF));
885 assert_eq!(modified, 0x3F);
886 let mut modified = val;
887 Divisible::<U4>::set(&mut modified, 1, U4::new(0xA));
888 assert_eq!(modified, 0xA4);
889
890 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
892 assert_eq!(parts.len(), 2);
893 assert_eq!(parts[0], U4::new(0x4));
894 assert_eq!(parts[1], U4::new(0x3));
895
896 let parts: Vec<U4> = Divisible::<U4>::value_iter(val).collect();
898 assert_eq!(parts.len(), 2);
899 assert_eq!(parts[0], U4::new(0x4));
900 assert_eq!(parts[1], U4::new(0x3));
901
902 let vals = [0x34u8, 0x56u8];
904 let parts: Vec<U4> = Divisible::<U4>::slice_iter(&vals).collect();
905 assert_eq!(parts.len(), 4);
906 assert_eq!(parts[0], U4::new(0x4));
907 assert_eq!(parts[1], U4::new(0x3));
908 assert_eq!(parts[2], U4::new(0x6));
909 assert_eq!(parts[3], U4::new(0x5));
910 }
911
912 #[test]
913 fn test_divisible_u16_u4() {
914 let val: u16 = 0x1234;
915
916 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(0x4));
918 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(0x3));
919 assert_eq!(Divisible::<U4>::get(&val, 2), U4::new(0x2));
920 assert_eq!(Divisible::<U4>::get(&val, 3), U4::new(0x1));
921
922 let mut modified = val;
924 Divisible::<U4>::set(&mut modified, 1, U4::new(0xF));
925 assert_eq!(modified, 0x12F4);
926
927 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
929 assert_eq!(parts.len(), 4);
930 assert_eq!(parts[0], U4::new(0x4));
931 assert_eq!(parts[3], U4::new(0x1));
932 }
933
934 #[test]
935 fn test_divisible_u16_u2() {
936 let val: u16 = 0b1011001011010011;
938
939 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();
946 assert_eq!(parts.len(), 8);
947 assert_eq!(parts[0], U2::new(0b11));
948 assert_eq!(parts[7], U2::new(0b10));
949 }
950
951 #[test]
952 fn test_divisible_u16_u1() {
953 let val: u16 = 0b1010110000110101;
955
956 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;
963 Divisible::<U1>::set(&mut modified, 0, U1::new(0));
964 assert_eq!(modified, 0b1010110000110100);
965
966 let parts: Vec<U1> = Divisible::<U1>::ref_iter(&val).collect();
968 assert_eq!(parts.len(), 16);
969 assert_eq!(parts[0], U1::new(1));
970 assert_eq!(parts[15], U1::new(1));
971 }
972
973 #[test]
974 fn test_divisible_u64_u4() {
975 let val: u64 = 0x123456789ABCDEF0;
976
977 assert_eq!(Divisible::<U4>::get(&val, 0), U4::new(0x0));
979 assert_eq!(Divisible::<U4>::get(&val, 1), U4::new(0xF));
980 assert_eq!(Divisible::<U4>::get(&val, 15), U4::new(0x1));
981
982 let parts: Vec<U4> = Divisible::<U4>::ref_iter(&val).collect();
984 assert_eq!(parts.len(), 16);
985 }
986
987 #[test]
988 fn test_divisible_u32_u8_slice() {
989 let vals: [u32; 2] = [0x04030201, 0x08070605];
990
991 let parts: Vec<u8> = Divisible::<u8>::slice_iter(&vals).collect();
993 assert_eq!(parts.len(), 8);
994 assert_eq!(parts[0], 0x01);
996 assert_eq!(parts[1], 0x02);
997 assert_eq!(parts[2], 0x03);
998 assert_eq!(parts[3], 0x04);
999 assert_eq!(parts[4], 0x05);
1000 assert_eq!(parts[5], 0x06);
1001 assert_eq!(parts[6], 0x07);
1002 assert_eq!(parts[7], 0x08);
1003 }
1004
1005 #[test]
1006 fn test_broadcast_u32_u8() {
1007 let result: u32 = Divisible::<u8>::broadcast(0xAB);
1008 assert_eq!(result, 0xABABABAB);
1009 }
1010
1011 #[test]
1012 fn test_broadcast_u64_u16() {
1013 let result: u64 = Divisible::<u16>::broadcast(0x1234);
1014 assert_eq!(result, 0x1234123412341234);
1015 }
1016
1017 #[test]
1018 fn test_broadcast_u128_u32() {
1019 let result: u128 = Divisible::<u32>::broadcast(0xDEADBEEF);
1020 assert_eq!(result, 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF);
1021 }
1022
1023 #[test]
1024 fn test_broadcast_u8_u4() {
1025 let result: u8 = Divisible::<U4>::broadcast(U4::new(0x5));
1026 assert_eq!(result, 0x55);
1027 }
1028
1029 #[test]
1030 fn test_broadcast_u16_u4() {
1031 let result: u16 = Divisible::<U4>::broadcast(U4::new(0xA));
1032 assert_eq!(result, 0xAAAA);
1033 }
1034
1035 #[test]
1036 fn test_broadcast_u8_u2() {
1037 let result: u8 = Divisible::<U2>::broadcast(U2::new(0b11));
1038 assert_eq!(result, 0xFF);
1039 let result: u8 = Divisible::<U2>::broadcast(U2::new(0b01));
1040 assert_eq!(result, 0x55);
1041 }
1042
1043 #[test]
1044 fn test_broadcast_u8_u1() {
1045 let result: u8 = Divisible::<U1>::broadcast(U1::new(0));
1046 assert_eq!(result, 0x00);
1047 let result: u8 = Divisible::<U1>::broadcast(U1::new(1));
1048 assert_eq!(result, 0xFF);
1049 }
1050
1051 #[test]
1052 fn test_broadcast_smallu2_from_smallu1() {
1053 let result: SmallU<2> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(0));
1054 assert_eq!(result.val(), 0b00);
1055 let result: SmallU<2> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(1));
1056 assert_eq!(result.val(), 0b11);
1057 }
1058
1059 #[test]
1060 fn test_broadcast_smallu4_from_smallu1() {
1061 let result: SmallU<4> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(0));
1062 assert_eq!(result.val(), 0b0000);
1063 let result: SmallU<4> = Divisible::<SmallU<1>>::broadcast(SmallU::<1>::new(1));
1064 assert_eq!(result.val(), 0b1111);
1065 }
1066
1067 #[test]
1068 fn test_broadcast_smallu4_from_smallu2() {
1069 let result: SmallU<4> = Divisible::<SmallU<2>>::broadcast(SmallU::<2>::new(0b10));
1070 assert_eq!(result.val(), 0b1010);
1071 }
1072
1073 #[test]
1074 fn test_broadcast_reflexive() {
1075 let result: u64 = Divisible::<u64>::broadcast(0x123456789ABCDEF0);
1076 assert_eq!(result, 0x123456789ABCDEF0);
1077 }
1078
1079 #[test]
1080 fn test_from_iter_full() {
1081 let result: u32 = Divisible::<u8>::from_iter([0x01, 0x02, 0x03, 0x04].into_iter());
1082 assert_eq!(result, 0x04030201);
1083 }
1084
1085 #[test]
1086 fn test_from_iter_partial() {
1087 let result: u32 = Divisible::<u8>::from_iter([0xAB, 0xCD].into_iter());
1089 assert_eq!(result, 0x0000CDAB);
1090 }
1091
1092 #[test]
1093 fn test_from_iter_empty() {
1094 let result: u32 = Divisible::<u8>::from_iter(std::iter::empty());
1095 assert_eq!(result, 0);
1096 }
1097
1098 #[test]
1099 fn test_from_iter_excess() {
1100 let result: u32 =
1102 Divisible::<u8>::from_iter([0x01, 0x02, 0x03, 0x04, 0x05, 0x06].into_iter());
1103 assert_eq!(result, 0x04030201);
1104 }
1105
1106 #[test]
1107 fn test_from_iter_u64_u16() {
1108 let result: u64 = Divisible::<u16>::from_iter([0x1234, 0x5678, 0x9ABC].into_iter());
1109 assert_eq!(result, 0x0000_9ABC_5678_1234);
1111 }
1112
1113 #[test]
1114 fn test_from_iter_smallu() {
1115 let result: u8 = Divisible::<U4>::from_iter([U4::new(0xA), U4::new(0xB)].into_iter());
1116 assert_eq!(result, 0xBA);
1117 }
1118}