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