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