use std::{
fmt::Debug,
hash::Hash,
ops::{Mul, MulAssign},
};
use ff::Field;
use hybrid_array::{Array, ArraySize};
use rand::RngCore;
use serde::{Deserialize, Serialize};
use wincode::{SchemaRead, SchemaWrite};
use crate::{
algebra::{
ops::{AccReduce, DotProduct, MulAccReduce},
uniform_bytes::FromUniformBytes,
},
types::{HeapArray, Positive},
};
pub type ByteSize<F> = <F as FieldExtension>::FieldBytesSize;
pub type BitSize<F> = <F as FieldExtension>::FieldBitSize;
pub type FieldDegree<F> = <F as FieldExtension>::Degree;
pub type Subfield<F> = <F as FieldExtension>::Subfield;
pub trait FieldExtension:
Field
+ Ord
+ Debug
+ PartialEq
+ Hash
+ Mul<Self::Subfield, Output = Self>
+ MulAssign<Self::Subfield>
+ Serialize
+ for<'de> Deserialize<'de>
+ SchemaWrite<Src = Self>
+ for<'a> SchemaRead<'a, Dst = Self>
+ FromUniformBytes
+ From<u64>
+ From<u128>
+ AccReduce
+ MulAccReduce
+ MulAccReduce<Self, Self::Subfield>
+ DotProduct
+ for<'a> DotProduct<Self, &'a Self>
+ for<'a> DotProduct<&'a Self, &'a Self>
+ DotProduct<Self, Self::Subfield>
+ for<'a> DotProduct<&'a Self, Self::Subfield>
+ Unpin
{
type Subfield: FieldExtension<Subfield = Self::Subfield>;
type Degree: ArraySize + Positive;
type FieldBitSize: ArraySize + Positive;
type FieldBytesSize: ArraySize + Positive;
fn to_subfield_elements(&self) -> impl ExactSizeIterator<Item = Self::Subfield>;
fn from_subfield_elements(elems: &[Self::Subfield]) -> Option<Self>;
fn to_le_bytes(&self) -> Array<u8, Self::FieldBytesSize>;
fn from_le_bytes(bytes: &[u8]) -> Option<Self>;
fn mul_by_subfield(&self, other: &Self::Subfield) -> Self;
fn generator() -> Self;
fn random_elements<M: Positive>(mut rng: impl RngCore) -> HeapArray<Self, M> {
HeapArray::from_fn(|_| <Self as Field>::random(&mut rng))
}
fn linear_orthomorphism(&self) -> Self {
*self * Self::from(2u64)
}
}
pub trait PrimeFieldExtension: FieldExtension<Subfield = Self> {}
impl<F: FieldExtension<Subfield = Self>> PrimeFieldExtension for F {}