Skip to main content

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