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 packed_ext_powers(base: BinomialExtensionField<F, D>) -> crate::Powers<Self> {
212        let width = F::Packing::WIDTH;
213        let powers = base.powers().take(width + 1).collect_vec();
214        // Transpose first WIDTH powers
215        let current = Self::from_ext_slice(&powers[..width]);
216
217        // Broadcast self^WIDTH
218        let multiplier = powers[width].into();
219
220        Powers {
221            base: multiplier,
222            current,
223        }
224    }
225}
226
227impl<F, PF, const D: usize> Neg for PackedBinomialExtensionField<F, PF, D>
228where
229    F: BinomiallyExtendable<D>,
230    PF: PackedField<Scalar = F>,
231{
232    type Output = Self;
233
234    #[inline]
235    fn neg(self) -> Self {
236        Self {
237            value: self.value.map(PF::neg),
238        }
239    }
240}
241
242impl<F, PF, const D: usize> Add for PackedBinomialExtensionField<F, PF, D>
243where
244    F: BinomiallyExtendable<D>,
245    PF: PackedField<Scalar = F>,
246{
247    type Output = Self;
248
249    #[inline]
250    fn add(self, rhs: Self) -> Self {
251        let value = vector_add(&self.value, &rhs.value);
252        Self { value }
253    }
254}
255
256impl<F, PF, const D: usize> Add<BinomialExtensionField<F, D>>
257    for PackedBinomialExtensionField<F, PF, D>
258where
259    F: BinomiallyExtendable<D>,
260    PF: PackedField<Scalar = F>,
261{
262    type Output = Self;
263
264    #[inline]
265    fn add(self, rhs: BinomialExtensionField<F, D>) -> Self {
266        let value = vector_add(&self.value, &rhs.value);
267        Self { value }
268    }
269}
270
271impl<F, PF, const D: usize> Add<PF> for PackedBinomialExtensionField<F, PF, D>
272where
273    F: BinomiallyExtendable<D>,
274    PF: PackedField<Scalar = F>,
275{
276    type Output = Self;
277
278    #[inline]
279    fn add(mut self, rhs: PF) -> Self {
280        self.value[0] += rhs;
281        self
282    }
283}
284
285impl<F, PF, const D: usize> AddAssign for PackedBinomialExtensionField<F, PF, D>
286where
287    F: BinomiallyExtendable<D>,
288    PF: PackedField<Scalar = F>,
289{
290    #[inline]
291    fn add_assign(&mut self, rhs: Self) {
292        for i in 0..D {
293            self.value[i] += rhs.value[i];
294        }
295    }
296}
297
298impl<F, PF, const D: usize> AddAssign<BinomialExtensionField<F, D>>
299    for PackedBinomialExtensionField<F, PF, D>
300where
301    F: BinomiallyExtendable<D>,
302    PF: PackedField<Scalar = F>,
303{
304    #[inline]
305    fn add_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
306        for i in 0..D {
307            self.value[i] += rhs.value[i];
308        }
309    }
310}
311
312impl<F, PF, const D: usize> AddAssign<PF> 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: PF) {
319        self.value[0] += rhs;
320    }
321}
322
323impl<F, PF, const D: usize> Sum for PackedBinomialExtensionField<F, PF, D>
324where
325    F: BinomiallyExtendable<D>,
326    PF: PackedField<Scalar = F>,
327{
328    #[inline]
329    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
330        iter.reduce(|acc, x| acc + x).unwrap_or(Self::ZERO)
331    }
332}
333
334impl<F, PF, const D: usize> Sub for PackedBinomialExtensionField<F, PF, D>
335where
336    F: BinomiallyExtendable<D>,
337    PF: PackedField<Scalar = F>,
338{
339    type Output = Self;
340
341    #[inline]
342    fn sub(self, rhs: Self) -> Self {
343        let value = vector_sub(&self.value, &rhs.value);
344        Self { value }
345    }
346}
347
348impl<F, PF, const D: usize> Sub<BinomialExtensionField<F, D>>
349    for PackedBinomialExtensionField<F, PF, D>
350where
351    F: BinomiallyExtendable<D>,
352    PF: PackedField<Scalar = F>,
353{
354    type Output = Self;
355
356    #[inline]
357    fn sub(self, rhs: BinomialExtensionField<F, D>) -> Self {
358        let value = vector_sub(&self.value, &rhs.value);
359        Self { value }
360    }
361}
362
363impl<F, PF, const D: usize> Sub<PF> for PackedBinomialExtensionField<F, PF, D>
364where
365    F: BinomiallyExtendable<D>,
366    PF: PackedField<Scalar = F>,
367{
368    type Output = Self;
369
370    #[inline]
371    fn sub(self, rhs: PF) -> Self {
372        let mut res = self.value;
373        res[0] -= rhs;
374        Self { value: res }
375    }
376}
377
378impl<F, PF, const D: usize> SubAssign for PackedBinomialExtensionField<F, PF, D>
379where
380    F: BinomiallyExtendable<D>,
381    PF: PackedField<Scalar = F>,
382{
383    #[inline]
384    fn sub_assign(&mut self, rhs: Self) {
385        *self = *self - rhs;
386    }
387}
388
389impl<F, PF, const D: usize> SubAssign<BinomialExtensionField<F, D>>
390    for PackedBinomialExtensionField<F, PF, D>
391where
392    F: BinomiallyExtendable<D>,
393    PF: PackedField<Scalar = F>,
394{
395    #[inline]
396    fn sub_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
397        *self = *self - rhs;
398    }
399}
400
401impl<F, PF, const D: usize> SubAssign<PF> for PackedBinomialExtensionField<F, PF, D>
402where
403    F: BinomiallyExtendable<D>,
404    PF: PackedField<Scalar = F>,
405{
406    #[inline]
407    fn sub_assign(&mut self, rhs: PF) {
408        *self = *self - rhs;
409    }
410}
411
412impl<F, PF, const D: usize> Mul for PackedBinomialExtensionField<F, PF, D>
413where
414    F: BinomiallyExtendable<D>,
415    PF: PackedField<Scalar = F>,
416{
417    type Output = Self;
418
419    #[inline]
420    fn mul(self, rhs: Self) -> Self {
421        let a = self.value;
422        let b = rhs.value;
423        let mut res = Self::default();
424        let w = F::W;
425
426        binomial_mul::<F, PF, PF, D>(&a, &b, &mut res.value, w);
427
428        res
429    }
430}
431
432impl<F, PF, const D: usize> Mul<BinomialExtensionField<F, D>>
433    for PackedBinomialExtensionField<F, PF, D>
434where
435    F: BinomiallyExtendable<D>,
436    PF: PackedField<Scalar = F>,
437{
438    type Output = Self;
439
440    #[inline]
441    fn mul(self, rhs: BinomialExtensionField<F, D>) -> Self {
442        let a = self.value;
443        let b = rhs.value;
444        let mut res = Self::default();
445        let w = F::W;
446
447        binomial_mul(&a, &b, &mut res.value, w);
448
449        res
450    }
451}
452
453impl<F, PF, const D: usize> Mul<PF> for PackedBinomialExtensionField<F, PF, D>
454where
455    F: BinomiallyExtendable<D>,
456    PF: PackedField<Scalar = F>,
457{
458    type Output = Self;
459
460    #[inline]
461    fn mul(self, rhs: PF) -> Self {
462        Self {
463            value: self.value.map(|x| x * rhs),
464        }
465    }
466}
467
468impl<F, PF, const D: usize> Product for PackedBinomialExtensionField<F, PF, D>
469where
470    F: BinomiallyExtendable<D>,
471    PF: PackedField<Scalar = F>,
472{
473    #[inline]
474    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
475        iter.reduce(|acc, x| acc * x).unwrap_or(Self::ZERO)
476    }
477}
478
479impl<F, PF, const D: usize> MulAssign for PackedBinomialExtensionField<F, PF, D>
480where
481    F: BinomiallyExtendable<D>,
482    PF: PackedField<Scalar = F>,
483{
484    #[inline]
485    fn mul_assign(&mut self, rhs: Self) {
486        *self = *self * rhs;
487    }
488}
489
490impl<F, PF, const D: usize> MulAssign<BinomialExtensionField<F, D>>
491    for PackedBinomialExtensionField<F, PF, D>
492where
493    F: BinomiallyExtendable<D>,
494    PF: PackedField<Scalar = F>,
495{
496    #[inline]
497    fn mul_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
498        *self = *self * rhs;
499    }
500}
501
502impl<F, PF, const D: usize> MulAssign<PF> for PackedBinomialExtensionField<F, PF, D>
503where
504    F: BinomiallyExtendable<D>,
505    PF: PackedField<Scalar = F>,
506{
507    #[inline]
508    fn mul_assign(&mut self, rhs: PF) {
509        *self = *self * rhs;
510    }
511}