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 let res = array::from_fn(|i| F::Packing::from_fn(|j| ext_slice[j].value[i]));
265 Self::new(res)
266 }
267
268 #[inline]
269 fn packed_ext_powers(base: QuinticTrinomialExtensionField<F>) -> Powers<Self> {
270 use itertools::Itertools;
271 let width = F::Packing::WIDTH;
272 let powers = base.powers().take(width + 1).collect_vec();
273 let current = Self::from_ext_slice(&powers[..width]);
275
276 let multiplier = powers[width].into();
278
279 Powers {
280 base: multiplier,
281 current,
282 }
283 }
284}
285
286impl<F, PF> Neg for PackedQuinticTrinomialExtensionField<F, PF>
287where
288 F: QuinticTrinomialExtendable,
289 PF: PackedField<Scalar = F>,
290{
291 type Output = Self;
292
293 #[inline]
294 fn neg(self) -> Self {
295 Self::new(self.value.map(PF::neg))
296 }
297}
298
299impl<F, PF> Add for PackedQuinticTrinomialExtensionField<F, PF>
300where
301 F: QuinticTrinomialExtendable,
302 PF: PackedField<Scalar = F>,
303{
304 type Output = Self;
305
306 #[inline]
307 fn add(self, rhs: Self) -> Self {
308 Self::new(vector_add(&self.value, &rhs.value))
309 }
310}
311
312impl<F, PF> Add<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
313where
314 F: QuinticTrinomialExtendable,
315 PF: PackedField<Scalar = F>,
316{
317 type Output = Self;
318
319 #[inline]
320 fn add(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
321 let value = vector_add(&self.value, &rhs.value);
322 Self { value }
323 }
324}
325
326impl<F, PF> Add<PF> for PackedQuinticTrinomialExtensionField<F, PF>
327where
328 F: QuinticTrinomialExtendable,
329 PF: PackedField<Scalar = F>,
330{
331 type Output = Self;
332
333 #[inline]
334 fn add(mut self, rhs: PF) -> Self {
335 self.value[0] += rhs;
336 self
337 }
338}
339
340impl<F, PF> AddAssign for PackedQuinticTrinomialExtensionField<F, PF>
341where
342 F: QuinticTrinomialExtendable,
343 PF: PackedField<Scalar = F>,
344{
345 #[inline]
346 fn add_assign(&mut self, rhs: Self) {
347 for i in 0..5 {
348 self.value[i] += rhs.value[i];
349 }
350 }
351}
352
353impl<F, PF> AddAssign<QuinticTrinomialExtensionField<F>>
354 for PackedQuinticTrinomialExtensionField<F, PF>
355where
356 F: QuinticTrinomialExtendable,
357 PF: PackedField<Scalar = F>,
358{
359 #[inline]
360 fn add_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
361 for i in 0..5 {
362 self.value[i] += rhs.value[i];
363 }
364 }
365}
366
367impl<F, PF> AddAssign<PF> for PackedQuinticTrinomialExtensionField<F, PF>
368where
369 F: QuinticTrinomialExtendable,
370 PF: PackedField<Scalar = F>,
371{
372 #[inline]
373 fn add_assign(&mut self, rhs: PF) {
374 self.value[0] += rhs;
375 }
376}
377
378impl<F, PF> Sum for PackedQuinticTrinomialExtensionField<F, PF>
379where
380 F: QuinticTrinomialExtendable,
381 PF: PackedField<Scalar = F>,
382{
383 #[inline]
384 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
385 iter.reduce(|acc, x| acc + x).unwrap_or(Self::ZERO)
386 }
387}
388
389impl<F, PF> Sub for PackedQuinticTrinomialExtensionField<F, PF>
390where
391 F: QuinticTrinomialExtendable,
392 PF: PackedField<Scalar = F>,
393{
394 type Output = Self;
395
396 #[inline]
397 fn sub(self, rhs: Self) -> Self {
398 Self::new(vector_sub(&self.value, &rhs.value))
399 }
400}
401
402impl<F, PF> Sub<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
403where
404 F: QuinticTrinomialExtendable,
405 PF: PackedField<Scalar = F>,
406{
407 type Output = Self;
408
409 #[inline]
410 fn sub(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
411 let value = vector_sub(&self.value, &rhs.value);
412 Self { value }
413 }
414}
415
416impl<F, PF> Sub<PF> for PackedQuinticTrinomialExtensionField<F, PF>
417where
418 F: QuinticTrinomialExtendable,
419 PF: PackedField<Scalar = F>,
420{
421 type Output = Self;
422
423 #[inline]
424 fn sub(self, rhs: PF) -> Self {
425 let mut res = self.value;
426 res[0] -= rhs;
427 Self { value: res }
428 }
429}
430
431impl<F, PF> SubAssign for PackedQuinticTrinomialExtensionField<F, PF>
432where
433 F: QuinticTrinomialExtendable,
434 PF: PackedField<Scalar = F>,
435{
436 #[inline]
437 fn sub_assign(&mut self, rhs: Self) {
438 *self = *self - rhs;
439 }
440}
441
442impl<F, PF> SubAssign<QuinticTrinomialExtensionField<F>>
443 for PackedQuinticTrinomialExtensionField<F, PF>
444where
445 F: QuinticTrinomialExtendable,
446 PF: PackedField<Scalar = F>,
447{
448 #[inline]
449 fn sub_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
450 *self = *self - rhs;
451 }
452}
453
454impl<F, PF> SubAssign<PF> for PackedQuinticTrinomialExtensionField<F, PF>
455where
456 F: QuinticTrinomialExtendable,
457 PF: PackedField<Scalar = F>,
458{
459 #[inline]
460 fn sub_assign(&mut self, rhs: PF) {
461 *self = *self - rhs;
462 }
463}
464
465impl<F, PF> Mul for PackedQuinticTrinomialExtensionField<F, PF>
466where
467 F: QuinticTrinomialExtendable,
468 PF: PackedField<Scalar = F>,
469{
470 type Output = Self;
471
472 #[inline]
473 fn mul(self, rhs: Self) -> Self {
474 let mut res = Self::default();
475 trinomial_quintic_mul(&self.value, &rhs.value, &mut res.value);
476 res
477 }
478}
479
480impl<F, PF> Mul<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
481where
482 F: QuinticTrinomialExtendable,
483 PF: PackedField<Scalar = F>,
484{
485 type Output = Self;
486
487 #[inline]
488 fn mul(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
489 self * Self::from(rhs)
490 }
491}
492
493impl<F, PF> Mul<PF> for PackedQuinticTrinomialExtensionField<F, PF>
494where
495 F: QuinticTrinomialExtendable,
496 PF: PackedField<Scalar = F>,
497{
498 type Output = Self;
499
500 #[inline]
501 fn mul(self, rhs: PF) -> Self {
502 Self {
503 value: self.value.map(|x| x * rhs),
504 }
505 }
506}
507
508impl<F, PF> Product for PackedQuinticTrinomialExtensionField<F, PF>
509where
510 F: QuinticTrinomialExtendable,
511 PF: PackedField<Scalar = F>,
512{
513 #[inline]
514 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
515 iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE)
516 }
517}
518
519impl<F, PF> MulAssign for PackedQuinticTrinomialExtensionField<F, PF>
520where
521 F: QuinticTrinomialExtendable,
522 PF: PackedField<Scalar = F>,
523{
524 #[inline]
525 fn mul_assign(&mut self, rhs: Self) {
526 *self = *self * rhs;
527 }
528}
529
530impl<F, PF> MulAssign<QuinticTrinomialExtensionField<F>>
531 for PackedQuinticTrinomialExtensionField<F, PF>
532where
533 F: QuinticTrinomialExtendable,
534 PF: PackedField<Scalar = F>,
535{
536 #[inline]
537 fn mul_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
538 *self = *self * rhs;
539 }
540}
541
542impl<F, PF> MulAssign<PF> for PackedQuinticTrinomialExtensionField<F, PF>
543where
544 F: QuinticTrinomialExtendable,
545 PF: PackedField<Scalar = F>,
546{
547 #[inline]
548 fn mul_assign(&mut self, rhs: PF) {
549 *self = *self * rhs;
550 }
551}
552
553impl<F, PF> Sum<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
554where
555 F: QuinticTrinomialExtendable,
556 PF: PackedField<Scalar = F>,
557{
558 #[inline]
559 fn sum<I: Iterator<Item = QuinticTrinomialExtensionField<F>>>(iter: I) -> Self {
560 iter.map(Self::from).sum()
561 }
562}
563
564impl<F, PF> Product<QuinticTrinomialExtensionField<F>>
565 for PackedQuinticTrinomialExtensionField<F, PF>
566where
567 F: QuinticTrinomialExtendable,
568 PF: PackedField<Scalar = F>,
569{
570 #[inline]
571 fn product<I: Iterator<Item = QuinticTrinomialExtensionField<F>>>(iter: I) -> Self {
572 iter.map(Self::from).product()
573 }
574}
575
576impl<F, PF> Div<QuinticTrinomialExtensionField<F>> for PackedQuinticTrinomialExtensionField<F, PF>
577where
578 F: QuinticTrinomialExtendable,
579 PF: PackedField<Scalar = F>,
580{
581 type Output = Self;
582
583 #[allow(clippy::suspicious_arithmetic_impl)]
584 #[inline]
585 fn div(self, rhs: QuinticTrinomialExtensionField<F>) -> Self {
586 self * Self::from(rhs.inverse())
587 }
588}
589
590impl<F, PF> DivAssign<QuinticTrinomialExtensionField<F>>
591 for PackedQuinticTrinomialExtensionField<F, PF>
592where
593 F: QuinticTrinomialExtendable,
594 PF: PackedField<Scalar = F>,
595{
596 #[inline]
597 fn div_assign(&mut self, rhs: QuinticTrinomialExtensionField<F>) {
598 *self = *self / rhs;
599 }
600}