binius_field/
as_packed_field.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use crate::{
4	aes_field::*,
5	arch::{
6		packed_1::*, packed_128::*, packed_16::*, packed_2::*, packed_32::*, packed_4::*,
7		packed_64::*, packed_8::*, packed_aes_128::*, packed_aes_16::*, packed_aes_32::*,
8		packed_aes_64::*, packed_aes_8::*, packed_polyval_128::PackedBinaryPolyval1x128b,
9	},
10	binary_field::*,
11	polyval::BinaryField128bPolyval,
12	underlier::{UnderlierType, WithUnderlier},
13	ExtensionField, Field, PackedField,
14};
15
16/// Trait that establishes correspondence between the scalar field and a packed field of the same
17/// bit size with a single element.
18///
19/// E.g. `BinaryField64b` -> `PackedBinaryField1x64b`.
20/// Note that the underlier of the packed field may be different.
21/// E.g. `BinaryField128b` has u128 as underlier, while for x64 `PackedBinaryField1x128b`'s underlier
22/// may be `M128`.
23pub trait AsSinglePacked: Field {
24	type Packed: PackedField<Scalar = Self>
25		+ WithUnderlier<Underlier: From<Self::Underlier> + Into<Self::Underlier>>;
26
27	fn to_single_packed(self) -> Self::Packed {
28		assert_eq!(Self::Packed::WIDTH, 1);
29
30		Self::Packed::set_single(self)
31	}
32
33	fn from_single_packed(value: Self::Packed) -> Self {
34		assert_eq!(Self::Packed::WIDTH, 1);
35
36		value.get(0)
37	}
38}
39
40macro_rules! impl_as_single_packed_field {
41	($field:ty, $packed_field:ty) => {
42		impl AsSinglePacked for $field {
43			type Packed = $packed_field;
44		}
45	};
46}
47
48impl_as_single_packed_field!(BinaryField1b, PackedBinaryField1x1b);
49impl_as_single_packed_field!(BinaryField2b, PackedBinaryField1x2b);
50impl_as_single_packed_field!(BinaryField4b, PackedBinaryField1x4b);
51impl_as_single_packed_field!(BinaryField8b, PackedBinaryField1x8b);
52impl_as_single_packed_field!(BinaryField16b, PackedBinaryField1x16b);
53impl_as_single_packed_field!(BinaryField32b, PackedBinaryField1x32b);
54impl_as_single_packed_field!(BinaryField64b, PackedBinaryField1x64b);
55impl_as_single_packed_field!(BinaryField128b, PackedBinaryField1x128b);
56
57impl_as_single_packed_field!(AESTowerField8b, PackedAESBinaryField1x8b);
58impl_as_single_packed_field!(AESTowerField16b, PackedAESBinaryField1x16b);
59impl_as_single_packed_field!(AESTowerField32b, PackedAESBinaryField1x32b);
60impl_as_single_packed_field!(AESTowerField64b, PackedAESBinaryField1x64b);
61impl_as_single_packed_field!(AESTowerField128b, PackedAESBinaryField1x128b);
62
63impl_as_single_packed_field!(BinaryField128bPolyval, PackedBinaryPolyval1x128b);
64
65/// This trait represents correspondence (UnderlierType, Field) -> PackedField.
66/// For example (u64, BinaryField16b) -> PackedBinaryField4x16b.
67pub trait PackScalar<F: Field>: UnderlierType {
68	type Packed: PackedField<Scalar = F> + WithUnderlier<Underlier = Self>;
69}
70
71/// Returns the packed field type for the scalar field `F` and underlier `U`.
72pub type PackedType<U, F> = <U as PackScalar<F>>::Packed;
73
74/// A trait to convert field to a same bit size packed field with some smaller scalar.
75pub(crate) trait AsPackedField<Scalar: Field>: Field
76where
77	Self: ExtensionField<Scalar>,
78{
79	type Packed: PackedField<Scalar = Scalar>
80		+ WithUnderlier<Underlier: From<Self::Underlier> + Into<Self::Underlier>>;
81
82	fn to_packed(self) -> Self::Packed {
83		Self::Packed::from_underlier(self.to_underlier().into())
84	}
85
86	fn from_packed(value: Self::Packed) -> Self {
87		Self::from_underlier(value.to_underlier().into())
88	}
89}
90
91impl<Scalar, F> AsPackedField<Scalar> for F
92where
93	F: Field
94		+ WithUnderlier<Underlier: PackScalar<Scalar>>
95		+ AsSinglePacked
96		+ ExtensionField<Scalar>,
97	Scalar: Field,
98{
99	type Packed = <Self::Underlier as PackScalar<Scalar>>::Packed;
100}