use std::fmt::Debug;
use std::ops::{Div, Neg, Sub};
use num_traits::{One, Zero};
pub trait Field:
Clone
+ PartialEq
+ Debug
+ Zero
+ One
+ Neg<Output = Self>
+ Sub<Output = Self>
+ Div<Output = Self>
{
fn inverse(&self) -> Option<Self> {
(!self.is_zero()).then(|| Self::one() / self.clone())
}
}
impl<F> Field for F where
F: Clone + PartialEq + Debug + Zero + One + Neg<Output = F> + Sub<Output = F> + Div<Output = F>
{
}
pub fn pow<F: Field>(x: &F, mut e: u64) -> F {
let (mut base, mut acc) = (x.clone(), F::one());
while e > 0 {
if e & 1 == 1 {
acc = acc * base.clone();
}
e >>= 1;
if e > 0 {
base = base.clone() * base;
}
}
acc
}
pub fn nat<F: Field>(n: u64) -> F {
let two = F::one() + F::one();
(0..u64::BITS - n.leading_zeros())
.rev()
.fold(F::zero(), |acc, i| {
let acc = acc * two.clone();
if n >> i & 1 == 1 { acc + F::one() } else { acc }
})
}