p3_field/extension/
binomial_extension.rs

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