use super::*;
use rand::Rng;
pub trait Field:
'static
+ Clone
+ Copy
+ Default
+ core::fmt::Display
+ core::fmt::Debug
+ core::hash::Hash
+ core::cmp::PartialEq
+ core::cmp::Eq
+ core::marker::Send
+ core::marker::Sync
+ core::default::Default
+ Rand
+ Sized
{
const ZERO: Self;
const ONE: Self;
type CharField = Self;
fn is_zero(&self) -> bool;
fn inverse(&self) -> Option<Self>;
fn add_assign(&'_ mut self, other: &Self) -> &'_ mut Self;
fn sub_assign(&'_ mut self, other: &Self) -> &'_ mut Self;
fn mul_assign(&'_ mut self, other: &Self) -> &'_ mut Self;
fn square(&'_ mut self) -> &'_ mut Self;
fn negate(&'_ mut self) -> &'_ mut Self;
fn double(&'_ mut self) -> &'_ mut Self;
fn pow(&self, mut exp: u32) -> Self {
let mut base = *self;
let mut result = Self::ONE;
while exp > 0 {
if exp % 2 == 1 {
result.mul_assign(&base);
}
exp >>= 1;
base.square();
}
result
}
fn exp_power_of_2(&mut self, power_log: usize) {
for _ in 0..power_log {
self.square();
}
}
fn mul_by_two(&'_ mut self) -> &'_ mut Self {
unimplemented!()
}
fn div_by_two(&'_ mut self) -> &'_ mut Self {
unimplemented!()
}
#[inline(always)]
fn fused_mul_add_assign(&'_ mut self, a: &Self, b: &Self) -> &'_ mut Self {
let mut t = *a;
t.mul_assign(&b);
self.add_assign(&t);
self
}
}
pub trait PrimeField: Field {
const TWO: Self;
const MINUS_ONE: Self;
const NUM_BYTES_IN_REPR: usize;
const CHAR_BITS: usize;
const CHARACTERISTICS: u64;
fn as_u64(self) -> u64;
fn from_u64_unchecked(value: u64) -> Self;
fn from_u64_with_reduction(value: u64) -> Self;
fn from_u64(value: u64) -> Option<Self>;
fn as_u64_reduced(&self) -> u64;
fn as_boolean(&self) -> bool;
fn from_boolean(flag: bool) -> Self {
if flag {
Self::ONE
} else {
Self::ZERO
}
}
fn to_le_bytes(self) -> [u8; Self::NUM_BYTES_IN_REPR];
fn increment_unchecked(&'_ mut self);
}
pub trait BaseField: Field {
const QUADRATIC_NON_RESIDUE: Self;
fn mul_by_non_residue(elem: &mut Self) {
elem.mul_assign(&Self::QUADRATIC_NON_RESIDUE);
}
}
pub trait FieldExtension<BaseField: Field> {
const DEGREE: usize;
fn mul_assign_by_base(&mut self, elem: &BaseField) -> &mut Self;
fn into_coeffs_in_base(self) -> [BaseField; Self::DEGREE];
fn from_base_coeffs_array(coefs: &[BaseField; Self::DEGREE]) -> Self;
fn from_coeffs_in_base(coefs: &[BaseField]) -> Self;
fn from_coeffs_in_base_ref(coefs: &[&BaseField]) -> Self;
fn from_coeffs_in_base_iter<I: Iterator<Item = BaseField>>(coefs_iter: I) -> Self;
fn coeffs_in_base(&self) -> &[BaseField];
fn add_assign_base(&mut self, elem: &BaseField) -> &mut Self;
fn sub_assign_base(&mut self, elem: &BaseField) -> &mut Self;
fn from_base(elem: BaseField) -> Self;
fn get_coef_mut(&mut self, idx: usize) -> &mut BaseField;
}
impl<F: Field> FieldExtension<F> for F {
const DEGREE: usize = 1;
#[inline(always)]
fn from_coeffs_in_base(coefs: &[F]) -> Self {
coefs[0]
}
#[inline(always)]
fn from_base_coeffs_array(coefs: &[F; Self::DEGREE]) -> Self {
coefs[0]
}
#[inline(always)]
fn from_coeffs_in_base_ref(coefs: &[&F]) -> Self {
*coefs[0]
}
#[inline(always)]
fn into_coeffs_in_base(self) -> [Self; 1] {
[self]
}
#[inline(always)]
fn from_coeffs_in_base_iter<I: Iterator<Item = F>>(mut coefs_iter: I) -> Self {
coefs_iter.next().unwrap()
}
#[inline(always)]
fn coeffs_in_base(&self) -> &[F] {
core::slice::from_ref(self)
}
#[inline(always)]
fn mul_assign_by_base(&mut self, elem: &F) -> &mut Self {
self.mul_assign(elem)
}
#[inline(always)]
fn add_assign_base(&mut self, elem: &F) -> &mut Self {
self.add_assign(elem)
}
#[inline(always)]
fn sub_assign_base(&mut self, elem: &F) -> &mut Self {
self.sub_assign(elem)
}
#[inline(always)]
fn from_base(elem: F) -> Self {
elem
}
#[inline(always)]
fn get_coef_mut(&mut self, idx: usize) -> &mut F {
assert_eq!(idx, 0);
self
}
}
pub trait TwoAdicField: Field {
const TWO_ADICITY: usize;
#[must_use]
fn two_adic_generator() -> Self;
#[must_use]
fn two_adic_group_order() -> usize;
}
impl<F: PrimeField> Rand for F {
fn random_element<R: Rng + ?Sized>(rng: &mut R) -> F {
F::from_u64_unchecked(rng.gen_range(0..F::CHARACTERISTICS))
}
}