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/// The packed subfield type sharing the same underlier as the packed extension field type `P`.
9///
10/// `P` and `PackedSubfield<P, FSub>` have the same in-memory representation, differing only in the
11/// scalar type and preserving the order of the smaller elements. This is what makes the reinterpret
12/// casts ([`cast_bases_mut`], [`cast_base_mut`], [`cast_ext`]) sound: the `FSub` scalars of
13/// `cast_bases_mut(exts)` are exactly the scalars yielded by
14/// `exts.iter().flat_map(|ext| ext.iter_bases())`.
15pub type PackedSubfield<P, FSub> = PackedPrimitiveType<<P as WithUnderlier>::Underlier, FSub>;
16
17/// Reinterpret a mutable slice of packed extension field elements as a mutable slice of the
18/// corresponding packed subfield elements.
19///
20/// The two slices share the same memory; `PackedSubfield<P, FSub>` has the same underlier as `P`.
21pub fn cast_bases_mut<FSub, P>(packed: &mut [P]) -> &mut [PackedSubfield<P, FSub>]
22where
23	FSub: BinaryField,
24	P: PackedField<Scalar: ExtensionField<FSub>> + WithUnderlier,
25	PackedSubfield<P, FSub>: PackedField<Scalar = FSub>,
26{
27	PackedSubfield::<P, FSub>::from_underliers_ref_mut(P::to_underliers_ref_mut(packed))
28}
29
30/// Reinterpret a mutable reference to a packed extension field element as a mutable reference to
31/// the corresponding packed subfield element.
32pub fn cast_base_mut<FSub, P>(packed: &mut P) -> &mut PackedSubfield<P, FSub>
33where
34	FSub: BinaryField,
35	P: PackedField<Scalar: ExtensionField<FSub>> + WithUnderlier,
36	PackedSubfield<P, FSub>: PackedField<Scalar = FSub>,
37{
38	PackedSubfield::<P, FSub>::from_underlier_ref_mut(packed.to_underlier_ref_mut())
39}
40
41/// Reinterpret a packed extension field element as the corresponding packed subfield element.
42pub fn cast_base<FSub, P>(ext: P) -> PackedSubfield<P, FSub>
43where
44	FSub: BinaryField,
45	P: PackedField<Scalar: ExtensionField<FSub>> + WithUnderlier,
46	PackedSubfield<P, FSub>: PackedField<Scalar = FSub>,
47{
48	PackedSubfield::<P, FSub>::from_underlier(ext.to_underlier())
49}
50
51/// Reinterpret a packed subfield element as the corresponding packed extension field element.
52pub fn cast_ext<FSub, P>(base: PackedSubfield<P, FSub>) -> P
53where
54	FSub: BinaryField,
55	P: PackedField<Scalar: ExtensionField<FSub>> + WithUnderlier,
56	PackedSubfield<P, FSub>: PackedField<Scalar = FSub>,
57{
58	P::from_underlier(base.to_underlier())
59}