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