openvm_pairing_guest/pairing/
sextic_ext_field.rsuse core::{
fmt::{Debug, Formatter, Result},
ops::{Add, AddAssign, Sub, SubAssign},
};
use openvm_algebra_guest::field::Field;
#[cfg(target_os = "zkvm")]
use {
super::shifted_funct7,
crate::{PairingBaseFunct7, OPCODE, PAIRING_FUNCT3},
openvm_platform::custom_insn_r,
};
#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(C)]
pub struct SexticExtField<F> {
pub c: [F; 6],
}
impl<F> SexticExtField<F> {
pub const fn new(c: [F; 6]) -> Self {
Self { c }
}
}
impl<'a, F: Field> AddAssign<&'a SexticExtField<F>> for SexticExtField<F> {
#[inline(always)]
fn add_assign(&mut self, other: &'a SexticExtField<F>) {
for i in 0..6 {
self.c[i] += &other.c[i];
}
}
}
impl<'a, F: Field> Add<&'a SexticExtField<F>> for &SexticExtField<F> {
type Output = SexticExtField<F>;
#[inline(always)]
fn add(self, other: &'a SexticExtField<F>) -> Self::Output {
let mut res = self.clone();
res += other;
res
}
}
impl<'a, F: Field> SubAssign<&'a SexticExtField<F>> for SexticExtField<F> {
#[inline(always)]
fn sub_assign(&mut self, other: &'a SexticExtField<F>) {
for i in 0..6 {
self.c[i] -= &other.c[i];
}
}
}
impl<'a, F: Field> Sub<&'a SexticExtField<F>> for &SexticExtField<F> {
type Output = SexticExtField<F>;
#[inline(always)]
fn sub(self, other: &'a SexticExtField<F>) -> Self::Output {
let mut res = self.clone();
res -= other;
res
}
}
#[allow(dead_code)]
#[cfg(target_os = "zkvm")]
#[inline(always)]
pub(crate) fn sextic_tower_mul_intrinsic<P: super::PairingIntrinsics>(
dst: *mut u8,
lhs: *const u8,
rhs: *const u8,
) {
custom_insn_r!(
OPCODE,
PAIRING_FUNCT3,
shifted_funct7::<P>(PairingBaseFunct7::Fp12Mul),
dst,
lhs,
rhs
);
}
#[allow(dead_code)]
#[cfg(not(target_os = "zkvm"))]
pub(crate) fn sextic_tower_mul_host<F: Field>(
lhs: &SexticExtField<F>,
rhs: &SexticExtField<F>,
xi: &F,
) -> SexticExtField<F>
where
for<'a> &'a F: core::ops::Mul<&'a F, Output = F>,
{
let (s0, s1, s2, s3, s4, s5) = (
&lhs.c[0], &lhs.c[2], &lhs.c[4], &lhs.c[1], &lhs.c[3], &lhs.c[5],
);
let (o0, o1, o2, o3, o4, o5) = (
&rhs.c[0], &rhs.c[2], &rhs.c[4], &rhs.c[1], &rhs.c[3], &rhs.c[5],
);
let c0 = s0 * o0 + xi * &(s1 * o2 + s2 * o1 + s3 * o5 + s4 * o4 + s5 * o3);
let c1 = s0 * o1 + s1 * o0 + s3 * o3 + xi * &(s2 * o2 + s4 * o5 + s5 * o4);
let c2 = s0 * o2 + s1 * o1 + s2 * o0 + s3 * o4 + s4 * o3 + xi * &(s5 * o5);
let c3 = s0 * o3 + s3 * o0 + xi * &(s1 * o5 + s2 * o4 + s4 * o2 + s5 * o1);
let c4 = s0 * o4 + s1 * o3 + s3 * o1 + s4 * o0 + xi * &(s2 * o5 + s5 * o2);
let c5 = s0 * o5 + s1 * o4 + s2 * o3 + s3 * o2 + s4 * o1 + s5 * o0;
SexticExtField::new([c0, c3, c1, c4, c2, c5])
}
impl<F: Field> AddAssign for SexticExtField<F> {
#[inline(always)]
fn add_assign(&mut self, other: Self) {
self.add_assign(&other);
}
}
impl<F: Field> Add for SexticExtField<F> {
type Output = Self;
#[inline(always)]
fn add(mut self, other: Self) -> Self::Output {
self += other;
self
}
}
impl<'a, F: Field> Add<&'a SexticExtField<F>> for SexticExtField<F> {
type Output = Self;
#[inline(always)]
fn add(mut self, other: &'a SexticExtField<F>) -> Self::Output {
self += other;
self
}
}
impl<F: Field> SubAssign for SexticExtField<F> {
#[inline(always)]
fn sub_assign(&mut self, other: Self) {
self.sub_assign(&other);
}
}
impl<F: Field> Sub for SexticExtField<F> {
type Output = Self;
#[inline(always)]
fn sub(mut self, other: Self) -> Self::Output {
self -= other;
self
}
}
impl<'a, F: Field> Sub<&'a SexticExtField<F>> for SexticExtField<F> {
type Output = Self;
#[inline(always)]
fn sub(mut self, other: &'a SexticExtField<F>) -> Self::Output {
self -= other;
self
}
}
impl<F: Field> Debug for SexticExtField<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(
f,
"{:?}, {:?}, {:?}, {:?}, {:?}, {:?}",
self.c[0], self.c[1], self.c[2], self.c[3], self.c[4], self.c[5]
)
}
}