1use std::{
9 fmt::Debug,
10 iter,
11 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
12};
13
14use bytemuck::Zeroable;
15
16use super::{Random, arithmetic_traits::Square};
17use crate::{BinaryField, Divisible, Maskable, WideMul, field::FieldOps};
18
19pub trait PackedField:
25 Default
26 + Debug
27 + Clone
28 + Copy
29 + Eq
30 + Sized
31 + FieldOps
32 + Add<Self::Scalar, Output = Self>
33 + Sub<Self::Scalar, Output = Self>
34 + Mul<Self::Scalar, Output = Self>
35 + AddAssign<Self::Scalar>
36 + SubAssign<Self::Scalar>
37 + MulAssign<Self::Scalar>
38 + Send
39 + Sync
40 + Zeroable
41 + Random
42 + WideMul<Output: Debug + Send + Sync + 'static>
43 + 'static
44 + Divisible<Self::Scalar>
48 + Maskable<Self::Scalar>
50{
51 const LOG_WIDTH: usize = Self::LOG_N;
55
56 const WIDTH: usize = 1 << Self::LOG_WIDTH;
60
61 #[inline]
63 fn into_iter(self) -> impl ExactSizeIterator<Item = Self::Scalar> + Send + Clone {
64 Divisible::value_iter(self)
65 }
66
67 #[inline]
69 fn iter(&self) -> impl ExactSizeIterator<Item = Self::Scalar> + Send + Clone + '_ {
70 Divisible::ref_iter(self)
71 }
72
73 #[inline]
75 fn iter_slice(slice: &[Self]) -> impl ExactSizeIterator<Item = Self::Scalar> + Send + Clone + '_
76 {
77 Divisible::slice_iter(slice)
78 }
79
80 fn from_fn(f: impl FnMut(usize) -> Self::Scalar) -> Self;
82
83 #[inline]
89 fn from_scalars(values: impl IntoIterator<Item = Self::Scalar>) -> Self {
90 Divisible::from_iter(values.into_iter())
91 }
92
93 fn pow(self, exp: u64) -> Self {
95 let mut res = Self::one();
96 for i in (0..64).rev() {
97 res = Square::square(res);
98 if ((exp >> i) & 1) == 1 {
99 res.mul_assign(self);
100 }
101 }
102 res
103 }
104
105 fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self);
121
122 fn unzip(self, other: Self, log_block_len: usize) -> (Self, Self);
135
136 #[inline]
168 fn spread(self, log_block_len: usize, block_idx: usize) -> Self {
169 assert!(log_block_len <= Self::LOG_WIDTH);
170 assert!(block_idx < 1 << (Self::LOG_WIDTH - log_block_len));
171
172 unsafe { self.spread_unchecked(log_block_len, block_idx) }
174 }
175
176 #[inline]
182 unsafe fn spread_unchecked(self, log_block_len: usize, block_idx: usize) -> Self {
183 let block_len = 1 << log_block_len;
184 let repeat = 1 << (Self::LOG_WIDTH - log_block_len);
185
186 Self::from_scalars(
187 self.iter()
188 .skip(block_idx * block_len)
189 .take(block_len)
190 .flat_map(|elem| iter::repeat_n(elem, repeat)),
191 )
192 }
193}
194
195#[inline(always)]
196pub fn get_packed_slice<P: PackedField>(packed: &[P], i: usize) -> P::Scalar {
197 assert!(i >> P::LOG_WIDTH < packed.len(), "index out of bounds");
198
199 unsafe { get_packed_slice_unchecked(packed, i) }
200}
201
202#[inline(always)]
206pub unsafe fn get_packed_slice_unchecked<P: PackedField>(packed: &[P], i: usize) -> P::Scalar {
207 unsafe {
212 packed
213 .get_unchecked(i >> P::LOG_WIDTH)
214 .get_unchecked(i % P::WIDTH)
215 }
216}
217
218#[inline]
222pub unsafe fn set_packed_slice_unchecked<P: PackedField>(
223 packed: &mut [P],
224 i: usize,
225 scalar: P::Scalar,
226) {
227 unsafe {
231 packed
232 .get_unchecked_mut(i >> P::LOG_WIDTH)
233 .set_unchecked(i % P::WIDTH, scalar);
234 }
235}
236
237pub trait PackedBinaryField: PackedField<Scalar: BinaryField> {}
239
240impl<PT> PackedBinaryField for PT where PT: PackedField<Scalar: BinaryField> {}
241
242#[cfg(test)]
243mod tests {
244 use std::iter::repeat_with;
245
246 use rand::prelude::*;
247
248 use crate::{
249 BinaryField1b, Ghash128b, PackedBinaryField1x1b, PackedBinaryField2x1b,
250 PackedBinaryField4x1b, PackedBinaryField8x1b, PackedBinaryField16x1b,
251 PackedBinaryField32x1b, PackedBinaryField64x1b, PackedBinaryField128x1b,
252 PackedBinaryField256x1b, PackedBinaryField512x1b, PackedField, PackedGhash1x128b,
253 PackedGhash2x128b, PackedGhash4x128b, PackedRijndael1x8b, PackedRijndael16x8b,
254 PackedRijndael32x8b, PackedRijndael64x8b, Rijndael8b, SlicedGhashSq1x256b,
255 SlicedGhashSq2x256b, SlicedGhashSq4x256b,
256 };
257
258 trait PackedFieldTest {
259 fn run<P: PackedField>(&self);
260 }
261
262 fn run_for_all_packed_fields(test: &impl PackedFieldTest) {
264 test.run::<BinaryField1b>();
266 test.run::<PackedBinaryField1x1b>();
267 test.run::<PackedBinaryField2x1b>();
268 test.run::<PackedBinaryField4x1b>();
269 test.run::<PackedBinaryField8x1b>();
270 test.run::<PackedBinaryField16x1b>();
271 test.run::<PackedBinaryField32x1b>();
272 test.run::<PackedBinaryField64x1b>();
273 test.run::<PackedBinaryField128x1b>();
274 test.run::<PackedBinaryField256x1b>();
275 test.run::<PackedBinaryField512x1b>();
276
277 test.run::<Rijndael8b>();
279 test.run::<PackedRijndael1x8b>();
280 test.run::<PackedRijndael16x8b>();
281 test.run::<PackedRijndael32x8b>();
282 test.run::<PackedRijndael64x8b>();
283
284 test.run::<Ghash128b>();
286 test.run::<PackedGhash1x128b>();
287 test.run::<PackedGhash2x128b>();
288 test.run::<PackedGhash4x128b>();
289
290 test.run::<SlicedGhashSq1x256b>();
292 test.run::<SlicedGhashSq2x256b>();
293 test.run::<SlicedGhashSq4x256b>();
294 }
295
296 fn check_value_iteration<P: PackedField>(mut rng: impl Rng) {
297 let packed = P::random(&mut rng);
298 let mut iter = packed.iter();
299 for i in 0..P::WIDTH {
300 assert_eq!(packed.get(i), iter.next().unwrap());
301 }
302 assert!(iter.next().is_none());
303 }
304
305 fn check_ref_iteration<P: PackedField>(mut rng: impl Rng) {
306 let packed = P::random(&mut rng);
307 let mut iter = packed.into_iter();
308 for i in 0..P::WIDTH {
309 assert_eq!(packed.get(i), iter.next().unwrap());
310 }
311 assert!(iter.next().is_none());
312 }
313
314 fn check_exact_size<P: PackedField>(mut rng: impl Rng) {
315 let packed = P::random(&mut rng);
316
317 assert_eq!(packed.iter().len(), P::WIDTH);
319 assert_eq!(packed.iter().count(), P::WIDTH);
320 assert_eq!(packed.iter().size_hint(), (P::WIDTH, Some(P::WIDTH)));
321
322 assert_eq!(packed.into_iter().len(), P::WIDTH);
323 assert_eq!(packed.into_iter().count(), P::WIDTH);
324 assert_eq!(packed.into_iter().size_hint(), (P::WIDTH, Some(P::WIDTH)));
325
326 for len in [0, 1, 3] {
329 let slice = repeat_with(|| P::random(&mut rng))
330 .take(len)
331 .collect::<Vec<_>>();
332 let expected = len * P::WIDTH;
333
334 assert_eq!(P::iter_slice(&slice).len(), expected);
335 assert_eq!(P::iter_slice(&slice).count(), expected);
336 assert_eq!(P::iter_slice(&slice).size_hint(), (expected, Some(expected)));
337 }
338 }
339
340 fn check_iter_slice_matches_flat_map<P: PackedField>(mut rng: impl Rng) {
341 for len in [0, 1, 2, 5] {
344 let slice = repeat_with(|| P::random(&mut rng))
345 .take(len)
346 .collect::<Vec<_>>();
347
348 let expected = slice.iter().flat_map(P::iter).collect::<Vec<_>>();
350 assert_eq!(P::iter_slice(&slice).collect::<Vec<_>>(), expected);
351 }
352 }
353
354 fn check_skipping<P: PackedField>(mut rng: impl Rng) {
355 let packed = P::random(&mut rng);
356 let scalars = packed.iter().collect::<Vec<_>>();
357
358 for skip in 0..P::WIDTH {
361 assert_eq!(packed.iter().nth(skip), Some(scalars[skip]));
362 assert!(packed.iter().skip(skip).eq(scalars[skip..].iter().copied()));
363 }
364 assert_eq!(packed.iter().nth(P::WIDTH), None);
365
366 let slice = [packed, P::random(&mut rng)];
370 let expected = slice.iter().flat_map(P::iter).collect::<Vec<_>>();
371 for skip in [0, P::WIDTH - 1, P::WIDTH, 2 * P::WIDTH - 1] {
372 assert_eq!(P::iter_slice(&slice).nth(skip), Some(expected[skip]));
373 }
374 }
375
376 struct PackedFieldIterationTest;
377
378 impl PackedFieldTest for PackedFieldIterationTest {
379 fn run<P: PackedField>(&self) {
380 let mut rng = StdRng::seed_from_u64(0);
381
382 check_value_iteration::<P>(&mut rng);
383 check_ref_iteration::<P>(&mut rng);
384 check_exact_size::<P>(&mut rng);
385 check_iter_slice_matches_flat_map::<P>(&mut rng);
386 check_skipping::<P>(&mut rng);
387 }
388 }
389
390 #[test]
391 fn test_iteration() {
392 run_for_all_packed_fields(&PackedFieldIterationTest);
393 }
394}