p3_field/packed/
packed_traits.rs1use core::iter::{Product, Sum};
2use core::mem::MaybeUninit;
3use core::ops::{Div, DivAssign};
4use core::{array, slice};
5
6use crate::field::Field;
7use crate::{Algebra, BasedVectorSpace, ExtensionField, Powers, PrimeCharacteristicRing};
8
9pub trait Packable: 'static + Default + Copy + Send + Sync + PartialEq + Eq {}
13
14pub unsafe trait PackedValue: 'static + Copy + Send + Sync {
20 type Value: Packable;
22
23 const WIDTH: usize;
25
26 #[must_use]
31 fn from_slice(slice: &[Self::Value]) -> &Self;
32
33 #[must_use]
38 fn from_slice_mut(slice: &mut [Self::Value]) -> &mut Self;
39
40 #[must_use]
44 fn from_fn<F>(f: F) -> Self
45 where
46 F: FnMut(usize) -> Self::Value;
47
48 #[must_use]
50 fn as_slice(&self) -> &[Self::Value];
51
52 #[must_use]
54 fn as_slice_mut(&mut self) -> &mut [Self::Value];
55
56 #[inline]
61 #[must_use]
62 fn pack_slice(buf: &[Self::Value]) -> &[Self] {
63 const {
65 assert!(align_of::<Self>() <= align_of::<Self::Value>());
66 }
67 assert!(
68 buf.len().is_multiple_of(Self::WIDTH),
69 "Slice length (got {}) must be a multiple of packed field width ({}).",
70 buf.len(),
71 Self::WIDTH
72 );
73 let buf_ptr = buf.as_ptr().cast::<Self>();
74 let n = buf.len() / Self::WIDTH;
75 unsafe { slice::from_raw_parts(buf_ptr, n) }
76 }
77
78 #[inline]
80 #[must_use]
81 fn pack_slice_with_suffix(buf: &[Self::Value]) -> (&[Self], &[Self::Value]) {
82 let (packed, suffix) = buf.split_at(buf.len() - buf.len() % Self::WIDTH);
83 (Self::pack_slice(packed), suffix)
84 }
85
86 #[inline]
91 #[must_use]
92 fn pack_slice_mut(buf: &mut [Self::Value]) -> &mut [Self] {
93 const {
94 assert!(align_of::<Self>() <= align_of::<Self::Value>());
95 }
96 assert!(
97 buf.len().is_multiple_of(Self::WIDTH),
98 "Slice length (got {}) must be a multiple of packed field width ({}).",
99 buf.len(),
100 Self::WIDTH
101 );
102 let buf_ptr = buf.as_mut_ptr().cast::<Self>();
103 let n = buf.len() / Self::WIDTH;
104 unsafe { slice::from_raw_parts_mut(buf_ptr, n) }
105 }
106
107 #[inline]
113 #[must_use]
114 fn pack_maybe_uninit_slice_mut(
115 buf: &mut [MaybeUninit<Self::Value>],
116 ) -> &mut [MaybeUninit<Self>] {
117 const {
118 assert!(align_of::<Self>() <= align_of::<Self::Value>());
119 }
120 assert!(
121 buf.len().is_multiple_of(Self::WIDTH),
122 "Slice length (got {}) must be a multiple of packed field width ({}).",
123 buf.len(),
124 Self::WIDTH
125 );
126 let buf_ptr = buf.as_mut_ptr().cast::<MaybeUninit<Self>>();
127 let n = buf.len() / Self::WIDTH;
128 unsafe { slice::from_raw_parts_mut(buf_ptr, n) }
129 }
130
131 #[inline]
135 #[must_use]
136 fn pack_slice_with_suffix_mut(buf: &mut [Self::Value]) -> (&mut [Self], &mut [Self::Value]) {
137 let (packed, suffix) = buf.split_at_mut(buf.len() - buf.len() % Self::WIDTH);
138 (Self::pack_slice_mut(packed), suffix)
139 }
140
141 #[inline]
145 #[must_use]
146 fn pack_maybe_uninit_slice_with_suffix_mut(
147 buf: &mut [MaybeUninit<Self::Value>],
148 ) -> (&mut [MaybeUninit<Self>], &mut [MaybeUninit<Self::Value>]) {
149 let (packed, suffix) = buf.split_at_mut(buf.len() - buf.len() % Self::WIDTH);
150 (Self::pack_maybe_uninit_slice_mut(packed), suffix)
151 }
152
153 #[inline]
158 #[must_use]
159 fn unpack_slice(buf: &[Self]) -> &[Self::Value] {
160 const {
161 assert!(align_of::<Self>() >= align_of::<Self::Value>());
162 }
163 let buf_ptr = buf.as_ptr().cast::<Self::Value>();
164 let n = buf.len() * Self::WIDTH;
165 unsafe { slice::from_raw_parts(buf_ptr, n) }
166 }
167
168 #[inline]
173 #[must_use]
174 fn extract(&self, lane: usize) -> Self::Value {
175 self.as_slice()[lane]
176 }
177
178 #[inline]
187 fn unpack_into<const N: usize>(packed: &[Self; N], rows: &mut [[Self::Value; N]]) {
188 assert_eq!(rows.len(), Self::WIDTH);
189 #[allow(clippy::needless_range_loop)]
190 for lane in 0..Self::WIDTH {
191 rows[lane] = array::from_fn(|col| packed[col].extract(lane));
192 }
193 }
194}
195
196unsafe impl<T: Packable, const WIDTH: usize> PackedValue for [T; WIDTH] {
197 type Value = T;
198 const WIDTH: usize = WIDTH;
199
200 #[inline]
201 fn from_slice(slice: &[Self::Value]) -> &Self {
202 assert_eq!(slice.len(), Self::WIDTH);
203 unsafe { &*slice.as_ptr().cast() }
204 }
205
206 #[inline]
207 fn from_slice_mut(slice: &mut [Self::Value]) -> &mut Self {
208 assert_eq!(slice.len(), Self::WIDTH);
209 unsafe { &mut *slice.as_mut_ptr().cast() }
210 }
211
212 #[inline]
213 fn from_fn<Fn>(f: Fn) -> Self
214 where
215 Fn: FnMut(usize) -> Self::Value,
216 {
217 core::array::from_fn(f)
218 }
219
220 #[inline]
221 fn as_slice(&self) -> &[Self::Value] {
222 self
223 }
224
225 #[inline]
226 fn as_slice_mut(&mut self) -> &mut [Self::Value] {
227 self
228 }
229}
230
231pub unsafe trait PackedField: Algebra<Self::Scalar>
236 + PackedValue<Value = Self::Scalar>
237 + Div<Self::Scalar, Output = Self>
239 + DivAssign<Self::Scalar>
240 + Sum<Self::Scalar>
241 + Product<Self::Scalar>
242{
243 type Scalar: Field;
244
245 #[must_use]
249 fn packed_powers(base: Self::Scalar) -> Powers<Self> {
250 Self::packed_shifted_powers(base, Self::Scalar::ONE)
251 }
252
253 #[must_use]
257 fn packed_shifted_powers(base: Self::Scalar, start: Self::Scalar) -> Powers<Self> {
258 let mut current: Self = start.into();
259 let slice = current.as_slice_mut();
260 for i in 1..Self::WIDTH {
261 slice[i] = slice[i - 1] * base;
262 }
263
264 Powers {
265 base: base.exp_u64(Self::WIDTH as u64).into(),
266 current,
267 }
268 }
269
270 #[must_use]
278 fn packed_linear_combination<const N: usize>(coeffs: &[Self::Scalar], vecs: &[Self]) -> Self {
279 assert_eq!(coeffs.len(), N);
280 assert_eq!(vecs.len(), N);
281 let combined: [Self; N] = array::from_fn(|i| vecs[i] * coeffs[i]);
282 Self::sum_array::<N>(&combined)
283 }
284}
285
286pub unsafe trait PackedFieldPow2: PackedField {
289 #[must_use]
326 fn interleave(&self, other: Self, block_len: usize) -> (Self, Self);
327}
328
329pub trait PackedFieldExtension<
338 BaseField: Field,
339 ExtField: ExtensionField<BaseField, ExtensionPacking = Self>,
340>: Algebra<ExtField> + Algebra<BaseField::Packing> + BasedVectorSpace<BaseField::Packing>
341{
342 #[must_use]
346 fn from_ext_slice(ext_slice: &[ExtField]) -> Self;
347
348 #[inline]
350 #[must_use]
351 fn extract(&self, lane: usize) -> ExtField {
352 ExtField::from_basis_coefficients_fn(|d| {
353 self.as_basis_coefficients_slice()[d].as_slice()[lane]
354 })
355 }
356
357 #[inline]
362 #[must_use]
363 fn to_ext_iter(iter: impl IntoIterator<Item = Self>) -> impl Iterator<Item = ExtField> {
364 iter.into_iter()
365 .flat_map(|x| (0..BaseField::Packing::WIDTH).map(move |i| x.extract(i)))
366 }
367
368 #[must_use]
371 fn packed_ext_powers(base: ExtField) -> Powers<Self>;
372
373 #[must_use]
379 fn packed_ext_powers_capped(base: ExtField, unpacked_len: usize) -> impl Iterator<Item = Self> {
380 Self::packed_ext_powers(base).take(unpacked_len.div_ceil(BaseField::Packing::WIDTH))
381 }
382}
383
384unsafe impl<T: Packable> PackedValue for T {
385 type Value = Self;
386
387 const WIDTH: usize = 1;
388
389 #[inline]
390 fn from_slice(slice: &[Self::Value]) -> &Self {
391 assert_eq!(slice.len(), Self::WIDTH);
392 &slice[0]
393 }
394
395 #[inline]
396 fn from_slice_mut(slice: &mut [Self::Value]) -> &mut Self {
397 assert_eq!(slice.len(), Self::WIDTH);
398 &mut slice[0]
399 }
400
401 #[inline]
402 fn from_fn<Fn>(mut f: Fn) -> Self
403 where
404 Fn: FnMut(usize) -> Self::Value,
405 {
406 f(0)
407 }
408
409 #[inline]
410 fn as_slice(&self) -> &[Self::Value] {
411 slice::from_ref(self)
412 }
413
414 #[inline]
415 fn as_slice_mut(&mut self) -> &mut [Self::Value] {
416 slice::from_mut(self)
417 }
418}
419
420unsafe impl<F: Field> PackedField for F {
421 type Scalar = Self;
422}
423
424unsafe impl<F: Field> PackedFieldPow2 for F {
425 #[inline]
426 fn interleave(&self, other: Self, block_len: usize) -> (Self, Self) {
427 match block_len {
428 1 => (*self, other),
429 _ => panic!("unsupported block length"),
430 }
431 }
432}
433
434impl<F: Field> PackedFieldExtension<F, F> for F::Packing {
435 #[inline]
436 fn from_ext_slice(ext_slice: &[F]) -> Self {
437 *F::Packing::from_slice(ext_slice)
438 }
439
440 #[inline]
441 fn packed_ext_powers(base: F) -> Powers<Self> {
442 F::Packing::packed_powers(base)
443 }
444}
445
446impl Packable for u8 {}
447
448impl Packable for u16 {}
449
450impl Packable for u32 {}
451
452impl Packable for u64 {}
453
454impl Packable for u128 {}