use std::ops::{Add, Mul, Neg, Sub};
use subtle::{Choice, ConditionallySelectable, CtOption};
pub trait FieldRandom: Sized {
fn random(rng: &mut (impl rand::CryptoRng + rand::Rng)) -> Self;
}
pub trait FieldOps:
Sized
+ Clone
+ PartialEq
+ Eq
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Neg<Output = Self>
+ Default
+ ConditionallySelectable
{
fn zero() -> Self;
fn one() -> Self;
fn is_zero(&self) -> Choice;
fn is_one(&self) -> Choice;
fn negate(&self) -> Self;
fn add(&self, rhs: &Self) -> Self;
fn sub(&self, rhs: &Self) -> Self;
fn mul(&self, rhs: &Self) -> Self;
fn square(&self) -> Self;
fn double(&self) -> Self;
fn invert(&self) -> CtOption<Self>;
fn div(&self, rhs: &Self) -> CtOption<Self> {
rhs.invert().map(|inv| self.mul(&inv))
}
fn pow_vartime(&self, exp: &[u64]) -> Self {
let mut result = Self::one();
let mut base = self.clone();
for &limb in exp {
let mut limb = limb;
for _ in 0..64 {
let mybit = limb & 1;
let tmp = <Self as FieldOps>::mul(&result, &base);
result = Self::conditional_select(&result, &tmp, (mybit as u8).into());
base = <Self as FieldOps>::square(&base);
limb >>= 1;
}
}
result
}
fn pow(&self, exp: &[u64]) -> Self {
let mut result = Self::one();
let mut base = self.clone();
for &limb in exp.iter().rev() {
let mut limb = limb.reverse_bits();
for _ in 0..64 {
let mybit = limb & 1;
Self::conditional_swap(&mut base, &mut result, (mybit as u8).into());
base = <Self as FieldOps>::mul(&result, &base);
result = <Self as FieldOps>::square(&result);
Self::conditional_swap(&mut base, &mut result, (mybit as u8).into());
limb >>= 1;
}
}
result
}
fn frobenius(&self) -> Self;
fn frobenius_pow(&self, k: u32) -> Self {
let mut result = self.clone();
for _ in 0..k {
result = result.frobenius();
}
result
}
fn norm(&self) -> Self;
fn trace(&self) -> Self;
fn sqrt(&self) -> CtOption<Self>;
fn inverse_and_sqrt(&self) -> (CtOption<Self>, CtOption<Self>) {
(self.invert(), self.sqrt())
}
fn inv_sqrt(&self) -> CtOption<Self> {
self.sqrt().and_then(|s| s.invert())
}
fn invertme_sqrtother(&self, rhs: &Self) -> (CtOption<Self>, CtOption<Self>) {
(self.invert(), rhs.sqrt())
}
fn sqrt_ratio(&self, rhs: &Self) -> CtOption<Self> {
rhs.invert().and_then(|inv_rhs| self.mul(&inv_rhs).sqrt())
}
fn legendre(&self) -> i8;
fn characteristic() -> Vec<u64>;
fn degree() -> u32;
fn from_u64(x: u64) -> Self;
}
pub trait FieldFromRepr: FieldOps {
type Repr;
fn from_repr(x: Self::Repr) -> Self;
}