use snarkvm_fields::PrimeField;
use snarkvm_gadgets::{nonnative::NonNativeFieldVar, traits::fields::FieldGadget};
use snarkvm_r1cs::{ConstraintSystem, SynthesisError};
use crate::PhantomData;
pub struct AlgebraForAHP<F: PrimeField, CF: PrimeField> {
field: PhantomData<F>,
constraint_field: PhantomData<CF>,
}
impl<TargetField: PrimeField, BaseField: PrimeField> AlgebraForAHP<TargetField, BaseField> {
pub fn prepare<CS: ConstraintSystem<BaseField>>(
cs: CS,
x: &NonNativeFieldVar<TargetField, BaseField>,
domain_size: u64,
) -> Result<NonNativeFieldVar<TargetField, BaseField>, SynthesisError> {
x.pow_by_constant(cs, &[domain_size])
}
pub fn prepared_eval_vanishing_polynomial<CS: ConstraintSystem<BaseField>>(
mut cs: CS,
x_prepared: &NonNativeFieldVar<TargetField, BaseField>,
) -> Result<NonNativeFieldVar<TargetField, BaseField>, SynthesisError> {
let one = NonNativeFieldVar::<TargetField, BaseField>::one(cs.ns(|| "one"))?;
let result = x_prepared.sub(cs.ns(|| "x_prepared_minus_one"), &one)?;
Ok(result)
}
pub fn eval_vanishing_polynomial<CS: ConstraintSystem<BaseField>>(
mut cs: CS,
x: &NonNativeFieldVar<TargetField, BaseField>,
domain_size: u64,
) -> Result<NonNativeFieldVar<TargetField, BaseField>, SynthesisError> {
let x_prepared = Self::prepare(cs.ns(|| "x_prepared"), x, domain_size)?;
Self::prepared_eval_vanishing_polynomial(cs, &x_prepared)
}
pub fn prepared_eval_bivariable_vanishing_polynomial<CS: ConstraintSystem<BaseField>>(
mut cs: CS,
x: &NonNativeFieldVar<TargetField, BaseField>,
y: &NonNativeFieldVar<TargetField, BaseField>,
x_prepared: &NonNativeFieldVar<TargetField, BaseField>,
y_prepared: &NonNativeFieldVar<TargetField, BaseField>,
) -> Result<NonNativeFieldVar<TargetField, BaseField>, SynthesisError> {
let denominator = x.sub(cs.ns(|| "denominator"), y)?;
let numerator = x_prepared.sub(cs.ns(|| "numerator"), y_prepared)?;
let denominator_invert = denominator.inverse(cs.ns(|| "denominator_inverse"))?;
let result = numerator.mul(cs.ns(|| "numerator_over_denominator"), &denominator_invert)?;
Ok(result)
}
pub fn eval_bivariate_vanishing_polynomial<CS: ConstraintSystem<BaseField>>(
mut cs: CS,
x: &NonNativeFieldVar<TargetField, BaseField>,
y: &NonNativeFieldVar<TargetField, BaseField>,
domain_size: u64,
) -> Result<NonNativeFieldVar<TargetField, BaseField>, SynthesisError> {
let x_prepared = Self::prepare(cs.ns(|| "x_prepared"), x, domain_size)?;
let y_prepared = Self::prepare(cs.ns(|| "y_prepared"), y, domain_size)?;
Self::prepared_eval_bivariable_vanishing_polynomial(cs, x, y, &x_prepared, &y_prepared)
}
}