use primitive_types::{H512, U256, U512};
use rand_core::{CryptoRng, TryCryptoRng};
use std::fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex};
use std::iter::{Product, Sum};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use std::str::FromStr;
use subtle::{
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
CtOption,
};
pub trait Field:
'static
+ Debug
+ Default
+ Sized
+ Send
+ Sync
+ Copy
+ Clone
+ Eq
+ Ord
+ ConstantTimeEq
+ ConstantTimeGreater
+ ConstantTimeLess
+ ConditionallySelectable
+ Add<Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ AddAssign<Self>
+ for<'a> AddAssign<&'a Self>
+ Neg<Output = Self>
+ Sub<Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ SubAssign<Self>
+ for<'a> SubAssign<&'a Self>
+ Mul<Output = Self>
+ for<'a> Mul<&'a Self, Output = Self>
+ MulAssign<Self>
+ for<'a> MulAssign<&'a Self>
+ Div<Output = Self>
+ for<'a> Div<&'a Self, Output = Self>
+ DivAssign<Self>
+ for<'a> DivAssign<&'a Self>
+ Sum
+ Product
+ Display
+ Binary
+ Octal
+ LowerHex
+ UpperHex
+ FromStr
+ From<u8>
+ From<u16>
+ TryFrom<usize, Error: Debug>
{
const LEN: usize;
const NUM_BITS: usize = Self::LEN * 8;
const BITS: usize = Self::NUM_BITS;
const ZERO: Self;
const ONE: Self;
const MAX: Self;
fn zero() -> Self {
Self::ZERO
}
fn one() -> Self {
Self::ONE
}
fn is_zero(&self) -> Choice {
self.ct_eq(&Self::ZERO)
}
fn is_even(&self) -> Choice {
!self.is_odd()
}
fn is_odd(&self) -> Choice;
fn try_random<R: TryCryptoRng>(rng: &mut R) -> Result<Self, R::Error>;
fn random<R: CryptoRng>(rng: &mut R) -> Self;
fn random_default() -> Self;
fn double(&self) -> Self {
self.add(self)
}
fn square(&self) -> Self {
self.mul(self)
}
fn cube(&self) -> Self {
self.square() * self
}
fn invert(&self) -> CtOption<Self>;
fn invert_unwrap(&self) -> Self {
self.invert().unwrap()
}
fn invert_or_zero(&self) -> Self {
self.invert().unwrap_or(Self::ZERO)
}
fn invert_vartime(&self) -> Option<Self>;
fn invert_batch(values: &mut [Self]) {
let length = values.len();
let mut partial_products = vec![Self::ONE; length];
let mut accumulator = Self::ONE;
for i in 0..length {
partial_products[i] = accumulator;
accumulator *= values[i];
}
let mut inverse = accumulator.invert_unwrap();
for i in (0..length).rev() {
let input = values[i];
values[i] = partial_products[i] * inverse;
inverse *= input;
}
}
fn invert_batch_vartime(values: &mut [Self]) {
let length = values.len();
let mut partial_products = vec![Self::ONE; length];
let mut accumulator = Self::ONE;
for i in 0..length {
partial_products[i] = accumulator;
accumulator *= values[i];
}
let mut inverse = accumulator.invert_vartime().unwrap();
for i in (0..length).rev() {
let input = values[i];
values[i] = partial_products[i] * inverse;
inverse *= input;
}
}
fn pow(self, exp: Self) -> Self;
fn pow_vartime(self, exp: Self) -> Self;
fn pow_small(mut self, mut exp: usize) -> Self {
let mut result = Self::ONE;
for _ in 0..usize::BITS {
let product = result * self;
result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
exp >>= 1;
self = self.square();
}
result
}
fn pow_small_vartime(mut self, mut exp: usize) -> Self {
let mut result = Self::ONE;
while exp != 0 {
if (exp & 1) != 0 {
result *= self;
}
exp >>= 1;
self = self.square();
}
result
}
fn pow_u32(mut self, mut exp: u32) -> Self {
let mut result = Self::ONE;
for _ in 0..u32::BITS {
let product = result * self;
result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
exp >>= 1;
self = self.square();
}
result
}
fn pow_u32_vartime(mut self, mut exp: u32) -> Self {
let mut result = Self::ONE;
while exp != 0 {
if (exp & 1) != 0 {
result *= self;
}
exp >>= 1;
self = self.square();
}
result
}
fn pow_u64(mut self, mut exp: u64) -> Self {
let mut result = Self::ONE;
for _ in 0..u64::BITS {
let product = result * self;
result = Self::conditional_select(&result, &product, Choice::from((exp & 1) as u8));
exp >>= 1;
self = self.square();
}
result
}
fn pow_u64_vartime(mut self, mut exp: u64) -> Self {
let mut result = Self::ONE;
while exp != 0 {
if (exp & 1) != 0 {
result *= self;
}
exp >>= 1;
self = self.square();
}
result
}
fn div_int(&self, rhs: &Self) -> (Self, Self);
fn try_from_le_bytes(bytes: &[u8]) -> CtOption<Self>;
fn try_from_be_bytes(bytes: &[u8]) -> CtOption<Self>;
fn from_str_radix(s: &str, radix: usize) -> Result<Self, std::fmt::Error>;
fn to_str_radix(&self, radix: usize, pad_to: usize, upper_case: bool) -> String;
fn try_to_u8(&self) -> Option<u8>;
fn try_to_u16(&self) -> Option<u16>;
}
pub trait Field64: Field + From<u32> + TryFrom<u64, Error: Debug> {
fn to_le_bytes(&self) -> [u8; 8];
fn to_be_bytes(&self) -> [u8; 8];
fn from_u128_mod_n(u128: u128) -> Self;
fn from_u256_mod_n(u256: U256) -> Self;
fn try_to_u32(&self) -> CtOption<u32>;
fn to_u64(&self) -> u64;
fn to_u128(&self) -> u128;
fn to_u256(&self) -> U256;
fn to_u512(&self) -> U512;
}
pub trait Field256:
Field + From<u32> + From<u64> + From<u128> + TryFrom<U256, Error: Debug>
{
fn to_le_bytes(&self) -> [u8; 32];
fn to_be_bytes(&self) -> [u8; 32];
fn from_u512_mod_n(u512: U512) -> Self;
fn from_h512(h512: H512) -> Self;
fn try_to_u32(&self) -> CtOption<u32>;
fn try_to_u64(&self) -> CtOption<u64>;
fn try_to_u128(&self) -> CtOption<u128>;
fn to_u256(&self) -> U256;
fn to_u512(&self) -> U512;
}
pub trait PrimeField: Field {
const MODULUS: &'static str;
const S: usize;
const MULTIPLICATIVE_GENERATOR: Self;
const MINUS_TWO: Self;
const TWO_INV: Self;
const ROOT_OF_UNITY: Self;
const ROOT_OF_UNITY_INV: Self;
const DELTA: Self;
}
pub trait PrimeField64: Field64 + PrimeField {}
pub trait PrimeField256: Field256 + PrimeField {}
pub trait ThreeAdicField: PrimeField {
const T: usize;
const THREE_INV: Self;
const THREE_ADIC_ROOT_OF_UNITY: Self;
const THREE_ADIC_ROOT_OF_UNITY_INV: Self;
}