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 packed_ext_powers(base: QuinticTrinomialExtensionField<F>) -> Powers<Self> {
176 let width = F::Packing::WIDTH;
177 let powers = base.powers().collect_n(width + 1);
178 let current = Self::from_ext_slice(&powers[..width]);
180
181 let multiplier = powers[width].into();
183
184 Powers {
185 base: multiplier,
186 current,
187 }
188 }
189}
190
191impl<F, PF> Neg for PackedQuinticTrinomialExtensionField<F, PF>
192where
193 F: QuinticTrinomialExtendable,
194 PF: PackedField<Scalar = F>,
195{
196 type Output = Self;
197
198 #[inline]
199 fn neg(self) -> Self {
200 Self::new(self.value.map(PF::neg))
201 }
202}
203
204impl<F, PF> Add for PackedQuinticTrinomialExtensionField<F, PF>
205where
206 F: QuinticTrinomialExtendable,
207 PF: PackedField<Scalar = F>,
208{
209 type Output = Self;
210
211 #[inline]
212 fn add(self, rhs: Self) -> Self {
213 Self::new(vector_add(&self.value, &rhs.value))
214 }
215}
216
217impl<F, PF> Add<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
218where
219 F: QuinticTrinomialExtendable,
220 PF: PackedField<Scalar = F>,
221{
222 type Output = Self;
223
224 #[inline]
225 fn add(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
226 let value = vector_add(&self.value, &rhs.value);
227 Self::new(value)
228 }
229}
230
231impl<F, PF> Add<PF> for PackedQuinticTrinomialExtensionField<F, PF>
232where
233 F: QuinticTrinomialExtendable,
234 PF: PackedField<Scalar = F>,
235{
236 type Output = Self;
237
238 #[inline]
239 fn add(mut self, rhs: PF) -> Self {
240 self.value[0] += rhs;
241 self
242 }
243}
244
245impl<F, PF> AddAssign for PackedQuinticTrinomialExtensionField<F, PF>
246where
247 F: QuinticTrinomialExtendable,
248 PF: PackedField<Scalar = F>,
249{
250 #[inline]
251 fn add_assign(&mut self, rhs: Self) {
252 for i in 0..5 {
253 self.value[i] += rhs.value[i];
254 }
255 }
256}
257
258impl<F, PF> AddAssign<QuinticTrinomialExtensionField<F>>
259 for PackedQuinticTrinomialExtensionField<F, PF>
260where
261 F: QuinticTrinomialExtendable,
262 PF: PackedField<Scalar = F>,
263{
264 #[inline]
265 fn add_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
266 for i in 0..5 {
267 self.value[i] += rhs.value[i];
268 }
269 }
270}
271
272impl<F, PF> AddAssign<PF> for PackedQuinticTrinomialExtensionField<F, PF>
273where
274 F: QuinticTrinomialExtendable,
275 PF: PackedField<Scalar = F>,
276{
277 #[inline]
278 fn add_assign(&mut self, rhs: PF) {
279 self.value[0] += rhs;
280 }
281}
282
283impl<F, PF> Sum for PackedQuinticTrinomialExtensionField<F, PF>
284where
285 F: QuinticTrinomialExtendable,
286 PF: PackedField<Scalar = F>,
287{
288 #[inline]
289 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
290 iter.reduce(|acc, x| acc + x).unwrap_or(Self::ZERO)
291 }
292}
293
294impl<F, PF> Sub for PackedQuinticTrinomialExtensionField<F, PF>
295where
296 F: QuinticTrinomialExtendable,
297 PF: PackedField<Scalar = F>,
298{
299 type Output = Self;
300
301 #[inline]
302 fn sub(self, rhs: Self) -> Self {
303 Self::new(vector_sub(&self.value, &rhs.value))
304 }
305}
306
307impl<F, PF> Sub<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
308where
309 F: QuinticTrinomialExtendable,
310 PF: PackedField<Scalar = F>,
311{
312 type Output = Self;
313
314 #[inline]
315 fn sub(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
316 let value = vector_sub(&self.value, &rhs.value);
317 Self::new(value)
318 }
319}
320
321impl<F, PF> Sub<PF> for PackedQuinticTrinomialExtensionField<F, PF>
322where
323 F: QuinticTrinomialExtendable,
324 PF: PackedField<Scalar = F>,
325{
326 type Output = Self;
327
328 #[inline]
329 fn sub(self, rhs: PF) -> Self {
330 let mut res = self.value;
331 res[0] -= rhs;
332 Self::new(res)
333 }
334}
335
336impl<F, PF> SubAssign for PackedQuinticTrinomialExtensionField<F, PF>
337where
338 F: QuinticTrinomialExtendable,
339 PF: PackedField<Scalar = F>,
340{
341 #[inline]
342 fn sub_assign(&mut self, rhs: Self) {
343 *self = *self - rhs;
344 }
345}
346
347impl<F, PF> SubAssign<QuinticTrinomialExtensionField<F>>
348 for PackedQuinticTrinomialExtensionField<F, PF>
349where
350 F: QuinticTrinomialExtendable,
351 PF: PackedField<Scalar = F>,
352{
353 #[inline]
354 fn sub_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
355 *self = *self - rhs;
356 }
357}
358
359impl<F, PF> SubAssign<PF> for PackedQuinticTrinomialExtensionField<F, PF>
360where
361 F: QuinticTrinomialExtendable,
362 PF: PackedField<Scalar = F>,
363{
364 #[inline]
365 fn sub_assign(&mut self, rhs: PF) {
366 *self = *self - rhs;
367 }
368}
369
370impl<F, PF> Mul for PackedQuinticTrinomialExtensionField<F, PF>
371where
372 F: QuinticTrinomialExtendable,
373 PF: PackedField<Scalar = F>,
374{
375 type Output = Self;
376
377 #[inline]
378 fn mul(self, rhs: Self) -> Self {
379 let mut res = Self::default();
380 trinomial_quintic_mul(&self.value, &rhs.value, &mut res.value);
381 res
382 }
383}
384
385impl<F, PF> Mul<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
386where
387 F: QuinticTrinomialExtendable,
388 PF: PackedField<Scalar = F>,
389{
390 type Output = Self;
391
392 #[inline]
393 fn mul(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
394 self * Self::from(rhs)
395 }
396}
397
398impl<F, PF> Mul<PF> for PackedQuinticTrinomialExtensionField<F, PF>
399where
400 F: QuinticTrinomialExtendable,
401 PF: PackedField<Scalar = F>,
402{
403 type Output = Self;
404
405 #[inline]
406 fn mul(self, rhs: PF) -> Self {
407 Self::new(self.value.map(|x| x * rhs))
408 }
409}
410
411impl<F, PF> Product for PackedQuinticTrinomialExtensionField<F, PF>
412where
413 F: QuinticTrinomialExtendable,
414 PF: PackedField<Scalar = F>,
415{
416 #[inline]
417 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
418 iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE)
419 }
420}
421
422impl<F, PF> MulAssign for PackedQuinticTrinomialExtensionField<F, PF>
423where
424 F: QuinticTrinomialExtendable,
425 PF: PackedField<Scalar = F>,
426{
427 #[inline]
428 fn mul_assign(&mut self, rhs: Self) {
429 *self = *self * rhs;
430 }
431}
432
433impl<F, PF> MulAssign<QuinticTrinomialExtensionField<F>>
434 for PackedQuinticTrinomialExtensionField<F, PF>
435where
436 F: QuinticTrinomialExtendable,
437 PF: PackedField<Scalar = F>,
438{
439 #[inline]
440 fn mul_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
441 *self = *self * rhs;
442 }
443}
444
445impl<F, PF> MulAssign<PF> for PackedQuinticTrinomialExtensionField<F, PF>
446where
447 F: QuinticTrinomialExtendable,
448 PF: PackedField<Scalar = F>,
449{
450 #[inline]
451 fn mul_assign(&mut self, rhs: PF) {
452 *self = *self * rhs;
453 }
454}
455
456impl<F, PF> Sum<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
457where
458 F: QuinticTrinomialExtendable,
459 PF: PackedField<Scalar = F>,
460{
461 #[inline]
462 fn sum<I: Iterator<Item = QuinticTrinomialExtensionField<F>>>(iter: I) -> Self {
463 iter.map(Self::from).sum()
464 }
465}
466
467impl<F, PF> Product<QuinticTrinomialExtensionField<F>>
468 for PackedQuinticTrinomialExtensionField<F, PF>
469where
470 F: QuinticTrinomialExtendable,
471 PF: PackedField<Scalar = F>,
472{
473 #[inline]
474 fn product<I: Iterator<Item = QuinticTrinomialExtensionField<F>>>(iter: I) -> Self {
475 iter.map(Self::from).product()
476 }
477}
478
479impl<F, PF> Div<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
480where
481 F: QuinticTrinomialExtendable,
482 PF: PackedField<Scalar = F>,
483{
484 type Output = Self;
485
486 #[allow(clippy::suspicious_arithmetic_impl)]
487 #[inline]
488 fn div(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
489 self * Self::from(rhs.inverse())
490 }
491}
492
493impl<F, PF> DivAssign<QuinticTrinomialExtensionField<F>>
494 for PackedQuinticTrinomialExtensionField<F, PF>
495where
496 F: QuinticTrinomialExtendable,
497 PF: PackedField<Scalar = F>,
498{
499 #[inline]
500 fn div_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
501 *self = *self / rhs;
502 }
503}
504
505impl<F: QuinticTrinomialExtendable> Div for PackedQuinticTrinomialExtensionField<F, F::Packing> {
506 type Output = Self;
507
508 #[allow(clippy::suspicious_arithmetic_impl)]
509 #[inline]
510 fn div(self, rhs: Self) -> Self {
511 self * crate::invert_packed_extension::<F, QuinticTrinomialExtensionField<F>>(rhs)
512 }
513}
514
515impl<F: QuinticTrinomialExtendable> DivAssign
516 for PackedQuinticTrinomialExtensionField<F, F::Packing>
517{
518 #[inline]
519 fn div_assign(&mut self, rhs: Self) {
520 *self = *self / rhs;
521 }
522}