1use alloc::format;
2use alloc::string::ToString;
3use core::array;
4use core::fmt::{self, Debug, Display, Formatter};
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8use itertools::Itertools;
9use num_bigint::BigUint;
10use rand::distributions::Standard;
11use rand::prelude::Distribution;
12use serde::{Deserialize, Serialize};
13
14use super::{HasFrobenius, HasTwoAdicBionmialExtension};
15use crate::extension::BinomiallyExtendable;
16use crate::field::Field;
17use crate::{
18 field_to_array, AbstractExtensionField, AbstractField, ExtensionField, Packable, TwoAdicField,
19};
20
21#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
22#[repr(C)]
23pub struct BinomialExtensionField<AF, const D: usize> {
24 #[serde(
25 with = "p3_util::array_serialization",
26 bound(serialize = "AF: Serialize", deserialize = "AF: Deserialize<'de>")
27 )]
28 pub(crate) value: [AF; D],
29}
30
31impl<AF: AbstractField, const D: usize> Default for BinomialExtensionField<AF, D> {
32 fn default() -> Self {
33 Self {
34 value: array::from_fn(|_| AF::zero()),
35 }
36 }
37}
38
39impl<AF: AbstractField, const D: usize> From<AF> for BinomialExtensionField<AF, D> {
40 fn from(x: AF) -> Self {
41 Self {
42 value: field_to_array::<AF, D>(x),
43 }
44 }
45}
46
47impl<F: BinomiallyExtendable<D>, const D: usize> Packable for BinomialExtensionField<F, D> {}
48
49impl<F: BinomiallyExtendable<D>, const D: usize> ExtensionField<F>
50 for BinomialExtensionField<F, D>
51{
52 type ExtensionPacking = BinomialExtensionField<F::Packing, D>;
53}
54
55impl<F: BinomiallyExtendable<D>, const D: usize> HasFrobenius<F> for BinomialExtensionField<F, D> {
56 fn frobenius(&self) -> Self {
58 self.repeated_frobenius(1)
59 }
60
61 fn repeated_frobenius(&self, count: usize) -> Self {
66 if count == 0 {
67 return *self;
68 } else if count >= D {
69 return self.repeated_frobenius(count % D);
72 }
73 let arr: &[F] = self.as_base_slice();
74
75 let mut z0 = F::dth_root();
77 for _ in 1..count {
78 z0 *= F::dth_root();
79 }
80
81 let mut res = [F::zero(); D];
82 for (i, z) in z0.powers().take(D).enumerate() {
83 res[i] = arr[i] * z;
84 }
85
86 Self::from_base_slice(&res)
87 }
88
89 fn frobenius_inv(&self) -> Self {
91 let mut f = Self::one();
94 for _ in 1..D {
95 f = (f * *self).frobenius();
96 }
97
98 let a = self.value;
101 let b = f.value;
102 let mut g = F::zero();
103 for i in 1..D {
104 g += a[i] * b[D - i];
105 }
106 g *= F::w();
107 g += a[0] * b[0];
108 debug_assert_eq!(Self::from(g), *self * f);
109
110 f * g.inverse()
111 }
112}
113
114impl<AF, const D: usize> AbstractField for BinomialExtensionField<AF, D>
115where
116 AF: AbstractField,
117 AF::F: BinomiallyExtendable<D>,
118{
119 type F = BinomialExtensionField<AF::F, D>;
120
121 fn zero() -> Self {
122 Self {
123 value: field_to_array::<AF, D>(AF::zero()),
124 }
125 }
126 fn one() -> Self {
127 Self {
128 value: field_to_array::<AF, D>(AF::one()),
129 }
130 }
131 fn two() -> Self {
132 Self {
133 value: field_to_array::<AF, D>(AF::two()),
134 }
135 }
136 fn neg_one() -> Self {
137 Self {
138 value: field_to_array::<AF, D>(AF::neg_one()),
139 }
140 }
141
142 fn from_f(f: Self::F) -> Self {
143 Self {
144 value: f.value.map(AF::from_f),
145 }
146 }
147
148 fn from_bool(b: bool) -> Self {
149 AF::from_bool(b).into()
150 }
151
152 fn from_canonical_u8(n: u8) -> Self {
153 AF::from_canonical_u8(n).into()
154 }
155
156 fn from_canonical_u16(n: u16) -> Self {
157 AF::from_canonical_u16(n).into()
158 }
159
160 fn from_canonical_u32(n: u32) -> Self {
161 AF::from_canonical_u32(n).into()
162 }
163
164 fn from_canonical_u64(n: u64) -> Self {
166 AF::from_canonical_u64(n).into()
167 }
168
169 fn from_canonical_usize(n: usize) -> Self {
171 AF::from_canonical_usize(n).into()
172 }
173
174 fn from_wrapped_u32(n: u32) -> Self {
175 AF::from_wrapped_u32(n).into()
176 }
177
178 fn from_wrapped_u64(n: u64) -> Self {
179 AF::from_wrapped_u64(n).into()
180 }
181
182 fn generator() -> Self {
183 Self {
184 value: AF::F::ext_generator().map(AF::from_f),
185 }
186 }
187
188 #[inline(always)]
189 fn square(&self) -> Self {
190 match D {
191 2 => {
192 let a = self.value.clone();
193 let mut res = Self::default();
194 res.value[0] = a[0].square() + a[1].square() * AF::from_f(AF::F::w());
195 res.value[1] = a[0].clone() * a[1].double();
196 res
197 }
198 3 => Self {
199 value: cubic_square(&self.value, AF::F::w())
200 .to_vec()
201 .try_into()
202 .unwrap(),
203 },
204 _ => <Self as Mul<Self>>::mul(self.clone(), self.clone()),
205 }
206 }
207}
208
209impl<F: BinomiallyExtendable<D>, const D: usize> Field for BinomialExtensionField<F, D> {
210 type Packing = Self;
211
212 fn try_inverse(&self) -> Option<Self> {
213 if self.is_zero() {
214 return None;
215 }
216
217 match D {
218 2 => Some(Self::from_base_slice(&qudratic_inv(&self.value, F::w()))),
219 3 => Some(Self::from_base_slice(&cubic_inv(&self.value, F::w()))),
220 _ => Some(self.frobenius_inv()),
221 }
222 }
223
224 fn halve(&self) -> Self {
225 Self {
226 value: self.value.map(|x| x.halve()),
227 }
228 }
229
230 fn order() -> BigUint {
231 F::order().pow(D as u32)
232 }
233}
234
235impl<F, const D: usize> Display for BinomialExtensionField<F, D>
236where
237 F: BinomiallyExtendable<D>,
238{
239 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
240 if self.is_zero() {
241 write!(f, "0")
242 } else {
243 let str = self
244 .value
245 .iter()
246 .enumerate()
247 .filter(|(_, x)| !x.is_zero())
248 .map(|(i, x)| match (i, x.is_one()) {
249 (0, _) => format!("{x}"),
250 (1, true) => "X".to_string(),
251 (1, false) => format!("{x} X"),
252 (_, true) => format!("X^{i}"),
253 (_, false) => format!("{x} X^{i}"),
254 })
255 .join(" + ");
256 write!(f, "{}", str)
257 }
258 }
259}
260
261impl<AF, const D: usize> Neg for BinomialExtensionField<AF, D>
262where
263 AF: AbstractField,
264 AF::F: BinomiallyExtendable<D>,
265{
266 type Output = Self;
267
268 #[inline]
269 fn neg(self) -> Self {
270 Self {
271 value: self.value.map(AF::neg),
272 }
273 }
274}
275
276impl<AF, const D: usize> Add for BinomialExtensionField<AF, D>
277where
278 AF: AbstractField,
279 AF::F: BinomiallyExtendable<D>,
280{
281 type Output = Self;
282
283 #[inline]
284 fn add(self, rhs: Self) -> Self {
285 let mut res = self.value;
286 for (r, rhs_val) in res.iter_mut().zip(rhs.value) {
287 *r += rhs_val;
288 }
289 Self { value: res }
290 }
291}
292
293impl<AF, const D: usize> Add<AF> for BinomialExtensionField<AF, D>
294where
295 AF: AbstractField,
296 AF::F: BinomiallyExtendable<D>,
297{
298 type Output = Self;
299
300 #[inline]
301 fn add(self, rhs: AF) -> Self {
302 let mut res = self.value;
303 res[0] += rhs;
304 Self { value: res }
305 }
306}
307
308impl<AF, const D: usize> AddAssign for BinomialExtensionField<AF, D>
309where
310 AF: AbstractField,
311 AF::F: BinomiallyExtendable<D>,
312{
313 fn add_assign(&mut self, rhs: Self) {
314 *self = self.clone() + rhs;
315 }
316}
317
318impl<AF, const D: usize> AddAssign<AF> for BinomialExtensionField<AF, D>
319where
320 AF: AbstractField,
321 AF::F: BinomiallyExtendable<D>,
322{
323 fn add_assign(&mut self, rhs: AF) {
324 *self = self.clone() + rhs;
325 }
326}
327
328impl<AF, const D: usize> Sum for BinomialExtensionField<AF, D>
329where
330 AF: AbstractField,
331 AF::F: BinomiallyExtendable<D>,
332{
333 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
334 let zero = Self {
335 value: field_to_array::<AF, D>(AF::zero()),
336 };
337 iter.fold(zero, |acc, x| acc + x)
338 }
339}
340
341impl<AF, const D: usize> Sub for BinomialExtensionField<AF, D>
342where
343 AF: AbstractField,
344 AF::F: BinomiallyExtendable<D>,
345{
346 type Output = Self;
347
348 #[inline]
349 fn sub(self, rhs: Self) -> Self {
350 let mut res = self.value;
351 for (r, rhs_val) in res.iter_mut().zip(rhs.value) {
352 *r -= rhs_val;
353 }
354 Self { value: res }
355 }
356}
357
358impl<AF, const D: usize> Sub<AF> for BinomialExtensionField<AF, D>
359where
360 AF: AbstractField,
361 AF::F: BinomiallyExtendable<D>,
362{
363 type Output = Self;
364
365 #[inline]
366 fn sub(self, rhs: AF) -> Self {
367 let mut res = self.value;
368 res[0] -= rhs;
369 Self { value: res }
370 }
371}
372
373impl<AF, const D: usize> SubAssign for BinomialExtensionField<AF, D>
374where
375 AF: AbstractField,
376 AF::F: BinomiallyExtendable<D>,
377{
378 #[inline]
379 fn sub_assign(&mut self, rhs: Self) {
380 *self = self.clone() - rhs;
381 }
382}
383
384impl<AF, const D: usize> SubAssign<AF> for BinomialExtensionField<AF, D>
385where
386 AF: AbstractField,
387 AF::F: BinomiallyExtendable<D>,
388{
389 #[inline]
390 fn sub_assign(&mut self, rhs: AF) {
391 *self = self.clone() - rhs;
392 }
393}
394
395impl<AF, const D: usize> Mul for BinomialExtensionField<AF, D>
396where
397 AF: AbstractField,
398 AF::F: BinomiallyExtendable<D>,
399{
400 type Output = Self;
401
402 #[inline]
403 fn mul(self, rhs: Self) -> Self {
404 let a = self.value;
405 let b = rhs.value;
406 let w = AF::F::w();
407 let w_af = AF::from_f(w);
408
409 match D {
410 2 => {
411 let mut res = Self::default();
412 res.value[0] = a[0].clone() * b[0].clone() + a[1].clone() * w_af * b[1].clone();
413 res.value[1] = a[0].clone() * b[1].clone() + a[1].clone() * b[0].clone();
414 res
415 }
416 3 => Self {
417 value: cubic_mul(&a, &b, w).to_vec().try_into().unwrap(),
418 },
419 _ => {
420 let mut res = Self::default();
421 #[allow(clippy::needless_range_loop)]
422 for i in 0..D {
423 for j in 0..D {
424 if i + j >= D {
425 res.value[i + j - D] += a[i].clone() * w_af.clone() * b[j].clone();
426 } else {
427 res.value[i + j] += a[i].clone() * b[j].clone();
428 }
429 }
430 }
431 res
432 }
433 }
434 }
435}
436
437impl<AF, const D: usize> Mul<AF> for BinomialExtensionField<AF, D>
438where
439 AF: AbstractField,
440 AF::F: BinomiallyExtendable<D>,
441{
442 type Output = Self;
443
444 #[inline]
445 fn mul(self, rhs: AF) -> Self {
446 Self {
447 value: self.value.map(|x| x * rhs.clone()),
448 }
449 }
450}
451
452impl<AF, const D: usize> Product for BinomialExtensionField<AF, D>
453where
454 AF: AbstractField,
455 AF::F: BinomiallyExtendable<D>,
456{
457 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
458 let one = Self {
459 value: field_to_array::<AF, D>(AF::one()),
460 };
461 iter.fold(one, |acc, x| acc * x)
462 }
463}
464
465impl<F, const D: usize> Div for BinomialExtensionField<F, D>
466where
467 F: BinomiallyExtendable<D>,
468{
469 type Output = Self;
470
471 #[allow(clippy::suspicious_arithmetic_impl)]
472 fn div(self, rhs: Self) -> Self::Output {
473 self * rhs.inverse()
474 }
475}
476
477impl<F, const D: usize> DivAssign for BinomialExtensionField<F, D>
478where
479 F: BinomiallyExtendable<D>,
480{
481 fn div_assign(&mut self, rhs: Self) {
482 *self = *self / rhs;
483 }
484}
485
486impl<AF, const D: usize> MulAssign for BinomialExtensionField<AF, D>
487where
488 AF: AbstractField,
489 AF::F: BinomiallyExtendable<D>,
490{
491 #[inline]
492 fn mul_assign(&mut self, rhs: Self) {
493 *self = self.clone() * rhs;
494 }
495}
496
497impl<AF, const D: usize> MulAssign<AF> for BinomialExtensionField<AF, D>
498where
499 AF: AbstractField,
500 AF::F: BinomiallyExtendable<D>,
501{
502 fn mul_assign(&mut self, rhs: AF) {
503 *self = self.clone() * rhs;
504 }
505}
506
507impl<AF, const D: usize> AbstractExtensionField<AF> for BinomialExtensionField<AF, D>
508where
509 AF: AbstractField,
510 AF::F: BinomiallyExtendable<D>,
511{
512 const D: usize = D;
513
514 fn from_base(b: AF) -> Self {
515 Self {
516 value: field_to_array(b),
517 }
518 }
519
520 fn from_base_slice(bs: &[AF]) -> Self {
521 Self {
522 value: bs.to_vec().try_into().expect("slice has wrong length"),
523 }
524 }
525
526 #[inline]
527 fn from_base_fn<F: FnMut(usize) -> AF>(f: F) -> Self {
528 Self {
529 value: array::from_fn(f),
530 }
531 }
532
533 fn as_base_slice(&self) -> &[AF] {
534 &self.value
535 }
536}
537
538impl<F: BinomiallyExtendable<D>, const D: usize> Distribution<BinomialExtensionField<F, D>>
539 for Standard
540where
541 Standard: Distribution<F>,
542{
543 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> BinomialExtensionField<F, D> {
544 let mut res = [F::zero(); D];
545 for r in res.iter_mut() {
546 *r = Standard.sample(rng);
547 }
548 BinomialExtensionField::<F, D>::from_base_slice(&res)
549 }
550}
551
552impl<F: Field + HasTwoAdicBionmialExtension<D>, const D: usize> TwoAdicField
553 for BinomialExtensionField<F, D>
554{
555 const TWO_ADICITY: usize = F::EXT_TWO_ADICITY;
556
557 fn two_adic_generator(bits: usize) -> Self {
558 Self {
559 value: F::ext_two_adic_generator(bits),
560 }
561 }
562}
563
564#[inline]
566fn qudratic_inv<F: Field>(a: &[F], w: F) -> [F; 2] {
567 let scalar = (a[0].square() - w * a[1].square()).inverse();
568 [a[0] * scalar, -a[1] * scalar]
569}
570
571#[inline]
573fn cubic_inv<F: Field>(a: &[F], w: F) -> [F; 3] {
574 let a0_square = a[0].square();
575 let a1_square = a[1].square();
576 let a2_w = w * a[2];
577 let a0_a1 = a[0] * a[1];
578
579 let scalar = (a0_square * a[0] + w * a[1] * a1_square + a2_w.square() * a[2]
581 - (F::one() + F::two()) * a2_w * a0_a1)
582 .inverse();
583
584 [
586 scalar * (a0_square - a[1] * a2_w),
587 scalar * (a2_w * a[2] - a0_a1),
588 scalar * (a1_square - a[0] * a[2]),
589 ]
590}
591
592#[inline]
594fn cubic_mul<AF: AbstractField>(a: &[AF], b: &[AF], w: AF::F) -> [AF; 3] {
595 let a0_b0 = a[0].clone() * b[0].clone();
596 let a1_b1 = a[1].clone() * b[1].clone();
597 let a2_b2 = a[2].clone() * b[2].clone();
598
599 let c0 = a0_b0.clone()
600 + ((a[1].clone() + a[2].clone()) * (b[1].clone() + b[2].clone())
601 - a1_b1.clone()
602 - a2_b2.clone())
603 * AF::from_f(w);
604 let c1 = (a[0].clone() + a[1].clone()) * (b[0].clone() + b[1].clone())
605 - a0_b0.clone()
606 - a1_b1.clone()
607 + a2_b2.clone() * AF::from_f(w);
608 let c2 = (a[0].clone() + a[2].clone()) * (b[0].clone() + b[2].clone()) - a0_b0 - a2_b2 + a1_b1;
609
610 [c0, c1, c2]
611}
612
613#[inline]
615fn cubic_square<AF: AbstractField>(a: &[AF], w: AF::F) -> [AF; 3] {
616 let w_a2 = a[2].clone() * AF::from_f(w);
617
618 let c0 = a[0].square() + (a[1].clone() * w_a2.clone()).double();
619 let c1 = w_a2 * a[2].clone() + (a[0].clone() * a[1].clone()).double();
620 let c2 = a[1].square() + (a[0].clone() * a[2].clone()).double();
621
622 [c0, c1, c2]
623}