p3_field/integers.rs
1//! A collection of traits and macros which convert primitive integer types into field elements.
2
3/// A macro which lets us define the function `from_Int`
4/// where `Int` can be replaced by any integer type.
5///
6/// Running, `from_integer_types!(Int)` adds the following code to a trait:
7///
8/// ```rust,ignore
9/// /// Given an integer `r`, return the sum of `r` copies of `ONE`:
10/// ///
11/// /// `r * Self::ONE = Self::ONE + ... + Self::ONE (r times)`.
12/// ///
13/// /// Note that the output only depends on `r mod p`.
14/// ///
15/// /// This should be avoided in performance critical locations.
16/// fn from_Int(int: Int) -> Self {
17/// Self::from_prime_subfield(Self::PrimeSubfield::from_int(int))
18/// }
19/// ```
20///
21/// This macro can be run for any `Int` where `Self::PrimeSubfield` implements `QuotientMap<Int>`.
22/// It considerably cuts down on the amount of copy/pasted code.
23macro_rules! from_integer_types {
24 ($($type:ty),* $(,)? ) => {
25 $( paste::paste!{
26 /// Given an integer `r`, return the sum of `r` copies of `ONE`:
27 ///
28 /// `r * Self::ONE = Self::ONE + ... + Self::ONE (r times)`.
29 ///
30 /// Note that the output only depends on `r mod p`.
31 ///
32 /// This should be avoided in performance critical locations.
33 fn [<from_ $type>](int: $type) -> Self {
34 Self::from_prime_subfield(Self::PrimeSubfield::from_int(int))
35 }
36 }
37 )*
38 };
39}
40
41pub(crate) use from_integer_types;
42
43/// Implementation of the quotient map `ℤ -> ℤ/p` which sends an integer `r` to its conjugacy class `[r]`.
44///
45/// This is the key trait allowing us to convert integers into field elements. Each prime field
46/// should implement this for all primitive integer types.
47pub trait QuotientMap<Int>: Sized {
48 /// Convert a given integer into an element of the field `ℤ/p`.
49 ///
50 /// This is the most generic method which makes no assumptions on the size of the input.
51 /// Where possible, this method should be used with the smallest possible integer type.
52 /// For example, if a 32-bit integer `x` is known to be less than `2^16`, then
53 /// `from_int(x as u16)` will often be faster than `from_int(x)`.
54 ///
55 /// This method is also strongly preferred over `from_canonical_checked/from_canonical_unchecked`.
56 /// It will usually be identical when `Int` is a small type, e.g. `u8/u16` and is safer for
57 /// larger types.
58 #[must_use]
59 fn from_int(int: Int) -> Self;
60
61 /// Convert a given integer into an element of the field `ℤ/p`. The input is checked to
62 /// ensure it lies within a given range.
63 /// - If `Int` is an unsigned integer type the input must lie in `[0, p - 1]`.
64 /// - If `Int` is a signed integer type the input must lie in `[-(p - 1)/2, (p - 1)/2]`.
65 ///
66 /// Return `None` if the input lies outside this range and `Some(val)` otherwise.
67 #[must_use]
68 fn from_canonical_checked(int: Int) -> Option<Self>;
69
70 /// Convert a given integer into an element of the field `ℤ/p`. The input is guaranteed
71 /// to lie within a specific range depending on `p`. If the input lies outside of this
72 /// range, the output is undefined.
73 ///
74 /// In general `from_canonical_unchecked` will be faster for either `signed` or `unsigned`
75 /// types but the specifics will depend on the field.
76 ///
77 /// # Safety
78 /// - If `Int` is an unsigned integer type then the allowed range will include `[0, p - 1]`.
79 /// - If `Int` is a signed integer type then the allowed range will include `[-(p - 1)/2, (p - 1)/2]`.
80 #[must_use]
81 unsafe fn from_canonical_unchecked(int: Int) -> Self;
82}
83
84/// This allows us to avoid some duplication which arises when working with fields which contain a generic parameter.
85///
86/// See `quotient_map_small_int` to see what this will expand to/how to call it. This is not intended for use outside of
87/// that macro.
88#[macro_export]
89macro_rules! quotient_map_small_internals {
90 ($field:ty, $field_size:ty, $small_int:ty) => {
91 #[doc = concat!("Convert a given `", stringify!($small_int), "` integer into an element of the `", stringify!($field), "` field.
92 \n Due to the integer type, the input value is always canonical.")]
93 #[inline]
94 fn from_int(int: $small_int) -> Self {
95 // Check at compile time.
96 const { assert!(size_of::<$small_int>() < size_of::<$field_size>()); }
97 unsafe {
98 Self::from_canonical_unchecked(int as $field_size)
99 }
100 }
101
102 #[doc = concat!("Convert a given `", stringify!($small_int), "` integer into an element of the `", stringify!($field), "` field.
103 \n Due to the integer type, the input value is always canonical.")]
104 #[inline]
105 fn from_canonical_checked(int: $small_int) -> Option<Self> {
106 // Check at compile time.
107 const { assert!(size_of::<$small_int>() < size_of::<$field_size>()); }
108 Some(unsafe {
109 Self::from_canonical_unchecked(int as $field_size)
110 })
111 }
112
113 #[doc = concat!("Convert a given `", stringify!($small_int), "` integer into an element of the `", stringify!($field), "` field.
114 \n Due to the integer type, the input value is always canonical.")]
115 #[inline]
116 unsafe fn from_canonical_unchecked(int: $small_int) -> Self {
117 // Check at compile time.
118 const { assert!(size_of::<$small_int>() < size_of::<$field_size>()); }
119 unsafe {
120 Self::from_canonical_unchecked(int as $field_size)
121 }
122 }
123 };
124}
125
126/// If the integer type is smaller than the field order all possible inputs are canonical.
127/// In such a case we can easily implement `QuotientMap<SmallInt>` as all three methods will coincide.
128///
129/// The range of acceptable integer types depends on the size of the field:
130/// - For 31 bit fields, `SmallInt = u8, u16, i8, i16`.
131/// - For 64 bit fields, `SmallInt = u8, u16, u32, i8, i16, i32`.
132/// - For large fields (E.g. `Bn254`), `SmallInt` can be anything except for the largest primitive integer type `u128/i128`
133///
134/// This macro accepts 3 inputs.
135/// - The name of the prime field `P`
136/// - The larger integer type `Int` which inputs should be cast to.
137/// - A list of smaller integer types to auto implement `QuotientMap<SmallInt>`.
138///
139/// Then `from_int`, `from_canonical_checked`, `from_canonical_unchecked` are all
140/// implemented by casting the input to an `Int` and using the `from_canonical_unchecked`
141/// method from `QuotientMap<Int>`.
142///
143/// For a concrete example, `quotient_map_small_int!(Mersenne31, u32, [u8])` produces the following code:
144///
145/// ```rust,ignore
146/// impl QuotientMap<u8> for Mersenne31 {
147/// /// Convert a given `u8` integer into an element of the `Mersenne31` field.
148/// ///
149/// /// Due to the integer type, the input value is always canonical.
150/// #[inline]
151/// fn from_int(int: u8) -> Mersenne31 {
152/// // Check at compile time.
153/// const { assert!(size_of::<u8>() < size_of::<u32>()); }
154/// unsafe {
155/// Self::from_canonical_unchecked(int as u32)
156/// }
157/// }
158///
159/// /// Convert a given `u8` integer into an element of the `Mersenne31` field.
160/// ///
161/// /// Due to the integer type, the input value is always canonical.
162/// #[inline]
163/// fn from_canonical_checked(int: u8) -> Option<Mersenne31> {
164/// // Check at compile time.
165/// const { assert!(size_of::<u8>() < size_of::<u32>()); }
166/// Some(unsafe {
167/// Self::from_canonical_unchecked(int as u32)
168/// })
169/// }
170///
171/// /// Convert a given `u8` integer into an element of the `Mersenne31` field.
172/// ///
173/// /// Due to the integer type, the input value is always canonical.
174/// #[inline]
175/// unsafe fn from_canonical_unchecked(int: u8) -> Mersenne31 {
176/// // Check at compile time.
177/// const { assert!(size_of::<u8>() < size_of::<u32>()); }
178/// unsafe {
179/// Self::from_canonical_unchecked(int as u32)
180/// }
181/// }
182/// }
183///```
184///
185/// Fields will often use this method twice. Once for unsigned ints and once for signed ints.
186///
187/// We need two slightly different versions for this macro as MontyField31 uses generic parameters.
188#[macro_export]
189macro_rules! quotient_map_small_int {
190 ($field:ty, $field_size:ty, [$($small_int:ty),*] ) => {
191 $(
192 paste::paste!{
193 impl QuotientMap<$small_int> for $field {
194 $crate::quotient_map_small_internals!($field, $field_size, $small_int);
195 }
196 }
197 )*
198 };
199
200 ($field:ty, $field_size:ty, $field_param:ty, [$($small_int:ty),*] ) => {
201 $(
202 paste::paste!{
203 impl<FP: $field_param> QuotientMap<$small_int> for $field<FP> {
204 $crate::quotient_map_small_internals!($field, $field_size, $small_int);
205 }
206 }
207 )*
208 };
209}
210
211/// If the unsigned integer type is large enough, there is often no method better for `from_int` than
212/// just doing a modular reduction to a smaller type.
213///
214/// This macro accepts 6 inputs.
215/// - The name of the prime field `P`
216/// - The smallest natural integer type large enough to contain the field characteristic.
217/// - The characteristic of the field.
218/// - A string giving the range for which from_canonical_checked produces the correct result.
219/// - A string giving the range for which from_canonical_unchecked produces the correct result.
220/// - A list of large integer types to auto implement `QuotientMap<LargeInt>`.
221///
222/// For a concrete example, `quotient_map_large_uint!(Mersenne31, u32, Mersenne31::ORDER_U32, "`\[0, 2^31 - 2\]`", "`\[0, 2^31 - 1\]`", [u128])` would produce the following code:
223///
224/// ```rust,ignore
225/// impl QuotientMap<u128> for Mersenne31 {
226/// /// Convert a given `u128` integer into an element of the `Mersenne31` field.
227/// ///
228/// /// Uses a modular reduction to reduce to canonical form.
229/// /// This should be avoided in performance critical locations.
230/// #[inline]
231/// fn from_int(int: u128) -> Mersenne31 {
232/// // Check at compile time.
233/// const { assert!(size_of::<u128>() > size_of::<u32>()); }
234/// let red = (int % (Mersenne31::ORDER_U32 as u128)) as u32;
235/// unsafe {
236/// // This is safe as red is less than the field order by assumption.
237/// Self::from_canonical_unchecked(red)
238/// }
239/// }
240///
241/// /// Convert a given `u128` integer into an element of the `Mersenne31` field.
242/// ///
243/// /// Returns `None` if the input does not lie in the range: [0, 2^31 - 2].
244/// #[inline]
245/// fn from_canonical_checked(int: u128) -> Option<Mersenne31> {
246/// if int < Mersenne31::ORDER_U32 as u128 {
247/// unsafe {
248/// // This is safe as we just checked that int is less than the field order.
249/// Some(Self::from_canonical_unchecked(int as u32))
250/// }
251/// } else {
252/// None
253/// }
254/// }
255///
256/// /// Convert a given `u128` integer into an element of the `Mersenne31` field.
257/// ///
258/// /// # Safety
259/// /// The input must lie in the range:", [0, 2^31 - 1].
260/// #[inline]
261/// unsafe fn from_canonical_unchecked(int: u128) -> Mersenne31 {
262/// unsafe {
263/// Self::from_canonical_unchecked(int as u32)
264/// }
265/// }
266/// }
267///```
268#[macro_export]
269macro_rules! quotient_map_large_uint {
270 ($field:ty, $field_size:ty, $field_order:expr, $checked_bounds:literal, $unchecked_bounds:literal, [$($large_int:ty),*] ) => {
271 $(
272 impl QuotientMap<$large_int> for $field {
273 #[doc = concat!("Convert a given `", stringify!($large_int), "` integer into an element of the `", stringify!($field), "` field.
274 \n Uses a modular reduction to reduce to canonical form. \n This should be avoided in performance critical locations.")]
275 #[inline]
276 fn from_int(int: $large_int) -> $field {
277 const { assert!(size_of::<$large_int>() > size_of::<$field_size>()); }
278 let red = (int % ($field_order as $large_int)) as $field_size;
279 unsafe {
280 // This is safe as red is less than the field order by assumption.
281 Self::from_canonical_unchecked(red)
282 }
283 }
284
285 #[doc = concat!("Convert a given `", stringify!($large_int), "` integer into an element of the `", stringify!($field), "` field.
286 \n Returns `None` if the input does not lie in the range:", $checked_bounds, ".")]
287 #[inline]
288 fn from_canonical_checked(int: $large_int) -> Option<$field> {
289 if int < $field_order as $large_int {
290 unsafe {
291 // This is safe as we just checked that int is less than the field order.
292 Some(Self::from_canonical_unchecked(int as $field_size))
293 }
294 } else {
295 None
296 }
297 }
298
299 #[doc = concat!("Convert a given `", stringify!($large_int), "` integer into an element of the `", stringify!($field), "` field.")]
300 ///
301 /// # Safety
302 #[doc = concat!("The input must lie in the range:", $unchecked_bounds, ".")]
303 #[inline]
304 unsafe fn from_canonical_unchecked(int: $large_int) -> $field {
305 unsafe {
306 Self::from_canonical_unchecked(int as $field_size)
307 }
308 }
309 }
310 )*
311 };
312}
313
314/// For large signed integer types, a simple method which is usually good enough is to simply check the sign and use this to
315/// pass to the equivalent unsigned method.
316///
317/// This will often not be the fastest implementation but should be good enough for most cases.
318///
319/// This macro accepts 4 inputs.
320/// - The name of the prime field `P`.
321/// - The smallest natural integer type large enough to contain the field characteristic.
322/// - A string giving the range for which from_canonical_checked produces the correct result.
323/// - A string giving the range for which from_canonical_unchecked produces the correct result.
324/// - A list of pairs of large sign and unsigned integer types to auto implement `QuotientMap<LargeSignInt>`.
325///
326/// For a concrete example, `quotient_map_large_iint!(Mersenne31, i32, "`\[-2^30, 2^30\]`", "`\[1 - 2^31, 2^31 - 1\]`", [(i128, u128)])` would produce the following code:
327///
328/// ```rust,ignore
329/// impl QuotientMap<i128> for Mersenne31 {
330/// /// Convert a given `i128` integer into an element of the `Mersenne31` field.
331/// ///
332/// /// This checks the sign and then makes use of the equivalent method for unsigned integers.
333/// /// This should be avoided in performance critical locations.
334/// #[inline]
335/// fn from_int(int: i128) -> Mersenne31 {
336/// if int >= 0 {
337/// Self::from_int(int as u128)
338/// } else {
339/// -Self::from_int(-int as u128)
340/// }
341/// }
342///
343/// /// Convert a given `i128` integer into an element of the `Mersenne31` field.
344/// ///
345/// /// Returns `None` if the input does not lie in the range: `[-2^30, 2^30]`.
346/// #[inline]
347/// fn from_canonical_checked(int: i128) -> Option<Mersenne31> {
348/// // We just check that int fits into an i32 now and then use the i32 method.
349/// let int_small = TryInto::<i32>::try_into(int);
350/// if int_small.is_ok() {
351/// Self::from_canonical_checked(int_small.unwrap())
352/// } else {
353/// None
354/// }
355/// }
356///
357/// /// Convert a given `i128` integer into an element of the `Mersenne31` field.
358/// ///
359/// /// # Safety
360/// /// The input must lie in the range:", `[1 - 2^31, 2^31 - 1]`.
361/// #[inline]
362/// unsafe fn from_canonical_unchecked(int: i128) -> Mersenne31 {
363/// unsafe {
364/// Self::from_canonical_unchecked(int as i32)
365/// }
366/// }
367/// }
368///```
369#[macro_export]
370macro_rules! quotient_map_large_iint {
371 ($field:ty, $field_size:ty, $checked_bounds:literal, $unchecked_bounds:literal, [$(($large_signed_int:ty, $large_int:ty)),*] ) => {
372 $(
373 impl QuotientMap<$large_signed_int> for $field {
374 #[doc = concat!("Convert a given `", stringify!($large_signed_int), "` integer into an element of the `", stringify!($field), "` field.
375 \n This checks the sign and then makes use of the equivalent method for unsigned integers. \n This should be avoided in performance critical locations.")]
376 #[inline]
377 fn from_int(int: $large_signed_int) -> $field {
378 if int >= 0 {
379 Self::from_int(int as $large_int)
380 } else {
381 // `unsigned_abs` gives the magnitude without overflowing on the minimum value.
382 -Self::from_int(int.unsigned_abs())
383 }
384 }
385
386 #[doc = concat!("Convert a given `", stringify!($large_int), "` integer into an element of the `", stringify!($field), "` field.
387 \n Returns `None` if the input does not lie in the range:", $checked_bounds, ".")]
388 #[inline]
389 fn from_canonical_checked(int: $large_signed_int) -> Option<$field> {
390 let int_small = TryInto::<$field_size>::try_into(int).ok();
391
392 // The type of the following is Option<Option<$field>>.
393 // We use the ? operator to convert it to Option<$field>, with
394 // None and Some(None) both becoming None.
395 int_small.map(Self::from_canonical_checked)?
396 }
397
398 #[doc = concat!("Convert a given `", stringify!($large_int), "` integer into an element of the `", stringify!($field), "` field.")]
399 ///
400 /// # Safety
401 #[doc = concat!("The input must lie in the range:", $unchecked_bounds, ".")]
402 #[inline]
403 unsafe fn from_canonical_unchecked(int: $large_signed_int) -> $field {
404 unsafe {
405 Self::from_canonical_unchecked(int as $field_size)
406 }
407 }
408 }
409 )*
410 };
411}
412
413/// We implement `QuotientMap<usize>` (`QuotientMap<isize>`) by matching against the size of `usize` (`isize`)
414/// and then converting `usize` (`isize`) into the equivalent matching integer type.
415///
416/// The code is identical for both `usize` and `isize` outside of replacing some u's by i's so we use a macro
417/// to avoid the copy and paste.
418macro_rules! impl_u_i_size {
419 ($intsize:ty, $int8:ty, $int16:ty, $int32:ty, $int64:ty, $int128:ty) => {
420 impl<
421 F: QuotientMap<$int8>
422 + QuotientMap<$int16>
423 + QuotientMap<$int32>
424 + QuotientMap<$int64>
425 + QuotientMap<$int128>,
426 > QuotientMap<$intsize> for F
427 {
428 #[doc = concat!("We use the `from_int` method of the primitive integer type identical to `", stringify!($intsize), "` on this machine")]
429 fn from_int(int: $intsize) -> Self {
430 match size_of::<$intsize>() {
431 1 => Self::from_int(int as $int8),
432 2 => Self::from_int(int as $int16),
433 4 => Self::from_int(int as $int32),
434 8 => Self::from_int(int as $int64),
435 16 => Self::from_int(int as $int128),
436 _ => unreachable!(concat!(stringify!($intsize), "is not equivalent to any primitive integer types.")),
437 }
438 }
439
440 #[doc = concat!("We use the `from_canonical_checked` method of the primitive integer type identical to `", stringify!($intsize), "` on this machine")]
441 fn from_canonical_checked(int: $intsize) -> Option<Self> {
442 match size_of::<$intsize>() {
443 1 => Self::from_canonical_checked(int as $int8),
444 2 => Self::from_canonical_checked(int as $int16),
445 4 => Self::from_canonical_checked(int as $int32),
446 8 => Self::from_canonical_checked(int as $int64),
447 16 => Self::from_canonical_checked(int as $int128),
448 _ => unreachable!(concat!(stringify!($intsize), " is not equivalent to any primitive integer types.")),
449 }
450 }
451
452 #[doc = concat!("We use the `from_canonical_unchecked` method of the primitive integer type identical to `", stringify!($intsize), "` on this machine")]
453 unsafe fn from_canonical_unchecked(int: $intsize) -> Self {
454 unsafe {
455 match size_of::<$intsize>() {
456 1 => Self::from_canonical_unchecked(int as $int8),
457 2 => Self::from_canonical_unchecked(int as $int16),
458 4 => Self::from_canonical_unchecked(int as $int32),
459 8 => Self::from_canonical_unchecked(int as $int64),
460 16 => Self::from_canonical_unchecked(int as $int128),
461 _ => unreachable!(concat!(stringify!($intsize), " is not equivalent to any primitive integer types.")),
462 }
463 }
464 }
465 }
466 };
467}
468
469impl_u_i_size!(usize, u8, u16, u32, u64, u128);
470impl_u_i_size!(isize, i8, i16, i32, i64, i128);
471
472/// A simple macro which allows us to implement the `RawSerializable` trait for any 32-bit field.
473/// The field must implement PrimeField32.
474///
475/// This macro doesn't need any inputs as the implementation is identical for all 32-bit fields.
476#[macro_export]
477macro_rules! impl_raw_serializable_primefield32 {
478 () => {
479 const NUM_BYTES: usize = 4;
480
481 #[allow(refining_impl_trait)]
482 #[inline]
483 fn into_bytes(self) -> [u8; 4] {
484 self.to_unique_u32().to_le_bytes()
485 }
486
487 #[inline]
488 fn into_u32_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u32> {
489 // As every element is 32 bits, we can just convert the input to a unique u32.
490 input.into_iter().map(|x| x.to_unique_u32())
491 }
492
493 #[inline]
494 fn into_u64_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u64> {
495 let mut input = input.into_iter();
496 iter::from_fn(move || {
497 // If the first input.next() returns None, we return None.
498 let a = input.next()?;
499 // Otherwise we either pack 2 32 bit elements together if the iterator
500 // gives a second value or just cast the 32 bit element to 64 bits.
501 if let Some(b) = input.next() {
502 Some(a.to_unique_u64() | b.to_unique_u64() << 32)
503 } else {
504 Some(a.to_unique_u64())
505 }
506 })
507 }
508
509 #[inline]
510 fn into_parallel_byte_streams<const N: usize>(
511 input: impl IntoIterator<Item = [Self; N]>,
512 ) -> impl IntoIterator<Item = [u8; N]> {
513 input.into_iter().flat_map(|vector| {
514 let bytes = vector.map(|elem| elem.into_bytes());
515 (0..Self::NUM_BYTES).map(move |i| array::from_fn(|j| bytes[j][i]))
516 })
517 }
518
519 #[inline]
520 fn into_parallel_u32_streams<const N: usize>(
521 input: impl IntoIterator<Item = [Self; N]>,
522 ) -> impl IntoIterator<Item = [u32; N]> {
523 // As every element is 32 bits, we can just convert the input to a unique u32.
524 input.into_iter().map(|vec| vec.map(|x| x.to_unique_u32()))
525 }
526
527 #[inline]
528 fn into_parallel_u64_streams<const N: usize>(
529 input: impl IntoIterator<Item = [Self; N]>,
530 ) -> impl IntoIterator<Item = [u64; N]> {
531 let mut input = input.into_iter();
532 iter::from_fn(move || {
533 // If the first input.next() returns None, we return None.
534 let a = input.next()?;
535 // Otherwise we either pack pairs of 32 bit elements together if the iterator
536 // gives two arrays of or just cast the 32 bit elements to 64 bits.
537 if let Some(b) = input.next() {
538 let ab = array::from_fn(|i| {
539 let ai = a[i].to_unique_u64();
540 let bi = b[i].to_unique_u64();
541 ai | (bi << 32)
542 });
543 Some(ab)
544 } else {
545 Some(a.map(|x| x.to_unique_u64()))
546 }
547 })
548 }
549 };
550}
551
552/// A simple macro which allows us to implement the `RawSerializable` trait for any 64-bit field.
553/// The field must implement PrimeField64 (and should not implement PrimeField32).
554///
555/// This macro doesn't need any inputs as the implementation is identical for all 64-bit fields.
556#[macro_export]
557macro_rules! impl_raw_serializable_primefield64 {
558 () => {
559 const NUM_BYTES: usize = 8;
560
561 #[allow(refining_impl_trait)]
562 #[inline]
563 fn into_bytes(self) -> [u8; 8] {
564 self.to_unique_u64().to_le_bytes()
565 }
566
567 #[inline]
568 fn into_u32_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u32> {
569 input.into_iter().flat_map(|x| {
570 let x_u64 = x.to_unique_u64();
571 [x_u64 as u32, (x_u64 >> 32) as u32]
572 })
573 }
574
575 #[inline]
576 fn into_u64_stream(input: impl IntoIterator<Item = Self>) -> impl IntoIterator<Item = u64> {
577 // As every element is 64 bits, we can just convert the input to a unique u64.
578 input.into_iter().map(|x| x.to_unique_u64())
579 }
580
581 #[inline]
582 fn into_parallel_byte_streams<const N: usize>(
583 input: impl IntoIterator<Item = [Self; N]>,
584 ) -> impl IntoIterator<Item = [u8; N]> {
585 input.into_iter().flat_map(|vector| {
586 let bytes = vector.map(|elem| elem.into_bytes());
587 (0..Self::NUM_BYTES).map(move |i| array::from_fn(|j| bytes[j][i]))
588 })
589 }
590
591 #[inline]
592 fn into_parallel_u32_streams<const N: usize>(
593 input: impl IntoIterator<Item = [Self; N]>,
594 ) -> impl IntoIterator<Item = [u32; N]> {
595 input.into_iter().flat_map(|vec| {
596 let vec_64 = vec.map(|x| x.to_unique_u64());
597 let vec_32_lo = vec_64.map(|x| x as u32);
598 let vec_32_hi = vec_64.map(|x| (x >> 32) as u32);
599 [vec_32_lo, vec_32_hi]
600 })
601 }
602
603 #[inline]
604 fn into_parallel_u64_streams<const N: usize>(
605 input: impl IntoIterator<Item = [Self; N]>,
606 ) -> impl IntoIterator<Item = [u64; N]> {
607 // As every element is 64 bits, we can just convert the input to a unique u64.
608 input.into_iter().map(|vec| vec.map(|x| x.to_unique_u64()))
609 }
610 };
611}