use crate::zisklib::lib::utils::eq;
use super::{
fp12::mul_fp12_bn254,
fp2::{
add_fp2_bn254, dbl_fp2_bn254, inv_fp2_bn254, mul_fp2_bn254, scalar_mul_fp2_bn254,
square_fp2_bn254, sub_fp2_bn254,
},
};
pub fn compress_cyclo_bn254(a: &[u64; 48]) -> [u64; 32] {
let a4: &[u64; 8] = &a[8..16].try_into().unwrap();
let a3: &[u64; 8] = &a[16..24].try_into().unwrap();
let a2: &[u64; 8] = &a[24..32].try_into().unwrap();
let a5: &[u64; 8] = &a[40..48].try_into().unwrap();
let mut result = [0; 32];
result[0..8].copy_from_slice(a2);
result[8..16].copy_from_slice(a3);
result[16..24].copy_from_slice(a4);
result[24..32].copy_from_slice(a5);
result
}
#[inline]
pub fn decompress_cyclo_bn254(
a: &[u64; 32],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 48] {
let a2: &[u64; 8] = &a[0..8].try_into().unwrap();
let a3: &[u64; 8] = &a[8..16].try_into().unwrap();
let a4: &[u64; 8] = &a[16..24].try_into().unwrap();
let a5: &[u64; 8] = &a[24..32].try_into().unwrap();
let (a0, a1) = if eq(a2, &[0, 0, 0, 0, 0, 0, 0, 0]) {
let a3_inv = inv_fp2_bn254(
a3,
#[cfg(feature = "hints")]
hints,
);
let mut a1 = mul_fp2_bn254(
a4,
a5,
#[cfg(feature = "hints")]
hints,
);
a1 = dbl_fp2_bn254(
&a1,
#[cfg(feature = "hints")]
hints,
);
a1 = mul_fp2_bn254(
&a1,
&a3_inv,
#[cfg(feature = "hints")]
hints,
);
let a3a4 = mul_fp2_bn254(
a3,
a4,
#[cfg(feature = "hints")]
hints,
);
let mut a0 = square_fp2_bn254(
&a1,
#[cfg(feature = "hints")]
hints,
);
a0 = dbl_fp2_bn254(
&a0,
#[cfg(feature = "hints")]
hints,
);
a0 = sub_fp2_bn254(
&a0,
&scalar_mul_fp2_bn254(
&a3a4,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
a0 = mul_fp2_bn254(
&a0,
&[9, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
a0 = add_fp2_bn254(
&a0,
&[1, 0, 0, 0, 0, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
(a0, a1)
} else {
let a2_inv = inv_fp2_bn254(
&scalar_mul_fp2_bn254(
a2,
&[4, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
let a4_sq = square_fp2_bn254(
a4,
#[cfg(feature = "hints")]
hints,
);
let mut a1 = square_fp2_bn254(
a5,
#[cfg(feature = "hints")]
hints,
);
a1 = mul_fp2_bn254(
&a1,
&[9, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
a1 = add_fp2_bn254(
&a1,
&scalar_mul_fp2_bn254(
&a4_sq,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
a1 = sub_fp2_bn254(
&a1,
&dbl_fp2_bn254(
a3,
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
a1 = mul_fp2_bn254(
&a1,
&a2_inv,
#[cfg(feature = "hints")]
hints,
);
let a3a4 = mul_fp2_bn254(
a3,
a4,
#[cfg(feature = "hints")]
hints,
);
let a2a5 = mul_fp2_bn254(
a2,
a5,
#[cfg(feature = "hints")]
hints,
);
let mut a0 = square_fp2_bn254(
&a1,
#[cfg(feature = "hints")]
hints,
);
a0 = dbl_fp2_bn254(
&a0,
#[cfg(feature = "hints")]
hints,
);
a0 = add_fp2_bn254(
&a0,
&a2a5,
#[cfg(feature = "hints")]
hints,
);
a0 = sub_fp2_bn254(
&a0,
&scalar_mul_fp2_bn254(
&a3a4,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
a0 = mul_fp2_bn254(
&a0,
&[9, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
a0 = add_fp2_bn254(
&a0,
&[1, 0, 0, 0, 0, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
(a0, a1)
};
let mut result = [0; 48];
result[0..8].copy_from_slice(&a0);
result[8..16].copy_from_slice(a4);
result[16..24].copy_from_slice(a3);
result[24..32].copy_from_slice(a2);
result[32..40].copy_from_slice(&a1);
result[40..48].copy_from_slice(a5);
result
}
pub fn square_cyclo_bn254(
a: &[u64; 32],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 32] {
let a2: &[u64; 8] = &a[0..8].try_into().unwrap();
let a3: &[u64; 8] = &a[8..16].try_into().unwrap();
let a4: &[u64; 8] = &a[16..24].try_into().unwrap();
let a5: &[u64; 8] = &a[24..32].try_into().unwrap();
let b23 = mul_fp2_bn254(
a2,
a3,
#[cfg(feature = "hints")]
hints,
);
let b45 = mul_fp2_bn254(
a4,
a5,
#[cfg(feature = "hints")]
hints,
);
let a3xi = mul_fp2_bn254(
a3,
&[9, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
let a23 = mul_fp2_bn254(
&add_fp2_bn254(
a2,
a3,
#[cfg(feature = "hints")]
hints,
),
&add_fp2_bn254(
a2,
&a3xi,
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
let a5xi = mul_fp2_bn254(
a5,
&[9, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
let a45 = mul_fp2_bn254(
&add_fp2_bn254(
a4,
a5,
#[cfg(feature = "hints")]
hints,
),
&add_fp2_bn254(
a4,
&a5xi,
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
let mut b2 = mul_fp2_bn254(
&b45,
&[9, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b2 = scalar_mul_fp2_bn254(
&b2,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b2 = add_fp2_bn254(
a2,
&b2,
#[cfg(feature = "hints")]
hints,
);
b2 = dbl_fp2_bn254(
&b2,
#[cfg(feature = "hints")]
hints,
);
let mut b3 = mul_fp2_bn254(
&b45,
&[10, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b3 = sub_fp2_bn254(
&a45,
&b3,
#[cfg(feature = "hints")]
hints,
);
b3 = scalar_mul_fp2_bn254(
&b3,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b3 = sub_fp2_bn254(
&b3,
&dbl_fp2_bn254(
a3,
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
let mut b4 = mul_fp2_bn254(
&b23,
&[10, 0, 0, 0, 1, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b4 = sub_fp2_bn254(
&a23,
&b4,
#[cfg(feature = "hints")]
hints,
);
b4 = scalar_mul_fp2_bn254(
&b4,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b4 = sub_fp2_bn254(
&b4,
&dbl_fp2_bn254(
a4,
#[cfg(feature = "hints")]
hints,
),
#[cfg(feature = "hints")]
hints,
);
let mut b5 = scalar_mul_fp2_bn254(
&b23,
&[3, 0, 0, 0],
#[cfg(feature = "hints")]
hints,
);
b5 = add_fp2_bn254(
a5,
&b5,
#[cfg(feature = "hints")]
hints,
);
b5 = dbl_fp2_bn254(
&b5,
#[cfg(feature = "hints")]
hints,
);
let mut result = [0; 32];
result[0..8].copy_from_slice(&b2);
result[8..16].copy_from_slice(&b3);
result[16..24].copy_from_slice(&b4);
result[24..32].copy_from_slice(&b5);
result
}
pub fn exp_by_x_cyclo_bn254(
a: &[u64; 48],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 48] {
const X_BIN_LE: [u8; 63] = [
1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0,
1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0,
0, 0, 1,
];
let mut result = *a;
let mut comp = compress_cyclo_bn254(a);
for &bit in X_BIN_LE.iter().skip(1) {
comp = square_cyclo_bn254(
&comp,
#[cfg(feature = "hints")]
hints,
);
if bit == 1 {
let decomp = decompress_cyclo_bn254(
&comp,
#[cfg(feature = "hints")]
hints,
);
result = mul_fp12_bn254(
&result,
&decomp,
#[cfg(feature = "hints")]
hints,
);
}
}
result
}