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