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 add_assign_lane(&mut self, lane: usize, value: BinomialExtensionField<F, D>) {
202 for (coeff, v) in self.value.iter_mut().zip(value.value) {
204 coeff.as_slice_mut()[lane] += v;
205 }
206 }
207
208 #[inline]
209 fn packed_ext_powers(base: BinomialExtensionField<F, D>) -> crate::Powers<Self> {
210 let width = F::Packing::WIDTH;
211 let powers = base.powers().collect_n(width + 1);
212 let current = Self::from_ext_slice(&powers[..width]);
214
215 let multiplier = powers[width].into();
217
218 Powers {
219 base: multiplier,
220 current,
221 }
222 }
223}
224
225impl<F, PF, const D: usize> Neg for PackedBinomialExtensionField<F, PF, D>
226where
227 F: BinomiallyExtendable<D>,
228 PF: PackedField<Scalar = F>,
229{
230 type Output = Self;
231
232 #[inline]
233 fn neg(self) -> Self {
234 Self::new(self.value.map(PF::neg))
235 }
236}
237
238impl<F, PF, const D: usize> Add 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 add(self, rhs: Self) -> Self {
247 let value = vector_add(&self.value, &rhs.value);
248 Self::new(value)
249 }
250}
251
252impl<F, PF, const D: usize> Add<BinomialExtensionField<F, D>>
253 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: BinomialExtensionField<F, D>) -> Self {
262 let value = vector_add(&self.value, &rhs.value);
263 Self::new(value)
264 }
265}
266
267impl<F, PF, const D: usize> Add<PF> for PackedBinomialExtensionField<F, PF, D>
268where
269 F: BinomiallyExtendable<D>,
270 PF: PackedField<Scalar = F>,
271{
272 type Output = Self;
273
274 #[inline]
275 fn add(mut self, rhs: PF) -> Self {
276 self.value[0] += rhs;
277 self
278 }
279}
280
281impl<F, PF, const D: usize> AddAssign for PackedBinomialExtensionField<F, PF, D>
282where
283 F: BinomiallyExtendable<D>,
284 PF: PackedField<Scalar = F>,
285{
286 #[inline]
287 fn add_assign(&mut self, rhs: Self) {
288 for i in 0..D {
289 self.value[i] += rhs.value[i];
290 }
291 }
292}
293
294impl<F, PF, const D: usize> AddAssign<BinomialExtensionField<F, D>>
295 for PackedBinomialExtensionField<F, PF, D>
296where
297 F: BinomiallyExtendable<D>,
298 PF: PackedField<Scalar = F>,
299{
300 #[inline]
301 fn add_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
302 for i in 0..D {
303 self.value[i] += rhs.value[i];
304 }
305 }
306}
307
308impl<F, PF, const D: usize> AddAssign<PF> for PackedBinomialExtensionField<F, PF, D>
309where
310 F: BinomiallyExtendable<D>,
311 PF: PackedField<Scalar = F>,
312{
313 #[inline]
314 fn add_assign(&mut self, rhs: PF) {
315 self.value[0] += rhs;
316 }
317}
318
319impl<F, PF, const D: usize> Sum for PackedBinomialExtensionField<F, PF, D>
320where
321 F: BinomiallyExtendable<D>,
322 PF: PackedField<Scalar = F>,
323{
324 #[inline]
325 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
326 iter.reduce(|acc, x| acc + x).unwrap_or(Self::ZERO)
327 }
328}
329
330impl<F, PF, const D: usize> Sub for PackedBinomialExtensionField<F, PF, D>
331where
332 F: BinomiallyExtendable<D>,
333 PF: PackedField<Scalar = F>,
334{
335 type Output = Self;
336
337 #[inline]
338 fn sub(self, rhs: Self) -> Self {
339 let value = vector_sub(&self.value, &rhs.value);
340 Self::new(value)
341 }
342}
343
344impl<F, PF, const D: usize> Sub<BinomialExtensionField<F, D>>
345 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: BinomialExtensionField<F, D>) -> Self {
354 let value = vector_sub(&self.value, &rhs.value);
355 Self::new(value)
356 }
357}
358
359impl<F, PF, const D: usize> Sub<PF> for PackedBinomialExtensionField<F, PF, D>
360where
361 F: BinomiallyExtendable<D>,
362 PF: PackedField<Scalar = F>,
363{
364 type Output = Self;
365
366 #[inline]
367 fn sub(self, rhs: PF) -> Self {
368 let mut res = self.value;
369 res[0] -= rhs;
370 Self::new(res)
371 }
372}
373
374impl<F, PF, const D: usize> SubAssign for PackedBinomialExtensionField<F, PF, D>
375where
376 F: BinomiallyExtendable<D>,
377 PF: PackedField<Scalar = F>,
378{
379 #[inline]
380 fn sub_assign(&mut self, rhs: Self) {
381 *self = *self - rhs;
382 }
383}
384
385impl<F, PF, const D: usize> SubAssign<BinomialExtensionField<F, D>>
386 for PackedBinomialExtensionField<F, PF, D>
387where
388 F: BinomiallyExtendable<D>,
389 PF: PackedField<Scalar = F>,
390{
391 #[inline]
392 fn sub_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
393 *self = *self - rhs;
394 }
395}
396
397impl<F, PF, const D: usize> SubAssign<PF> for PackedBinomialExtensionField<F, PF, D>
398where
399 F: BinomiallyExtendable<D>,
400 PF: PackedField<Scalar = F>,
401{
402 #[inline]
403 fn sub_assign(&mut self, rhs: PF) {
404 *self = *self - rhs;
405 }
406}
407
408impl<F, PF, const D: usize> Mul for PackedBinomialExtensionField<F, PF, D>
409where
410 F: BinomiallyExtendable<D>,
411 PF: PackedField<Scalar = F>,
412{
413 type Output = Self;
414
415 #[inline]
416 fn mul(self, rhs: Self) -> Self {
417 let a = self.value;
418 let b = rhs.value;
419 let mut res = Self::default();
420 let w = F::W;
421
422 binomial_mul::<F, PF, PF, D>(&a, &b, &mut res.value, w);
423
424 res
425 }
426}
427
428impl<F, PF, const D: usize> Mul<BinomialExtensionField<F, D>>
429 for PackedBinomialExtensionField<F, PF, D>
430where
431 F: BinomiallyExtendable<D>,
432 PF: PackedField<Scalar = F>,
433{
434 type Output = Self;
435
436 #[inline]
437 fn mul(self, rhs: BinomialExtensionField<F, D>) -> Self {
438 let a = self.value;
439 let b = rhs.value;
440 let mut res = Self::default();
441 let w = F::W;
442
443 binomial_mul(&a, &b, &mut res.value, w);
444
445 res
446 }
447}
448
449impl<F, PF, const D: usize> Mul<PF> for PackedBinomialExtensionField<F, PF, D>
450where
451 F: BinomiallyExtendable<D>,
452 PF: PackedField<Scalar = F>,
453{
454 type Output = Self;
455
456 #[inline]
457 fn mul(self, rhs: PF) -> Self {
458 Self::new(self.value.map(|x| x * rhs))
459 }
460}
461
462impl<F, PF, const D: usize> Product for PackedBinomialExtensionField<F, PF, D>
463where
464 F: BinomiallyExtendable<D>,
465 PF: PackedField<Scalar = F>,
466{
467 #[inline]
468 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
469 iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE)
470 }
471}
472
473impl<F, PF, const D: usize> MulAssign for PackedBinomialExtensionField<F, PF, D>
474where
475 F: BinomiallyExtendable<D>,
476 PF: PackedField<Scalar = F>,
477{
478 #[inline]
479 fn mul_assign(&mut self, rhs: Self) {
480 *self = *self * rhs;
481 }
482}
483
484impl<F, PF, const D: usize> MulAssign<BinomialExtensionField<F, D>>
485 for PackedBinomialExtensionField<F, PF, D>
486where
487 F: BinomiallyExtendable<D>,
488 PF: PackedField<Scalar = F>,
489{
490 #[inline]
491 fn mul_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
492 *self = *self * rhs;
493 }
494}
495
496impl<F, PF, const D: usize> MulAssign<PF> for PackedBinomialExtensionField<F, PF, D>
497where
498 F: BinomiallyExtendable<D>,
499 PF: PackedField<Scalar = F>,
500{
501 #[inline]
502 fn mul_assign(&mut self, rhs: PF) {
503 *self = *self * rhs;
504 }
505}
506
507impl<F, PF, const D: usize> Div<BinomialExtensionField<F, D>>
508 for PackedBinomialExtensionField<F, PF, D>
509where
510 F: BinomiallyExtendable<D>,
511 PF: PackedField<Scalar = F>,
512{
513 type Output = Self;
514
515 #[allow(clippy::suspicious_arithmetic_impl)]
516 #[inline]
517 fn div(self, rhs: BinomialExtensionField<F, D>) -> Self {
518 self * Self::from(rhs.inverse())
519 }
520}
521
522impl<F, PF, const D: usize> DivAssign<BinomialExtensionField<F, D>>
523 for PackedBinomialExtensionField<F, PF, D>
524where
525 F: BinomiallyExtendable<D>,
526 PF: PackedField<Scalar = F>,
527{
528 #[inline]
529 fn div_assign(&mut self, rhs: BinomialExtensionField<F, D>) {
530 *self = *self / rhs;
531 }
532}
533
534impl<F: BinomiallyExtendable<D>, const D: usize> Div
535 for PackedBinomialExtensionField<F, F::Packing, D>
536{
537 type Output = Self;
538
539 #[allow(clippy::suspicious_arithmetic_impl)]
540 #[inline]
541 fn div(self, rhs: Self) -> Self {
542 self * crate::invert_packed_extension::<F, BinomialExtensionField<F, D>>(rhs)
543 }
544}
545
546impl<F: BinomiallyExtendable<D>, const D: usize> DivAssign
547 for PackedBinomialExtensionField<F, F::Packing, D>
548{
549 #[inline]
550 fn div_assign(&mut self, rhs: Self) {
551 *self = *self / rhs;
552 }
553}