use core::{
convert::TryFrom,
fmt::{Debug, Display},
ops::{
Add, AddAssign, BitAnd, Div, DivAssign, Mul, MulAssign, Neg, Shl, Shr, ShrAssign, Sub,
SubAssign,
},
};
use utils::{
collections::Vec, AsBytes, Deserializable, DeserializationError, Randomizable, Serializable,
};
pub trait FieldElement:
Copy
+ Clone
+ Debug
+ Display
+ Default
+ Send
+ Sync
+ Eq
+ PartialEq
+ Sized
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Mul<Self, Output = Self>
+ Div<Self, Output = Self>
+ AddAssign<Self>
+ SubAssign<Self>
+ MulAssign<Self>
+ DivAssign<Self>
+ Neg<Output = Self>
+ From<u128>
+ From<u64>
+ From<u32>
+ From<u16>
+ From<u8>
+ for<'a> TryFrom<&'a [u8]>
+ ExtensionOf<<Self as FieldElement>::BaseField>
+ AsBytes
+ Randomizable
+ Serializable
+ Deserializable
{
type PositiveInteger: Debug
+ Copy
+ PartialEq
+ PartialOrd
+ ShrAssign
+ Shl<u32, Output = Self::PositiveInteger>
+ Shr<u32, Output = Self::PositiveInteger>
+ BitAnd<Output = Self::PositiveInteger>
+ From<u32>
+ From<u64>;
type BaseField: StarkField;
const EXTENSION_DEGREE: usize;
const ELEMENT_BYTES: usize;
const IS_CANONICAL: bool;
const ZERO: Self;
const ONE: Self;
#[inline]
#[must_use]
fn double(self) -> Self {
self + self
}
#[inline]
#[must_use]
fn square(self) -> Self {
self * self
}
#[inline]
#[must_use]
fn cube(self) -> Self {
self * self * self
}
#[must_use]
fn exp(self, power: Self::PositiveInteger) -> Self {
self.exp_vartime(power)
}
#[must_use]
fn exp_vartime(self, power: Self::PositiveInteger) -> Self {
let mut r = Self::ONE;
let mut b = self;
let mut p = power;
let int_zero = Self::PositiveInteger::from(0u32);
let int_one = Self::PositiveInteger::from(1u32);
if p == int_zero {
return Self::ONE;
} else if b == Self::ZERO {
return Self::ZERO;
}
while p > int_zero {
if p & int_one == int_one {
r *= b;
}
p >>= int_one;
b = b.square();
}
r
}
#[must_use]
fn inv(self) -> Self;
#[must_use]
fn conjugate(&self) -> Self;
fn base_element(&self, i: usize) -> Self::BaseField;
fn slice_as_base_elements(elements: &[Self]) -> &[Self::BaseField];
fn slice_from_base_elements(elements: &[Self::BaseField]) -> &[Self];
fn elements_as_bytes(elements: &[Self]) -> &[u8];
unsafe fn bytes_as_elements(bytes: &[u8]) -> Result<&[Self], DeserializationError>;
fn zeroed_vector(n: usize) -> Vec<Self> {
vec![Self::ZERO; n]
}
}
pub trait StarkField: FieldElement<BaseField = Self> {
const MODULUS: Self::PositiveInteger;
const MODULUS_BITS: u32;
const GENERATOR: Self;
const TWO_ADICITY: u32;
const TWO_ADIC_ROOT_OF_UNITY: Self;
fn get_root_of_unity(n: u32) -> Self {
assert!(n != 0, "cannot get root of unity for n = 0");
assert!(
n <= Self::TWO_ADICITY,
"order cannot exceed 2^{}",
Self::TWO_ADICITY
);
let power = Self::PositiveInteger::from(1u32) << (Self::TWO_ADICITY - n);
Self::TWO_ADIC_ROOT_OF_UNITY.exp(power)
}
fn get_modulus_le_bytes() -> Vec<u8>;
fn as_int(&self) -> Self::PositiveInteger;
}
pub trait ExtensibleField<const N: usize>: StarkField {
fn mul(a: [Self; N], b: [Self; N]) -> [Self; N];
fn square(a: [Self; N]) -> [Self; N] {
<Self as ExtensibleField<N>>::mul(a, a)
}
fn mul_base(a: [Self; N], b: Self) -> [Self; N];
fn frobenius(x: [Self; N]) -> [Self; N];
fn is_supported() -> bool {
true
}
}
pub trait ExtensionOf<E: FieldElement>: From<E> {
fn mul_base(self, other: E) -> Self;
}
impl<E: FieldElement> ExtensionOf<E> for E {
#[inline(always)]
fn mul_base(self, other: E) -> Self {
self * other
}
}
pub trait ToElements<E: FieldElement> {
fn to_elements(&self) -> Vec<E>;
}
impl<E: FieldElement> ToElements<E> for () {
fn to_elements(&self) -> Vec<E> {
Vec::new()
}
}
impl<E: FieldElement> ToElements<E> for E {
fn to_elements(&self) -> Vec<E> {
vec![*self]
}
}