binius_field/underlier/
divisible.rs1use std::{
4 mem::{align_of, size_of},
5 slice::{self, from_raw_parts, from_raw_parts_mut},
6};
7
8#[allow(dead_code)]
16pub unsafe trait Divisible<U: UnderlierType>: UnderlierType {
17 const WIDTH: usize = {
18 assert!(size_of::<Self>().is_multiple_of(size_of::<U>()));
19 assert!(align_of::<Self>() >= align_of::<U>());
20 size_of::<Self>() / size_of::<U>()
21 };
22
23 type Array: IntoIterator<Item = U, IntoIter: Send + Clone>;
26
27 fn split_val(self) -> Self::Array;
28 fn split_ref(&self) -> &[U];
29 fn split_mut(&mut self) -> &mut [U];
30
31 fn split_slice(values: &[Self]) -> &[U] {
32 let ptr = values.as_ptr() as *const U;
33 unsafe { from_raw_parts(ptr, values.len() * Self::WIDTH) }
37 }
38
39 fn split_slice_mut(values: &mut [Self]) -> &mut [U] {
40 let ptr = values.as_mut_ptr() as *mut U;
41 unsafe { from_raw_parts_mut(ptr, values.len() * Self::WIDTH) }
45 }
46}
47
48unsafe impl<U: UnderlierType> Divisible<U> for U {
49 type Array = [U; 1];
50
51 fn split_val(self) -> Self::Array {
52 [self]
53 }
54
55 fn split_ref(&self) -> &[U] {
56 slice::from_ref(self)
57 }
58
59 fn split_mut(&mut self) -> &mut [U] {
60 slice::from_mut(self)
61 }
62}
63
64pub trait DivisIterable<T> {
82 type Iter<'a>: ExactSizeIterator<Item = &'a T>
83 where
84 Self: 'a,
85 T: 'a;
86
87 fn divide(&self) -> Self::Iter<'_>;
89}
90
91macro_rules! impl_divisible {
92 (@pairs $name:ty,?) => {};
93 (@pairs $bigger:ty, $smaller:ty) => {
94 unsafe impl $crate::underlier::Divisible<$smaller> for $bigger {
95 type Array = [$smaller; {size_of::<Self>() / size_of::<$smaller>()}];
96
97 fn split_val(self) -> Self::Array {
98 bytemuck::must_cast::<_, Self::Array>(self)
99 }
100
101 fn split_ref(&self) -> &[$smaller] {
102 bytemuck::must_cast_ref::<_, [$smaller;{(<$bigger>::BITS as usize / <$smaller>::BITS as usize ) }]>(self)
103 }
104
105 fn split_mut(&mut self) -> &mut [$smaller] {
106 bytemuck::must_cast_mut::<_, [$smaller;{(<$bigger>::BITS as usize / <$smaller>::BITS as usize ) }]>(self)
107 }
108 }
109
110 unsafe impl $crate::underlier::Divisible<$smaller> for $crate::underlier::ScaledUnderlier<$bigger, 2> {
111 type Array = [$smaller; {2 * size_of::<$bigger>() / size_of::<$smaller>()}];
112
113 fn split_val(self) -> Self::Array {
114 bytemuck::must_cast::<_, Self::Array>(self)
115 }
116
117 fn split_ref(&self) -> &[$smaller] {
118 bytemuck::must_cast_ref::<_, [$smaller;{(2 * <$bigger>::BITS as usize / <$smaller>::BITS as usize ) }]>(&self.0)
119 }
120
121 fn split_mut(&mut self) -> &mut [$smaller] {
122 bytemuck::must_cast_mut::<_, [$smaller;{(2 * <$bigger>::BITS as usize / <$smaller>::BITS as usize ) }]>(&mut self.0)
123 }
124 }
125
126 unsafe impl $crate::underlier::Divisible<$smaller> for $crate::underlier::ScaledUnderlier<$crate::underlier::ScaledUnderlier<$bigger, 2>, 2> {
127 type Array = [$smaller; {4 * size_of::<$bigger>() / size_of::<$smaller>()}];
128
129 fn split_val(self) -> Self::Array {
130 bytemuck::must_cast::<_, Self::Array>(self)
131 }
132
133 fn split_ref(&self) -> &[$smaller] {
134 bytemuck::must_cast_ref::<_, [$smaller;{(4 * <$bigger>::BITS as usize / <$smaller>::BITS as usize ) }]>(&self.0)
135 }
136
137 fn split_mut(&mut self) -> &mut [$smaller] {
138 bytemuck::must_cast_mut::<_, [$smaller;{(4 * <$bigger>::BITS as usize / <$smaller>::BITS as usize ) }]>(&mut self.0)
139 }
140 }
141
142 #[cfg(target_endian = "little")]
143 impl $crate::underlier::DivisIterable<$smaller> for $bigger {
144 type Iter<'a> = std::slice::Iter<'a, $smaller>;
145
146 #[inline]
147 fn divide(&self) -> Self::Iter<'_> {
148 const N: usize = size_of::<$bigger>() / size_of::<$smaller>();
149 ::bytemuck::must_cast_ref::<Self, [$smaller; N]>(self).iter()
150 }
151 }
152
153 #[cfg(target_endian = "big")]
154 impl $crate::underlier::DivisIterable<$smaller> for $bigger {
155 type Iter<'a> = std::iter::Rev<std::slice::Iter<'a, u8>>;
156
157 #[inline]
158 fn divide(&self) -> Self::Iter<'_> {
159 const N: usize = size_of::<$bigger>() / size_of::<$smaller>();
160 ::bytemuck::must_cast_ref::<Self, [$smaller; N]>(self).iter().rev()
161 }
162 }
163 };
164 (@pairs $first:ty, $second:ty, $($tail:ty),*) => {
165 impl_divisible!(@pairs $first, $second);
166 impl_divisible!(@pairs $first, $($tail),*);
167 };
168 ($_:ty) => {};
169 ($head:ty, $($tail:ty),*) => {
170 impl_divisible!(@pairs $head, $($tail),*);
171 impl_divisible!($($tail),*);
172 }
173}
174
175#[allow(unused)]
176pub(crate) use impl_divisible;
177
178use super::UnderlierType;
179
180impl_divisible!(u128, u64, u32, u16, u8);