use crate::{
syscalls::{
syscall_bn254_complex_add, syscall_bn254_complex_mul, syscall_bn254_complex_sub,
SyscallBn254ComplexAddParams, SyscallBn254ComplexMulParams, SyscallBn254ComplexSubParams,
SyscallComplex256,
},
zisklib::{eq, fcall_bn254_fp2_inv, is_one, is_zero, lt},
};
use super::constants::{P, P_MINUS_ONE};
#[inline]
fn to_syscall_complex(limbs: &[u64; 8]) -> SyscallComplex256 {
SyscallComplex256 { x: limbs[0..4].try_into().unwrap(), y: limbs[4..8].try_into().unwrap() }
}
#[inline]
fn to_syscall_complex_x(limbs: &[u64; 4]) -> SyscallComplex256 {
SyscallComplex256 { x: *limbs, y: [0u64; 4] }
}
#[inline]
fn to_syscall_complex_y(limbs: &[u64; 4]) -> SyscallComplex256 {
SyscallComplex256 { x: [0u64; 4], y: *limbs }
}
#[inline]
fn from_syscall_complex(complex: &SyscallComplex256) -> [u64; 8] {
let mut result = [0u64; 8];
result[0..4].copy_from_slice(&complex.x);
result[4..8].copy_from_slice(&complex.y);
result
}
#[inline]
pub fn add_fp2_bn254(
a: &[u64; 8],
b: &[u64; 8],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex(b);
let mut params = SyscallBn254ComplexAddParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_add(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn dbl_fp2_bn254(a: &[u64; 8], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex(a);
let mut params = SyscallBn254ComplexAddParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_add(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn neg_fp2_bn254(a: &[u64; 8], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex_x(&P_MINUS_ONE);
let mut params = SyscallBn254ComplexMulParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_mul(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn sub_fp2_bn254(
a: &[u64; 8],
b: &[u64; 8],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex(b);
let mut params = SyscallBn254ComplexSubParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_sub(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn mul_fp2_bn254(
a: &[u64; 8],
b: &[u64; 8],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex(b);
let mut params = SyscallBn254ComplexMulParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_mul(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn scalar_mul_fp2_bn254(
a: &[u64; 8],
b: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex_x(b);
let mut params = SyscallBn254ComplexMulParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_mul(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn square_fp2_bn254(a: &[u64; 8], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 8] {
let mut f1 = to_syscall_complex(a);
let f2 = to_syscall_complex(a);
let mut params = SyscallBn254ComplexMulParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_mul(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}
#[inline]
pub fn inv_fp2_bn254(a: &[u64; 8], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 8] {
if is_zero(a) {
return *a;
}
let inv = fcall_bn254_fp2_inv(
a,
#[cfg(feature = "hints")]
hints,
);
assert!(lt(&inv[0..4], &P) && lt(&inv[4..8], &P), "Inverse is not canonical");
let product = mul_fp2_bn254(
a,
&inv,
#[cfg(feature = "hints")]
hints,
);
assert!(is_one(&product), "Inverse verification failed");
inv
}
#[inline]
pub fn conjugate_fp2_bn254(
a: &[u64; 8],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 8] {
let mut f1 = to_syscall_complex_x(&a[0..4].try_into().unwrap());
let f2 = to_syscall_complex_y(&a[4..8].try_into().unwrap());
let mut params = SyscallBn254ComplexSubParams { f1: &mut f1, f2: &f2 };
syscall_bn254_complex_sub(
&mut params,
#[cfg(feature = "hints")]
hints,
);
from_syscall_complex(&f1)
}