1use alloc::vec::Vec;
2use core::array;
3use core::iter::{Product, Sum};
4use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5
6use p3_util::{flatten_to_base, reconstitute_from_base};
7use rand::distr::{Distribution, StandardUniform};
8
9use super::{BinomialExtensionField, PackedExtField, binomial_mul, vector_add, vector_sub};
10use crate::extension::{Binomial, BinomiallyExtendable, binomial_square};
11use crate::{
12 Algebra, BasedVectorSpace, Dup, Field, PackedField, PackedFieldExtension, PackedValue, Powers,
13 PrimeCharacteristicRing, field_to_array,
14};
15
16pub type PackedBinomialExtensionField<F, PF, const D: usize> =
20 PackedExtField<F, PF, D, Binomial<F>>;
21
22impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> Default
23 for PackedBinomialExtensionField<F, PF, D>
24{
25 #[inline]
26 fn default() -> Self {
27 Self::new(array::from_fn(|_| PF::ZERO))
28 }
29}
30
31impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> From<BinomialExtensionField<F, D>>
32 for PackedBinomialExtensionField<F, PF, D>
33{
34 #[inline]
35 fn from(x: BinomialExtensionField<F, D>) -> Self {
36 Self::new(x.value.map(Into::into))
37 }
38}
39
40impl<F: Field, PF: PackedField<Scalar = F>, const D: usize> From<PF>
41 for PackedBinomialExtensionField<F, PF, D>
42{
43 #[inline]
44 fn from(x: PF) -> Self {
45 Self::new(field_to_array(x))
46 }
47}
48
49impl<F: Field, PF: PackedField<Scalar = F>, const D: usize>
50 Distribution<PackedBinomialExtensionField<F, PF, D>> for StandardUniform
51where
52 Self: Distribution<PF>,
53{
54 #[inline]
55 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> PackedBinomialExtensionField<F, PF, D> {
56 PackedBinomialExtensionField::new(array::from_fn(|_| self.sample(rng)))
57 }
58}
59
60impl<F: BinomiallyExtendable<D>, PF: PackedField<Scalar = F>, const D: usize>
61 Algebra<BinomialExtensionField<F, D>> for PackedBinomialExtensionField<F, PF, D>
62{
63}
64
65impl<F: BinomiallyExtendable<D>, PF: PackedField<Scalar = F>, const D: usize> Algebra<PF>
66 for PackedBinomialExtensionField<F, PF, D>
67{
68 #[inline]
69 fn mixed_dot_product<const N: usize>(a: &[Self; N], f: &[PF; N]) -> Self
70 where
71 PF: Dup,
72 {
73 let mut result = Self::default();
75
76 for k in 0..D {
78 let coord_k: [PF; N] = core::array::from_fn(|i| a[i].value[k]);
82
83 result.value[k] = PF::dot_product::<N>(&coord_k, f);
88 }
89
90 result
91 }
92}
93
94impl<F, PF, const D: usize> PrimeCharacteristicRing for PackedBinomialExtensionField<F, PF, D>
95where
96 F: BinomiallyExtendable<D>,
97 PF: PackedField<Scalar = F>,
98{
99 type PrimeSubfield = PF::PrimeSubfield;
100
101 const ZERO: Self = Self::new([PF::ZERO; D]);
102
103 const ONE: Self = Self::new(field_to_array(PF::ONE));
104
105 const TWO: Self = Self::new(field_to_array(PF::TWO));
106
107 const NEG_ONE: Self = Self::new(field_to_array(PF::NEG_ONE));
108
109 #[inline]
110 fn from_prime_subfield(val: Self::PrimeSubfield) -> Self {
111 PF::from_prime_subfield(val).into()
112 }
113
114 #[inline]
115 fn from_bool(b: bool) -> Self {
116 PF::from_bool(b).into()
117 }
118
119 #[inline]
120 fn halve(&self) -> Self {
121 Self::new(self.value.map(|x| x.halve()))
122 }
123
124 #[inline(always)]
125 fn square(&self) -> Self {
126 let mut res = Self::default();
127 let w = F::W;
128 binomial_square(&self.value, &mut res.value, w);
129 res
130 }
131
132 #[inline]
133 fn mul_2exp_u64(&self, exp: u64) -> Self {
134 Self::new(self.value.map(|x| x.mul_2exp_u64(exp)))
135 }
136
137 #[inline]
138 fn div_2exp_u64(&self, exp: u64) -> Self {
139 Self::new(self.value.map(|x| x.div_2exp_u64(exp)))
140 }
141
142 #[inline]
143 fn zero_vec(len: usize) -> Vec<Self> {
144 unsafe { reconstitute_from_base(PF::zero_vec(len * D)) }
146 }
147}
148
149impl<F, PF, const D: usize> BasedVectorSpace<PF> for PackedBinomialExtensionField<F, PF, D>
150where
151 F: BinomiallyExtendable<D>,
152 PF: PackedField<Scalar = F>,
153{
154 const DIMENSION: usize = D;
155
156 #[inline]
157 fn as_basis_coefficients_slice(&self) -> &[PF] {
158 &self.value
159 }
160
161 #[inline]
162 fn from_basis_coefficients_fn<Fn: FnMut(usize) -> PF>(f: Fn) -> Self {
163 Self::new(array::from_fn(f))
164 }
165
166 #[inline]
167 fn from_basis_coefficients_iter<I: ExactSizeIterator<Item = PF>>(mut iter: I) -> Option<Self> {
168 (iter.len() == D).then(|| Self::new(array::from_fn(|_| iter.next().unwrap()))) }
170
171 #[inline]
172 fn flatten_to_base(vec: Vec<Self>) -> Vec<PF> {
173 unsafe {
174 flatten_to_base(vec)
177 }
178 }
179
180 #[inline]
181 fn reconstitute_from_base(vec: Vec<PF>) -> Vec<Self> {
182 unsafe {
183 reconstitute_from_base(vec)
186 }
187 }
188}
189
190impl<F, const D: usize> PackedFieldExtension<F, BinomialExtensionField<F, D>>
191 for PackedBinomialExtensionField<F, F::Packing, D>
192where
193 F: BinomiallyExtendable<D>,
194{
195 #[inline]
196 fn from_ext_fn(f: impl Fn(usize) -> BinomialExtensionField<F, D>) -> Self {
197 Self::new(F::Packing::pack_columns_fn(|lane| f(lane).value))
198 }
199
200 #[inline]
201 fn packed_ext_powers(base: BinomialExtensionField<F, D>) -> crate::Powers<Self> {
202 let width = F::Packing::WIDTH;
203 let powers = base.powers().collect_n(width + 1);
204 let current = Self::from_ext_slice(&powers[..width]);
206
207 let multiplier = powers[width].into();
209
210 Powers {
211 base: multiplier,
212 current,
213 }
214 }
215}
216
217impl<F, PF, const D: usize> Neg for PackedBinomialExtensionField<F, PF, D>
218where
219 F: BinomiallyExtendable<D>,
220 PF: PackedField<Scalar = F>,
221{
222 type Output = Self;
223
224 #[inline]
225 fn neg(self) -> Self {
226 Self::new(self.value.map(PF::neg))
227 }
228}
229
230impl<F, PF, const D: usize> Add for PackedBinomialExtensionField<F, PF, D>
231where
232 F: BinomiallyExtendable<D>,
233 PF: PackedField<Scalar = F>,
234{
235 type Output = Self;
236
237 #[inline]
238 fn add(self, rhs: Self) -> Self {
239 let value = vector_add(&self.value, &rhs.value);
240 Self::new(value)
241 }
242}
243
244impl<F, PF, const D: usize> Add<BinomialExtensionField<F, D>>
245 for PackedBinomialExtensionField<F, PF, D>
246where
247 F: BinomiallyExtendable<D>,
248 PF: PackedField<Scalar = F>,
249{
250 type Output = Self;
251
252 #[inline]
253 fn add(self, rhs: BinomialExtensionField<F, D>) -> Self {
254 let value = vector_add(&self.value, &rhs.value);
255 Self::new(value)
256 }
257}
258
259impl<F, PF, const D: usize> Add<PF> for PackedBinomialExtensionField<F, PF, D>
260where
261 F: BinomiallyExtendable<D>,
262 PF: PackedField<Scalar = F>,
263{
264 type Output = Self;
265
266 #[inline]
267 fn add(mut self, rhs: PF) -> Self {
268 self.value[0] += rhs;
269 self
270 }
271}
272
273impl<F, PF, const D: usize> AddAssign for PackedBinomialExtensionField<F, PF, D>
274where
275 F: BinomiallyExtendable<D>,
276 PF: PackedField<Scalar = F>,
277{
278 #[inline]
279 fn add_assign(&mut self, rhs: Self) {
280 for i in 0..D {
281 self.value[i] += rhs.value[i];
282 }
283 }
284}
285
286impl<F, PF, const D: usize> AddAssign<BinomialExtensionField<F, D>>
287 for PackedBinomialExtensionField<F, PF, D>
288where
289 F: BinomiallyExtendable<D>,
290 PF: PackedField<Scalar = F>,
291{
292 #[inline]
293 fn add_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
294 for i in 0..D {
295 self.value[i] += rhs.value[i];
296 }
297 }
298}
299
300impl<F, PF, const D: usize> AddAssign<PF> for PackedBinomialExtensionField<F, PF, D>
301where
302 F: BinomiallyExtendable<D>,
303 PF: PackedField<Scalar = F>,
304{
305 #[inline]
306 fn add_assign(&mut self, rhs: PF) {
307 self.value[0] += rhs;
308 }
309}
310
311impl<F, PF, const D: usize> Sum for PackedBinomialExtensionField<F, PF, D>
312where
313 F: BinomiallyExtendable<D>,
314 PF: PackedField<Scalar = F>,
315{
316 #[inline]
317 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
318 iter.reduce(|acc, x| acc + x).unwrap_or(Self::ZERO)
319 }
320}
321
322impl<F, PF, const D: usize> Sub for PackedBinomialExtensionField<F, PF, D>
323where
324 F: BinomiallyExtendable<D>,
325 PF: PackedField<Scalar = F>,
326{
327 type Output = Self;
328
329 #[inline]
330 fn sub(self, rhs: Self) -> Self {
331 let value = vector_sub(&self.value, &rhs.value);
332 Self::new(value)
333 }
334}
335
336impl<F, PF, const D: usize> Sub<BinomialExtensionField<F, D>>
337 for PackedBinomialExtensionField<F, PF, D>
338where
339 F: BinomiallyExtendable<D>,
340 PF: PackedField<Scalar = F>,
341{
342 type Output = Self;
343
344 #[inline]
345 fn sub(self, rhs: BinomialExtensionField<F, D>) -> Self {
346 let value = vector_sub(&self.value, &rhs.value);
347 Self::new(value)
348 }
349}
350
351impl<F, PF, const D: usize> Sub<PF> for PackedBinomialExtensionField<F, PF, D>
352where
353 F: BinomiallyExtendable<D>,
354 PF: PackedField<Scalar = F>,
355{
356 type Output = Self;
357
358 #[inline]
359 fn sub(self, rhs: PF) -> Self {
360 let mut res = self.value;
361 res[0] -= rhs;
362 Self::new(res)
363 }
364}
365
366impl<F, PF, const D: usize> SubAssign for PackedBinomialExtensionField<F, PF, D>
367where
368 F: BinomiallyExtendable<D>,
369 PF: PackedField<Scalar = F>,
370{
371 #[inline]
372 fn sub_assign(&mut self, rhs: Self) {
373 *self = *self - rhs;
374 }
375}
376
377impl<F, PF, const D: usize> SubAssign<BinomialExtensionField<F, D>>
378 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: BinomialExtensionField<F, D>) {
385 *self = *self - rhs;
386 }
387}
388
389impl<F, PF, const D: usize> SubAssign<PF> 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: PF) {
396 *self = *self - rhs;
397 }
398}
399
400impl<F, PF, const D: usize> Mul for PackedBinomialExtensionField<F, PF, D>
401where
402 F: BinomiallyExtendable<D>,
403 PF: PackedField<Scalar = F>,
404{
405 type Output = Self;
406
407 #[inline]
408 fn mul(self, rhs: Self) -> Self {
409 let a = self.value;
410 let b = rhs.value;
411 let mut res = Self::default();
412 let w = F::W;
413
414 binomial_mul::<F, PF, PF, D>(&a, &b, &mut res.value, w);
415
416 res
417 }
418}
419
420impl<F, PF, const D: usize> Mul<BinomialExtensionField<F, D>>
421 for PackedBinomialExtensionField<F, PF, D>
422where
423 F: BinomiallyExtendable<D>,
424 PF: PackedField<Scalar = F>,
425{
426 type Output = Self;
427
428 #[inline]
429 fn mul(self, rhs: BinomialExtensionField<F, D>) -> Self {
430 let a = self.value;
431 let b = rhs.value;
432 let mut res = Self::default();
433 let w = F::W;
434
435 binomial_mul(&a, &b, &mut res.value, w);
436
437 res
438 }
439}
440
441impl<F, PF, const D: usize> Mul<PF> for PackedBinomialExtensionField<F, PF, D>
442where
443 F: BinomiallyExtendable<D>,
444 PF: PackedField<Scalar = F>,
445{
446 type Output = Self;
447
448 #[inline]
449 fn mul(self, rhs: PF) -> Self {
450 Self::new(self.value.map(|x| x * rhs))
451 }
452}
453
454impl<F, PF, const D: usize> Product for PackedBinomialExtensionField<F, PF, D>
455where
456 F: BinomiallyExtendable<D>,
457 PF: PackedField<Scalar = F>,
458{
459 #[inline]
460 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
461 iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE)
462 }
463}
464
465impl<F, PF, const D: usize> MulAssign for PackedBinomialExtensionField<F, PF, D>
466where
467 F: BinomiallyExtendable<D>,
468 PF: PackedField<Scalar = F>,
469{
470 #[inline]
471 fn mul_assign(&mut self, rhs: Self) {
472 *self = *self * rhs;
473 }
474}
475
476impl<F, PF, const D: usize> MulAssign<BinomialExtensionField<F, D>>
477 for PackedBinomialExtensionField<F, PF, D>
478where
479 F: BinomiallyExtendable<D>,
480 PF: PackedField<Scalar = F>,
481{
482 #[inline]
483 fn mul_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
484 *self = *self * rhs;
485 }
486}
487
488impl<F, PF, const D: usize> MulAssign<PF> for PackedBinomialExtensionField<F, PF, D>
489where
490 F: BinomiallyExtendable<D>,
491 PF: PackedField<Scalar = F>,
492{
493 #[inline]
494 fn mul_assign(&mut self, rhs: PF) {
495 *self = *self * rhs;
496 }
497}
498
499impl<F, PF, const D: usize> Div<BinomialExtensionField<F, D>>
500 for PackedBinomialExtensionField<F, PF, D>
501where
502 F: BinomiallyExtendable<D>,
503 PF: PackedField<Scalar = F>,
504{
505 type Output = Self;
506
507 #[allow(clippy::suspicious_arithmetic_impl)]
508 #[inline]
509 fn div(self, rhs: BinomialExtensionField<F, D>) -> Self {
510 self * Self::from(rhs.inverse())
511 }
512}
513
514impl<F, PF, const D: usize> DivAssign<BinomialExtensionField<F, D>>
515 for PackedBinomialExtensionField<F, PF, D>
516where
517 F: BinomiallyExtendable<D>,
518 PF: PackedField<Scalar = F>,
519{
520 #[inline]
521 fn div_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
522 *self = *self / rhs;
523 }
524}
525
526impl<F: BinomiallyExtendable<D>, const D: usize> Div
527 for PackedBinomialExtensionField<F, F::Packing, D>
528{
529 type Output = Self;
530
531 #[allow(clippy::suspicious_arithmetic_impl)]
532 #[inline]
533 fn div(self, rhs: Self) -> Self {
534 self * crate::invert_packed_extension::<F, BinomialExtensionField<F, D>>(rhs)
535 }
536}
537
538impl<F: BinomiallyExtendable<D>, const D: usize> DivAssign
539 for PackedBinomialExtensionField<F, F::Packing, D>
540{
541 #[inline]
542 fn div_assign(&mut self, rhs: Self) {
543 *self = *self / rhs;
544 }
545}