openvm_pairing_guest/pairing/operations/
fp6.rs

1use openvm_algebra_guest::{field::FieldExtension, Field, IntMod};
2
3use super::fp2_invert_assign;
4
5pub(crate) fn fp6_invert_assign<
6    Fp: IntMod + Field,
7    Fp2: Field + FieldExtension<Fp, Coeffs = [Fp; 2]>,
8>(
9    c: &mut [Fp2; 3],
10    xi: &Fp2,
11) {
12    let mut c0 = c[2].clone();
13    c0 *= xi;
14    c0 *= &c[1];
15    c0 = c0.neg();
16    {
17        let mut c0s = c[0].clone();
18        <Fp2 as Field>::square_assign(&mut c0s);
19        c0 += &c0s;
20    }
21    let mut c1 = c[2].clone();
22    <Fp2 as Field>::square_assign(&mut c1);
23    c1 *= xi;
24    {
25        let mut c01 = c[0].clone();
26        c01 *= &c[1];
27        c1 -= &c01;
28    }
29    let mut c2 = c[1].clone();
30    <Fp2 as Field>::square_assign(&mut c2);
31    {
32        let mut c02 = c[0].clone();
33        c02 *= &c[2];
34        c2 -= &c02;
35    }
36
37    let mut tmp1 = c[2].clone();
38    tmp1 *= &c1;
39    let mut tmp2 = c[1].clone();
40    tmp2 *= &c2;
41    tmp1 += &tmp2;
42    tmp1 *= xi;
43    tmp2 = c[0].clone();
44    tmp2 *= &c0;
45    tmp1 += &tmp2;
46
47    let mut coeffs = tmp1.clone().to_coeffs();
48    fp2_invert_assign::<Fp>(&mut coeffs);
49    let tmp = Fp2::from_coeffs(coeffs);
50    let mut tmp = [tmp.clone(), tmp.clone(), tmp.clone()];
51    tmp[0] *= &c0;
52    tmp[1] *= &c1;
53    tmp[2] *= &c2;
54
55    *c = tmp;
56}
57
58pub(crate) fn fp6_mul_by_nonresidue_assign<
59    Fp: IntMod + Field,
60    Fp2: Field + FieldExtension<Fp, Coeffs = [Fp; 2]>,
61>(
62    c: &mut [Fp2; 3],
63    xi: &Fp2,
64) {
65    // c0, c1, c2 -> c2, c0, c1
66    c.swap(0, 1);
67    c.swap(0, 2);
68    c[0] *= xi;
69}
70
71pub(crate) fn fp6_sub_assign<
72    Fp: IntMod + Field,
73    Fp2: Field + FieldExtension<Fp, Coeffs = [Fp; 2]>,
74>(
75    a: &mut [Fp2; 3],
76    b: &[Fp2; 3],
77) {
78    a.iter_mut().zip(b).for_each(|(a, b)| *a -= b);
79}
80
81/// Squares 3 elements of `Fp2`, which represents as a single Fp6 element, in place
82pub(crate) fn fp6_square_assign<
83    Fp: IntMod + Field,
84    Fp2: Field + FieldExtension<Fp, Coeffs = [Fp; 2]>,
85>(
86    c: &mut [Fp2; 3],
87    xi: &Fp2,
88) {
89    // s0 = a^2
90    let mut s0 = c[0].clone();
91    <Fp2 as Field>::square_assign(&mut s0);
92    // s1 = 2ab
93    let mut ab = c[0].clone();
94    ab *= &c[1];
95    let mut s1 = ab;
96    <Fp2 as Field>::double_assign(&mut s1);
97    // s2 = (a - b + c)^2
98    let mut s2 = c[0].clone();
99    s2 -= &c[1];
100    s2 += &c[2];
101    <Fp2 as Field>::square_assign(&mut s2);
102    // bc
103    let mut bc = c[1].clone();
104    bc *= &c[2];
105    // s3 = 2bc
106    let mut s3 = bc;
107    <Fp2 as Field>::double_assign(&mut s3);
108    // s4 = c^2
109    let mut s4 = c[2].clone();
110    <Fp2 as Field>::square_assign(&mut s4);
111
112    // new c0 = 2bc.mul_by_xi + a^2
113    c[0] = s3.clone();
114    c[0] *= xi;
115    c[0] += &s0;
116
117    // new c1 = (c^2).mul_by_xi + 2ab
118    c[1] = s4.clone();
119    c[1] *= xi;
120    c[1] += &s1;
121
122    // new c2 = 2ab + (a - b + c)^2 + 2bc - a^2 - c^2 = b^2 + 2ac
123    c[2] = s1;
124    c[2] += &s2;
125    c[2] += &s3;
126    c[2] -= &s0;
127    c[2] -= &s4;
128}
129
130pub(crate) fn fp6_mul_assign<
131    Fp: IntMod + Field,
132    Fp2: Field + FieldExtension<Fp, Coeffs = [Fp; 2]>,
133>(
134    a: &mut [Fp2; 3],
135    b: &[Fp2; 3],
136    xi: &Fp2,
137) {
138    let mut a_a = a[0].clone();
139    let mut b_b = a[1].clone();
140    let mut c_c = a[2].clone();
141
142    a_a *= &b[0];
143    b_b *= &b[1];
144    c_c *= &b[2];
145
146    let mut t1 = b[1].clone();
147    t1 += &b[2];
148    {
149        let mut tmp = a[1].clone();
150        tmp += &a[2];
151
152        t1 *= &tmp;
153        t1 -= &b_b;
154        t1 -= &c_c;
155        t1 *= xi;
156        t1 += &a_a;
157    }
158
159    let mut t3 = b[0].clone();
160    t3 += &b[2];
161    {
162        let mut tmp = a[0].clone();
163        tmp += &a[2];
164
165        t3 *= &tmp;
166        t3 -= &a_a;
167        t3 += &b_b;
168        t3 -= &c_c;
169    }
170
171    let mut t2 = b[0].clone();
172    t2 += &b[1];
173    {
174        let mut tmp = a[0].clone();
175        tmp += &a[1];
176
177        t2 *= &tmp;
178        t2 -= &a_a;
179        t2 -= &b_b;
180        c_c *= xi;
181        t2 += &c_c;
182    }
183
184    a[0] = t1;
185    a[1] = t2;
186    a[2] = t3;
187}