2021-08-14 17:57:08 +00:00
|
|
|
use std::fmt::{Display, Formatter, Result};
|
|
|
|
use std::ops::{Add, Mul, Sub};
|
|
|
|
|
|
|
|
/// Did I really implement an awfully hacky prime order field to play with this
|
|
|
|
/// Yes...yes I did...
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub struct PrimeOrderDomain<const ORDER: u64> {
|
|
|
|
val: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<const ORDER: u64> Display for PrimeOrderDomain<{ ORDER }> {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
2021-08-15 21:36:17 +00:00
|
|
|
write!(f, "{:20}", self.val)
|
2021-08-14 17:57:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<const ORDER: u64> PrimeOrderDomain<{ ORDER }> {
|
|
|
|
pub fn new(val: u64) -> PrimeOrderDomain<{ ORDER }> {
|
|
|
|
PrimeOrderDomain { val }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_zero(&self) -> bool {
|
|
|
|
self.val == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gt(&self, rhs: &Self) -> bool {
|
|
|
|
self.val > rhs.val
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn inverse(&self) -> Self {
|
2021-08-14 18:07:58 +00:00
|
|
|
self.pow(ORDER - 2) // at least it is faster an iterating...
|
2021-08-14 17:57:08 +00:00
|
|
|
}
|
|
|
|
|
2021-08-15 14:35:26 +00:00
|
|
|
// exponentiation by squaring
|
2021-08-14 17:57:08 +00:00
|
|
|
pub fn pow(&self, exp: u64) -> Self {
|
|
|
|
if exp == 0 {
|
|
|
|
return PrimeOrderDomain::new(1);
|
|
|
|
}
|
|
|
|
if exp == 1 {
|
|
|
|
return self.clone();
|
|
|
|
}
|
|
|
|
|
2021-08-15 14:35:26 +00:00
|
|
|
if exp % 2 == 0 {
|
|
|
|
(*self * *self).pow(exp / 2)
|
|
|
|
} else {
|
|
|
|
*self * self.pow(2).pow((exp - 1) / 2)
|
2021-08-14 17:57:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<const ORDER: u64> Add for PrimeOrderDomain<{ ORDER }> {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
|
|
PrimeOrderDomain {
|
|
|
|
val: ((self.val as u128 + rhs.val as u128) % ORDER as u128) as u64,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<const ORDER: u64> Sub for PrimeOrderDomain<{ ORDER }> {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
|
|
if rhs.val > self.val {
|
|
|
|
return PrimeOrderDomain {
|
|
|
|
val: ((ORDER - rhs.val) + self.val) % ORDER,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
PrimeOrderDomain {
|
|
|
|
val: (self.val - rhs.val) % ORDER,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<const ORDER: u64> Mul for PrimeOrderDomain<{ ORDER }> {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn mul(self, rhs: Self) -> Self::Output {
|
|
|
|
PrimeOrderDomain {
|
|
|
|
val: ((self.val as u128 * rhs.val as u128) % ORDER as u128) as u64,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|