openvm_pairing_guest/pairing/
sextic_ext_field.rs

1use core::{
2    fmt::{Debug, Formatter, Result},
3    ops::{Add, AddAssign, Sub, SubAssign},
4};
5
6use openvm_algebra_guest::field::Field;
7
8/// Sextic extension field of `F` with irreducible polynomial `X^6 - \xi`.
9/// Elements are represented as `c0 + c1 * w + ... + c5 * w^5` where `w^6 = \xi`, where `\xi in F`.
10///
11/// Memory alignment follows alignment of `F`.
12#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
13#[repr(C)]
14pub struct SexticExtField<F> {
15    pub c: [F; 6],
16}
17
18impl<F> SexticExtField<F> {
19    pub const fn new(c: [F; 6]) -> Self {
20        Self { c }
21    }
22}
23
24impl<'a, F: Field> AddAssign<&'a SexticExtField<F>> for SexticExtField<F> {
25    #[inline(always)]
26    fn add_assign(&mut self, other: &'a SexticExtField<F>) {
27        for i in 0..6 {
28            self.c[i] += &other.c[i];
29        }
30    }
31}
32
33impl<'a, F: Field> Add<&'a SexticExtField<F>> for &SexticExtField<F> {
34    type Output = SexticExtField<F>;
35    #[inline(always)]
36    fn add(self, other: &'a SexticExtField<F>) -> Self::Output {
37        let mut res = self.clone();
38        res += other;
39        res
40    }
41}
42
43impl<'a, F: Field> SubAssign<&'a SexticExtField<F>> for SexticExtField<F> {
44    #[inline(always)]
45    fn sub_assign(&mut self, other: &'a SexticExtField<F>) {
46        for i in 0..6 {
47            self.c[i] -= &other.c[i];
48        }
49    }
50}
51
52impl<'a, F: Field> Sub<&'a SexticExtField<F>> for &SexticExtField<F> {
53    type Output = SexticExtField<F>;
54    #[inline(always)]
55    fn sub(self, other: &'a SexticExtField<F>) -> Self::Output {
56        let mut res = self.clone();
57        res -= other;
58        res
59    }
60}
61
62pub(crate) fn sextic_tower_mul<F: Field>(
63    lhs: &SexticExtField<F>,
64    rhs: &SexticExtField<F>,
65    xi: &F,
66) -> SexticExtField<F>
67where
68    for<'a> &'a F: core::ops::Mul<&'a F, Output = F>,
69{
70    // The following multiplication is hand-derived with respect to the basis where degree 6 extension
71    // is composed of degree 3 extension followed by degree 2 extension.
72
73    // c0 = cs0co0 + xi(cs1co2 + cs2co1 + cs3co5 + cs4co4 + cs5co3)
74    // c1 = cs0co1 + cs1co0 + cs3co3 + xi(cs2co2 + cs4co5 + cs5co4)
75    // c2 = cs0co2 + cs1co1 + cs2co0 + cs3co4 + cs4co3 + xi(cs5co5)
76    // c3 = cs0co3 + cs3co0 + xi(cs1co5 + cs2co4 + cs4co2 + cs5co1)
77    // c4 = cs0co4 + cs1co3 + cs3co1 + cs4co0 + xi(cs2co5 + cs5co2)
78    // c5 = cs0co5 + cs1co4 + cs2co3 + cs3co2 + cs4co1 + cs5co0
79    //   where cs*: lhs.c*, co*: rhs.c*
80
81    let (s0, s1, s2, s3, s4, s5) = (
82        &lhs.c[0], &lhs.c[2], &lhs.c[4], &lhs.c[1], &lhs.c[3], &lhs.c[5],
83    );
84    let (o0, o1, o2, o3, o4, o5) = (
85        &rhs.c[0], &rhs.c[2], &rhs.c[4], &rhs.c[1], &rhs.c[3], &rhs.c[5],
86    );
87
88    let c0 = s0 * o0 + xi * &(s1 * o2 + s2 * o1 + s3 * o5 + s4 * o4 + s5 * o3);
89    let c1 = s0 * o1 + s1 * o0 + s3 * o3 + xi * &(s2 * o2 + s4 * o5 + s5 * o4);
90    let c2 = s0 * o2 + s1 * o1 + s2 * o0 + s3 * o4 + s4 * o3 + xi * &(s5 * o5);
91    let c3 = s0 * o3 + s3 * o0 + xi * &(s1 * o5 + s2 * o4 + s4 * o2 + s5 * o1);
92    let c4 = s0 * o4 + s1 * o3 + s3 * o1 + s4 * o0 + xi * &(s2 * o5 + s5 * o2);
93    let c5 = s0 * o5 + s1 * o4 + s2 * o3 + s3 * o2 + s4 * o1 + s5 * o0;
94
95    SexticExtField::new([c0, c3, c1, c4, c2, c5])
96}
97
98// Auto-derived implementations:
99
100impl<F: Field> AddAssign for SexticExtField<F> {
101    #[inline(always)]
102    fn add_assign(&mut self, other: Self) {
103        self.add_assign(&other);
104    }
105}
106
107impl<F: Field> Add for SexticExtField<F> {
108    type Output = Self;
109    #[inline(always)]
110    fn add(mut self, other: Self) -> Self::Output {
111        self += other;
112        self
113    }
114}
115
116impl<'a, F: Field> Add<&'a SexticExtField<F>> for SexticExtField<F> {
117    type Output = Self;
118    #[inline(always)]
119    fn add(mut self, other: &'a SexticExtField<F>) -> Self::Output {
120        self += other;
121        self
122    }
123}
124
125impl<F: Field> SubAssign for SexticExtField<F> {
126    #[inline(always)]
127    fn sub_assign(&mut self, other: Self) {
128        self.sub_assign(&other);
129    }
130}
131
132impl<F: Field> Sub for SexticExtField<F> {
133    type Output = Self;
134    #[inline(always)]
135    fn sub(mut self, other: Self) -> Self::Output {
136        self -= other;
137        self
138    }
139}
140
141impl<'a, F: Field> Sub<&'a SexticExtField<F>> for SexticExtField<F> {
142    type Output = Self;
143    #[inline(always)]
144    fn sub(mut self, other: &'a SexticExtField<F>) -> Self::Output {
145        self -= other;
146        self
147    }
148}
149
150impl<F: Field> Debug for SexticExtField<F> {
151    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
152        write!(
153            f,
154            "{:?}, {:?}, {:?}, {:?}, {:?}, {:?}",
155            self.c[0], self.c[1], self.c[2], self.c[3], self.c[4], self.c[5]
156        )
157    }
158}