Skip to main content

binius_field/
packed_extension.rs

1// Copyright 2023-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4use crate::{
5	BinaryField, ExtensionField, PackedField, arch::PackedPrimitiveType, underlier::WithUnderlier,
6};
7
8/// A packed extension field that can also be read as a packing of its subfield `FSub`.
9///
10/// `Self` and [`Self::PackedSubfield`] cover the same bits in the same order.
11/// They differ only in how wide a scalar those bits are cut into.
12/// That is what makes all four casts free reinterpretations rather than conversions.
13///
14/// The subfield scalars come out in [`ExtensionField`] basis order:
15///
16/// ```text
17/// P::cast_bases_mut(exts)  ==  exts.iter().flat_map(|ext| ext.iter_bases())
18/// ```
19pub trait PackedExtension<FSub: BinaryField>:
20	PackedField<Scalar: ExtensionField<FSub>> + WithUnderlier
21{
22	/// The packing of `FSub` covering the same bits as `Self`.
23	type PackedSubfield: PackedField<Scalar = FSub>;
24
25	/// Reads a packed extension field element as a packed subfield element.
26	fn cast_base(self) -> Self::PackedSubfield;
27
28	/// Reads a packed extension field element in place as a packed subfield element.
29	fn cast_base_mut(&mut self) -> &mut Self::PackedSubfield;
30
31	/// Reads a packed subfield element as a packed extension field element.
32	fn cast_ext(base: Self::PackedSubfield) -> Self;
33
34	/// Reads a slice of packed extension field elements in place as packed subfield elements.
35	fn cast_bases_mut(packed: &mut [Self]) -> &mut [Self::PackedSubfield];
36}
37
38/// A shorthand for [`PackedExtension::PackedSubfield`].
39pub type PackedSubfield<P, FSub> = <P as PackedExtension<FSub>>::PackedSubfield;
40
41/// A transparent wrapper over an underlier holds one contiguous bit string.
42/// Cutting that same string into `FSub` scalars is exactly a [`PackedPrimitiveType`].
43impl<FSub, P> PackedExtension<FSub> for P
44where
45	FSub: BinaryField,
46	P: PackedField<Scalar: ExtensionField<FSub>> + WithUnderlier,
47	PackedPrimitiveType<P::Underlier, FSub>: PackedField<Scalar = FSub>,
48{
49	type PackedSubfield = PackedPrimitiveType<P::Underlier, FSub>;
50
51	#[inline]
52	fn cast_base(self) -> Self::PackedSubfield {
53		Self::PackedSubfield::from_underlier(self.to_underlier())
54	}
55
56	#[inline]
57	fn cast_base_mut(&mut self) -> &mut Self::PackedSubfield {
58		Self::PackedSubfield::from_underlier_ref_mut(self.to_underlier_ref_mut())
59	}
60
61	#[inline]
62	fn cast_ext(base: Self::PackedSubfield) -> Self {
63		Self::from_underlier(base.to_underlier())
64	}
65
66	#[inline]
67	fn cast_bases_mut(packed: &mut [Self]) -> &mut [Self::PackedSubfield] {
68		Self::PackedSubfield::from_underliers_ref_mut(Self::to_underliers_ref_mut(packed))
69	}
70}