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