use ark_ff::{prelude::*, BitIteratorBE};
use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError};
use core::{
fmt::Debug,
iter::Sum,
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
};
use crate::{
convert::{ToBitsGadget, ToBytesGadget, ToConstraintFieldGadget},
prelude::*,
};
pub mod cubic_extension;
pub mod quadratic_extension;
pub mod fp;
pub mod emulated_fp;
pub mod fp12;
pub mod fp2;
pub mod fp3;
pub mod fp4;
pub mod fp6_2over3;
pub mod fp6_3over2;
pub trait FieldOpsBounds<'a, F, T: 'a>:
Sized
+ Add<&'a T, Output = T>
+ Sub<&'a T, Output = T>
+ Mul<&'a T, Output = T>
+ Add<T, Output = T>
+ Sub<T, Output = T>
+ Mul<T, Output = T>
+ Add<F, Output = T>
+ Sub<F, Output = T>
+ Mul<F, Output = T>
{
}
pub trait FieldVar<F: Field, ConstraintF: PrimeField>:
'static
+ Clone
+ From<Boolean<ConstraintF>>
+ GR1CSVar<ConstraintF, Value = F>
+ EqGadget<ConstraintF>
+ ToBitsGadget<ConstraintF>
+ AllocVar<F, ConstraintF>
+ ToBytesGadget<ConstraintF>
+ CondSelectGadget<ConstraintF>
+ ToConstraintFieldGadget<ConstraintF>
+ for<'a> FieldOpsBounds<'a, F, Self>
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
+ for<'a> MulAssign<&'a Self>
+ AddAssign<Self>
+ SubAssign<Self>
+ MulAssign<Self>
+ AddAssign<F>
+ SubAssign<F>
+ MulAssign<F>
+ Sum<Self>
+ for<'a> Sum<&'a Self>
+ Debug
{
fn zero() -> Self;
fn is_zero(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
self.is_eq(&Self::zero())
}
fn one() -> Self;
fn is_one(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
self.is_eq(&Self::one())
}
fn constant(v: F) -> Self;
fn double(&self) -> Result<Self, SynthesisError> {
Ok(self.clone() + self)
}
fn double_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
*self = self.double()?;
Ok(self)
}
fn negate(&self) -> Result<Self, SynthesisError>;
#[inline]
fn negate_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
*self = self.negate()?;
Ok(self)
}
fn square(&self) -> Result<Self, SynthesisError> {
Ok(self.clone() * self)
}
fn square_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
*self = self.square()?;
Ok(self)
}
fn mul_equals(&self, other: &Self, result: &Self) -> Result<(), SynthesisError> {
let actual_result = self.clone() * other;
result.enforce_equal(&actual_result)
}
fn square_equals(&self, result: &Self) -> Result<(), SynthesisError> {
let actual_result = self.square()?;
result.enforce_equal(&actual_result)
}
fn inverse(&self) -> Result<Self, SynthesisError>;
fn mul_by_inverse(&self, d: &Self) -> Result<Self, SynthesisError> {
d.enforce_not_equal(&Self::zero())?;
self.mul_by_inverse_unchecked(d)
}
fn mul_by_inverse_unchecked(&self, d: &Self) -> Result<Self, SynthesisError> {
let cs = self.cs().or(d.cs());
match cs {
ConstraintSystemRef::None => Self::new_constant(
cs,
self.value()? * d.value()?.inverse().expect("division by zero"),
),
_ => {
let result = Self::new_witness(ark_relations::ns!(cs, "self * d_inv"), || {
Ok(self.value()? * &d.value()?.inverse().unwrap_or(F::ZERO))
})?;
result.mul_equals(d, self)?;
Ok(result)
},
}
}
fn inner_product(this: &[Self], other: &[Self]) -> Result<Self, SynthesisError> {
if this.len() != other.len() {
return Err(SynthesisError::Unsatisfiable);
}
Ok(this.iter().zip(other).map(|(a, b)| a.clone() * b).sum())
}
fn frobenius_map(&self, power: usize) -> Result<Self, SynthesisError>;
fn frobenius_map_in_place(&mut self, power: usize) -> Result<&mut Self, SynthesisError> {
*self = self.frobenius_map(power)?;
Ok(self)
}
fn pow_le(&self, bits: &[Boolean<ConstraintF>]) -> Result<Self, SynthesisError> {
let mut res = Self::one();
let mut power = self.clone();
for bit in bits {
let tmp = res.clone() * &power;
res = bit.select(&tmp, &res)?;
power.square_in_place()?;
}
Ok(res)
}
fn pow_by_constant<S: AsRef<[u64]>>(&self, exp: S) -> Result<Self, SynthesisError> {
let mut res = Self::one();
for i in BitIteratorBE::without_leading_zeros(exp) {
res.square_in_place()?;
if i {
res *= self;
}
}
Ok(res)
}
}