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