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)] #[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 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()))) }
176
177 #[inline]
178 fn flatten_to_base(vec: Vec<Self>) -> Vec<PF> {
179 unsafe {
180 flatten_to_base(vec)
183 }
184 }
185
186 #[inline]
187 fn reconstitute_from_base(vec: Vec<PF>) -> Vec<Self> {
188 unsafe {
189 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 let current = Self::from_ext_slice(&powers[..width]);
216
217 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}