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 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 let current = Self::from_ext_slice(&powers[..width]);
229
230 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}