use ark_ff::{prelude::*, BitIteratorBE};
use ark_relations::r1cs::SynthesisError;
use core::{
fmt::Debug,
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
};
use crate::prelude::*;
pub mod cubic_extension;
pub mod quadratic_extension;
pub mod 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: Field>:
'static
+ Clone
+ From<Boolean<ConstraintF>>
+ R1CSVar<ConstraintF, Value = F>
+ EqGadget<ConstraintF>
+ ToBitsGadget<ConstraintF>
+ AllocVar<F, ConstraintF>
+ ToBytesGadget<ConstraintF>
+ CondSelectGadget<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>
+ 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> {
let d_inv = d.inverse()?;
Ok(d_inv * self)
}
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)
}
}