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