Skip to main content

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)]
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    /// FrobeniusField automorphisms: x -> x^n, where n is the order of BaseField.
57    fn frobenius(&self) -> Self {
58        self.repeated_frobenius(1)
59    }
60
61    /// Repeated Frobenius automorphisms: x -> x^(n^count).
62    ///
63    /// Follows precomputation suggestion in Section 11.3.3 of the
64    /// Handbook of Elliptic and Hyperelliptic Curve Cryptography.
65    fn repeated_frobenius(&self, count: usize) -> Self {
66        if count == 0 {
67            return *self;
68        } else if count >= D {
69            // x |-> x^(n^D) is the identity, so x^(n^count) ==
70            // x^(n^(count % D))
71            return self.repeated_frobenius(count % D);
72        }
73        let arr: &[F] = self.as_base_slice();
74
75        // z0 = DTH_ROOT^count = W^(k * count) where k = floor((n-1)/D)
76        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    /// Algorithm 11.3.4 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
90    fn frobenius_inv(&self) -> Self {
91        // Writing 'a' for self, we need to compute a^(r-1):
92        // r = n^D-1/n-1 = n^(D-1)+n^(D-2)+...+n
93        let mut f = Self::one();
94        for _ in 1..D {
95            f = (f * *self).frobenius();
96        }
97
98        // g = a^r is in the base field, so only compute that
99        // coefficient rather than the full product.
100        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    /// Convert from `u64`. Undefined behavior if the input is outside the canonical range.
165    fn from_canonical_u64(n: u64) -> Self {
166        AF::from_canonical_u64(n).into()
167    }
168
169    /// Convert from `usize`. Undefined behavior if the input is outside the canonical range.
170    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///Section 11.3.6b in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
565#[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/// Section 11.3.6b in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
572#[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    // scalar = (a0^3+wa1^3+w^2a2^3-3wa0a1a2)^-1
580    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    //scalar*[a0^2-wa1a2, wa2^2-a0a1, a1^2-a0a2]
585    [
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/// karatsuba multiplication for cubic extension field
593#[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/// Section 11.3.6a in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
614#[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}