use ff::PrimeField;
use group::prime::PrimeCurveAffine;
use pairing::{MillerLoopResult, MultiMillerLoop};
use rayon::prelude::*;
use crate::groth16::multiscalar::*;
use crate::SynthesisError;
pub(crate) fn pairing_miller_affine<E: MultiMillerLoop>(
left: &[E::G1Affine],
right: &[E::G2Affine],
) -> Result<<E as MultiMillerLoop>::Result, SynthesisError> {
if left.len() != right.len() {
return Err(SynthesisError::IncompatibleLengthVector(
"pairing_miller_affine left and right".to_string(),
));
}
let prepared: Vec<E::G2Prepared> = right.par_iter().map(|&p| p.into()).collect();
let pairs_ref: Vec<_> = left
.iter()
.zip(prepared.iter())
.map(|(a, b)| (a, b))
.collect();
Ok(E::multi_miller_loop(&pairs_ref))
}
pub(crate) fn pairing<E: MultiMillerLoop>(
left: &[E::G1Affine],
right: &[E::G2Affine],
) -> Result<E::Gt, SynthesisError> {
Ok(pairing_miller_affine::<E>(left, right)?.final_exponentiation())
}
pub(crate) fn multiexponentiation<G>(
left: &[G],
right: &[G::Scalar],
) -> Result<G::Curve, SynthesisError>
where
G: PrimeCurveAffine,
<G::Scalar as PrimeField>::Repr: Sync,
{
if left.len() != right.len() {
return Err(SynthesisError::IncompatibleLengthVector(
"multiexponentiation left and right".to_string(),
));
}
let table = precompute_fixed_window::<G>(left, WINDOW_SIZE);
let getter = |i: usize| -> <G::Scalar as PrimeField>::Repr { right[i].to_repr() };
Ok(par_multiscalar::<_, G>(
&ScalarList::Getter(getter, right.len()),
&table,
std::mem::size_of::<<G::Scalar as PrimeField>::Repr>() * 8,
))
}