p3_field/extension/
packed_binomial_extension.rs

1use alloc::vec::Vec;
2use core::array;
3use core::fmt::Debug;
4use core::iter::{Product, Sum};
5use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
6
7use itertools::Itertools;
8use p3_util::{flatten_to_base, reconstitute_from_base};
9use rand::distr::{Distribution, StandardUniform};
10use serde::{Deserialize, Serialize};
11
12use super::{BinomialExtensionField, binomial_mul, vector_add, vector_sub};
13use crate::extension::{BinomiallyExtendable, binomial_square};
14use crate::{
15    Algebra, BasedVectorSpace, Field, PackedField, PackedFieldExtension, PackedValue, Powers,
16    PrimeCharacteristicRing, field_to_array,
17};
18
19#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize, PartialOrd, Ord)]
20#[repr(transparent)] // Needed to make various casts safe.
21#[must_use]
22pub struct PackedBinomialExtensionField<F: Field, PF: PackedField<Scalar = F>, const D: usize> {
23    #[serde(
24        with = "p3_util::array_serialization",
25        bound(serialize = "PF: Serialize", deserialize = "PF: Deserialize<'de>")
26    )]
27    pub(crate) value: [PF; D],
28}
29
30impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> PackedBinomialExtensionField<F, PF, D> {
31    const fn new(value: [PF; D]) -> Self {
32        Self { value }
33    }
34}
35
36impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> Default
37    for PackedBinomialExtensionField<F, PF, D>
38{
39    #[inline]
40    fn default() -> Self {
41        Self {
42            value: array::from_fn(|_| PF::ZERO),
43        }
44    }
45}
46
47impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> From<BinomialExtensionField<F, D>>
48    for PackedBinomialExtensionField<F, PF, D>
49{
50    #[inline]
51    fn from(x: BinomialExtensionField<F, D>) -> Self {
52        Self {
53            value: x.value.map(Into::into),
54        }
55    }
56}
57
58impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> From<PF>
59    for PackedBinomialExtensionField<F, PF, D>
60{
61    #[inline]
62    fn from(x: PF) -> Self {
63        Self {
64            value: field_to_array(x),
65        }
66    }
67}
68
69impl<F: Field, PF: PackedField<Scalar = F>, const D: usize>
70    Distribution<PackedBinomialExtensionField<F, PF, D>> for StandardUniform
71where
72    Self: Distribution<PF>,
73{
74    #[inline]
75    fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> PackedBinomialExtensionField<F, PF, D> {
76        PackedBinomialExtensionField::new(array::from_fn(|_| self.sample(rng)))
77    }
78}
79
80impl<F: BinomiallyExtendable<D>, PF: PackedField<Scalar = F>, const D: usize>
81    Algebra<BinomialExtensionField<F, D>> for PackedBinomialExtensionField<F, PF, D>
82{
83}
84
85impl<F: BinomiallyExtendable<D>, PF: PackedField<Scalar = F>, const D: usize> Algebra<PF>
86    for PackedBinomialExtensionField<F, PF, D>
87{
88}
89
90impl<F, PF, const D: usize> PrimeCharacteristicRing for PackedBinomialExtensionField<F, PF, D>
91where
92    F: BinomiallyExtendable<D>,
93    PF: PackedField<Scalar = F>,
94{
95    type PrimeSubfield = PF::PrimeSubfield;
96
97    const ZERO: Self = Self {
98        value: [PF::ZERO; D],
99    };
100
101    const ONE: Self = Self {
102        value: field_to_array(PF::ONE),
103    };
104
105    const TWO: Self = Self {
106        value: field_to_array(PF::TWO),
107    };
108
109    const NEG_ONE: Self = Self {
110        value: field_to_array(PF::NEG_ONE),
111    };
112
113    #[inline]
114    fn from_prime_subfield(val: Self::PrimeSubfield) -> Self {
115        PF::from_prime_subfield(val).into()
116    }
117
118    #[inline]
119    fn from_bool(b: bool) -> Self {
120        PF::from_bool(b).into()
121    }
122
123    #[inline]
124    fn halve(&self) -> Self {
125        Self::new(self.value.map(|x| x.halve()))
126    }
127
128    #[inline(always)]
129    fn square(&self) -> Self {
130        let mut res = Self::default();
131        let w = F::W;
132        binomial_square(&self.value, &mut res.value, w);
133        res
134    }
135
136    #[inline]
137    fn mul_2exp_u64(&self, exp: u64) -> Self {
138        Self::new(self.value.map(|x| x.mul_2exp_u64(exp)))
139    }
140
141    #[inline]
142    fn div_2exp_u64(&self, exp: u64) -> Self {
143        Self::new(self.value.map(|x| x.div_2exp_u64(exp)))
144    }
145
146    #[inline]
147    fn zero_vec(len: usize) -> Vec<Self> {
148        // SAFETY: this is a repr(transparent) wrapper around an array.
149        unsafe { reconstitute_from_base(PF::zero_vec(len * D)) }
150    }
151}
152
153impl<F, PF, const D: usize> BasedVectorSpace<PF> for PackedBinomialExtensionField<F, PF, D>
154where
155    F: BinomiallyExtendable<D>,
156    PF: PackedField<Scalar = F>,
157{
158    const DIMENSION: usize = D;
159
160    #[inline]
161    fn as_basis_coefficients_slice(&self) -> &[PF] {
162        &self.value
163    }
164
165    #[inline]
166    fn from_basis_coefficients_fn<Fn: FnMut(usize) -> PF>(f: Fn) -> Self {
167        Self {
168            value: array::from_fn(f),
169        }
170    }
171
172    #[inline]
173    fn from_basis_coefficients_iter<I: ExactSizeIterator<Item = PF>>(mut iter: I) -> Option<Self> {
174        (iter.len() == D).then(|| Self::new(array::from_fn(|_| iter.next().unwrap()))) // The unwrap is safe as we just checked the length of iter.
175    }
176
177    #[inline]
178    fn flatten_to_base(vec: Vec<Self>) -> Vec<PF> {
179        unsafe {
180            // Safety:
181            // As `Self` is a `repr(transparent)`, it is stored identically in memory to `[PF; D]`
182            flatten_to_base(vec)
183        }
184    }
185
186    #[inline]
187    fn reconstitute_from_base(vec: Vec<PF>) -> Vec<Self> {
188        unsafe {
189            // Safety:
190            // As `Self` is a `repr(transparent)`, it is stored identically in memory to `[PF; D]`
191            reconstitute_from_base(vec)
192        }
193    }
194}
195
196impl<F, const D: usize> PackedFieldExtension<F, BinomialExtensionField<F, D>>
197    for PackedBinomialExtensionField<F, F::Packing, D>
198where
199    F: BinomiallyExtendable<D>,
200{
201    #[inline]
202    fn from_ext_slice(ext_slice: &[BinomialExtensionField<F, D>]) -> Self {
203        let width = F::Packing::WIDTH;
204        assert_eq!(ext_slice.len(), width);
205
206        let res = array::from_fn(|i| F::Packing::from_fn(|j| ext_slice[j].value[i]));
207        Self::new(res)
208    }
209
210    #[inline]
211    fn to_ext_iter(
212        iter: impl IntoIterator<Item = Self>,
213    ) -> impl Iterator<Item = BinomialExtensionField<F, D>> {
214        let width = F::Packing::WIDTH;
215        iter.into_iter().flat_map(move |x| {
216            (0..width).map(move |i| {
217                let values = array::from_fn(|j| x.value[j].as_slice()[i]);
218                BinomialExtensionField::new(values)
219            })
220        })
221    }
222
223    #[inline]
224    fn packed_ext_powers(base: BinomialExtensionField<F, D>) -> crate::Powers<Self> {
225        let width = F::Packing::WIDTH;
226        let powers = base.powers().take(width + 1).collect_vec();
227        // Transpose first WIDTH powers
228        let current = Self::from_ext_slice(&powers[..width]);
229
230        // Broadcast self^WIDTH
231        let multiplier = powers[width].into();
232
233        Powers {
234            base: multiplier,
235            current,
236        }
237    }
238}
239
240impl<F, PF, const D: usize> Neg for PackedBinomialExtensionField<F, PF, D>
241where
242    F: BinomiallyExtendable<D>,
243    PF: PackedField<Scalar = F>,
244{
245    type Output = Self;
246
247    #[inline]
248    fn neg(self) -> Self {
249        Self {
250            value: self.value.map(PF::neg),
251        }
252    }
253}
254
255impl<F, PF, const D: usize> Add for PackedBinomialExtensionField<F, PF, D>
256where
257    F: BinomiallyExtendable<D>,
258    PF: PackedField<Scalar = F>,
259{
260    type Output = Self;
261
262    #[inline]
263    fn add(self, rhs: Self) -> Self {
264        let value = vector_add(&self.value, &rhs.value);
265        Self { value }
266    }
267}
268
269impl<F, PF, const D: usize> Add<BinomialExtensionField<F, D>>
270    for PackedBinomialExtensionField<F, PF, D>
271where
272    F: BinomiallyExtendable<D>,
273    PF: PackedField<Scalar = F>,
274{
275    type Output = Self;
276
277    #[inline]
278    fn add(self, rhs: BinomialExtensionField<F, D>) -> Self {
279        let value = vector_add(&self.value, &rhs.value);
280        Self { value }
281    }
282}
283
284impl<F, PF, const D: usize> Add<PF> for PackedBinomialExtensionField<F, PF, D>
285where
286    F: BinomiallyExtendable<D>,
287    PF: PackedField<Scalar = F>,
288{
289    type Output = Self;
290
291    #[inline]
292    fn add(mut self, rhs: PF) -> Self {
293        self.value[0] += rhs;
294        self
295    }
296}
297
298impl<F, PF, const D: usize> AddAssign for PackedBinomialExtensionField<F, PF, D>
299where
300    F: BinomiallyExtendable<D>,
301    PF: PackedField<Scalar = F>,
302{
303    #[inline]
304    fn add_assign(&mut self, rhs: Self) {
305        for i in 0..D {
306            self.value[i] += rhs.value[i];
307        }
308    }
309}
310
311impl<F, PF, const D: usize> AddAssign<BinomialExtensionField<F, D>>
312    for PackedBinomialExtensionField<F, PF, D>
313where
314    F: BinomiallyExtendable<D>,
315    PF: PackedField<Scalar = F>,
316{
317    #[inline]
318    fn add_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
319        for i in 0..D {
320            self.value[i] += rhs.value[i];
321        }
322    }
323}
324
325impl<F, PF, const D: usize> AddAssign<PF> for PackedBinomialExtensionField<F, PF, D>
326where
327    F: BinomiallyExtendable<D>,
328    PF: PackedField<Scalar = F>,
329{
330    #[inline]
331    fn add_assign(&mut self, rhs: PF) {
332        self.value[0] += rhs;
333    }
334}
335
336impl<F, PF, const D: usize> Sum for PackedBinomialExtensionField<F, PF, D>
337where
338    F: BinomiallyExtendable<D>,
339    PF: PackedField<Scalar = F>,
340{
341    #[inline]
342    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
343        iter.reduce(|acc, x| acc + x).unwrap_or(Self::ZERO)
344    }
345}
346
347impl<F, PF, const D: usize> Sub for PackedBinomialExtensionField<F, PF, D>
348where
349    F: BinomiallyExtendable<D>,
350    PF: PackedField<Scalar = F>,
351{
352    type Output = Self;
353
354    #[inline]
355    fn sub(self, rhs: Self) -> Self {
356        let value = vector_sub(&self.value, &rhs.value);
357        Self { value }
358    }
359}
360
361impl<F, PF, const D: usize> Sub<BinomialExtensionField<F, D>>
362    for PackedBinomialExtensionField<F, PF, D>
363where
364    F: BinomiallyExtendable<D>,
365    PF: PackedField<Scalar = F>,
366{
367    type Output = Self;
368
369    #[inline]
370    fn sub(self, rhs: BinomialExtensionField<F, D>) -> Self {
371        let value = vector_sub(&self.value, &rhs.value);
372        Self { value }
373    }
374}
375
376impl<F, PF, const D: usize> Sub<PF> for PackedBinomialExtensionField<F, PF, D>
377where
378    F: BinomiallyExtendable<D>,
379    PF: PackedField<Scalar = F>,
380{
381    type Output = Self;
382
383    #[inline]
384    fn sub(self, rhs: PF) -> Self {
385        let mut res = self.value;
386        res[0] -= rhs;
387        Self { value: res }
388    }
389}
390
391impl<F, PF, const D: usize> SubAssign for PackedBinomialExtensionField<F, PF, D>
392where
393    F: BinomiallyExtendable<D>,
394    PF: PackedField<Scalar = F>,
395{
396    #[inline]
397    fn sub_assign(&mut self, rhs: Self) {
398        *self = *self - rhs;
399    }
400}
401
402impl<F, PF, const D: usize> SubAssign<BinomialExtensionField<F, D>>
403    for PackedBinomialExtensionField<F, PF, D>
404where
405    F: BinomiallyExtendable<D>,
406    PF: PackedField<Scalar = F>,
407{
408    #[inline]
409    fn sub_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
410        *self = *self - rhs;
411    }
412}
413
414impl<F, PF, const D: usize> SubAssign<PF> for PackedBinomialExtensionField<F, PF, D>
415where
416    F: BinomiallyExtendable<D>,
417    PF: PackedField<Scalar = F>,
418{
419    #[inline]
420    fn sub_assign(&mut self, rhs: PF) {
421        *self = *self - rhs;
422    }
423}
424
425impl<F, PF, const D: usize> Mul for PackedBinomialExtensionField<F, PF, D>
426where
427    F: BinomiallyExtendable<D>,
428    PF: PackedField<Scalar = F>,
429{
430    type Output = Self;
431
432    #[inline]
433    fn mul(self, rhs: Self) -> Self {
434        let a = self.value;
435        let b = rhs.value;
436        let mut res = Self::default();
437        let w = F::W;
438
439        binomial_mul::<F, PF, PF, D>(&a, &b, &mut res.value, w);
440
441        res
442    }
443}
444
445impl<F, PF, const D: usize> Mul<BinomialExtensionField<F, D>>
446    for PackedBinomialExtensionField<F, PF, D>
447where
448    F: BinomiallyExtendable<D>,
449    PF: PackedField<Scalar = F>,
450{
451    type Output = Self;
452
453    #[inline]
454    fn mul(self, rhs: BinomialExtensionField<F, D>) -> Self {
455        let a = self.value;
456        let b = rhs.value;
457        let mut res = Self::default();
458        let w = F::W;
459
460        binomial_mul(&a, &b, &mut res.value, w);
461
462        res
463    }
464}
465
466impl<F, PF, const D: usize> Mul<PF> for PackedBinomialExtensionField<F, PF, D>
467where
468    F: BinomiallyExtendable<D>,
469    PF: PackedField<Scalar = F>,
470{
471    type Output = Self;
472
473    #[inline]
474    fn mul(self, rhs: PF) -> Self {
475        Self {
476            value: self.value.map(|x| x * rhs),
477        }
478    }
479}
480
481impl<F, PF, const D: usize> Product for PackedBinomialExtensionField<F, PF, D>
482where
483    F: BinomiallyExtendable<D>,
484    PF: PackedField<Scalar = F>,
485{
486    #[inline]
487    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
488        iter.reduce(|acc, x| acc * x).unwrap_or(Self::ZERO)
489    }
490}
491
492impl<F, PF, const D: usize> MulAssign for PackedBinomialExtensionField<F, PF, D>
493where
494    F: BinomiallyExtendable<D>,
495    PF: PackedField<Scalar = F>,
496{
497    #[inline]
498    fn mul_assign(&mut self, rhs: Self) {
499        *self = *self * rhs;
500    }
501}
502
503impl<F, PF, const D: usize> MulAssign<BinomialExtensionField<F, D>>
504    for PackedBinomialExtensionField<F, PF, D>
505where
506    F: BinomiallyExtendable<D>,
507    PF: PackedField<Scalar = F>,
508{
509    #[inline]
510    fn mul_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
511        *self = *self * rhs;
512    }
513}
514
515impl<F, PF, const D: usize> MulAssign<PF> for PackedBinomialExtensionField<F, PF, D>
516where
517    F: BinomiallyExtendable<D>,
518    PF: PackedField<Scalar = F>,
519{
520    #[inline]
521    fn mul_assign(&mut self, rhs: PF) {
522        *self = *self * rhs;
523    }
524}