openvm_pairing_guest/bn254/
fp2.rs
1use alloc::vec::Vec;
2use core::ops::Neg;
3
4use openvm_algebra_complex_macros::{complex_declare, complex_impl_field};
5use openvm_algebra_guest::{field::FieldExtension, Field, IntMod};
6
7use super::Fp;
8
9complex_declare! {
12 Bn254Fp2 { mod_type = Fp }
13}
14
15complex_impl_field! {
16 Bn254Fp2,
17}
18
19pub type Fp2 = Bn254Fp2;
20
21impl FieldExtension<Fp> for Fp2 {
22 const D: usize = 2;
23 type Coeffs = [Fp; 2];
24
25 fn from_coeffs([c0, c1]: Self::Coeffs) -> Self {
26 Self { c0, c1 }
27 }
28
29 fn from_bytes(bytes: &[u8]) -> Self {
30 assert_eq!(bytes.len(), 64);
31 Self::from_coeffs([
32 Fp::from_const_bytes(bytes[0..32].try_into().unwrap()),
33 Fp::from_const_bytes(bytes[32..64].try_into().unwrap()),
34 ])
35 }
36
37 fn to_coeffs(self) -> Self::Coeffs {
38 [self.c0, self.c1]
39 }
40
41 fn to_bytes(&self) -> Vec<u8> {
42 let mut bytes = Vec::with_capacity(64);
43 bytes.extend_from_slice(self.c0.as_le_bytes());
44 bytes.extend_from_slice(self.c1.as_le_bytes());
45 bytes
46 }
47
48 fn embed(c0: Fp) -> Self {
49 Self {
50 c0,
51 c1: <Fp as Field>::ZERO,
52 }
53 }
54
55 fn frobenius_map(&self, power: usize) -> Self {
56 if power % 2 == 0 {
57 self.clone()
58 } else {
59 Self {
60 c0: self.c0.clone(),
61 c1: (&self.c1).neg(),
62 }
63 }
64 }
65
66 fn mul_base(&self, rhs: &Fp) -> Self {
67 Self {
68 c0: &self.c0 * rhs,
69 c1: &self.c1 * rhs,
70 }
71 }
72}