use std::{cmp::min, str::FromStr};
use crate::{FftField, FieldError, FieldParameters, PoseidonDefaultField};
use snarkvm_utilities::biginteger::BigInteger;
pub trait PrimeField:
FftField<FftParameters = <Self as PrimeField>::Parameters> + PoseidonDefaultField + FromStr<Err = FieldError>
{
const SIZE_IN_BITS: usize = Self::Parameters::MODULUS_BITS as usize;
const SIZE_IN_DATA_BITS: usize = Self::Parameters::CAPACITY as usize;
type Parameters: FieldParameters<BigInteger = Self::BigInteger>;
type BigInteger: BigInteger;
fn from_bigint(repr: Self::BigInteger) -> Option<Self>;
fn to_bigint(&self) -> Self::BigInteger;
fn decompose(
&self,
q1: &[u64; 4],
q2: &[u64; 4],
b1: Self,
b2: Self,
r128: Self,
half_r: &[u64; 8],
) -> (Self, Self, bool, bool);
fn size_in_bits() -> usize {
Self::Parameters::MODULUS_BITS as usize
}
fn size_in_data_bits() -> usize {
Self::Parameters::CAPACITY as usize
}
fn modulus() -> Self::BigInteger {
Self::Parameters::MODULUS
}
fn modulus_minus_one_div_two() -> Self::BigInteger {
Self::Parameters::MODULUS_MINUS_ONE_DIV_TWO
}
fn trace() -> Self::BigInteger {
Self::Parameters::T
}
fn trace_minus_one_div_two() -> Self::BigInteger {
Self::Parameters::T_MINUS_ONE_DIV_TWO
}
fn from_bytes_be_mod_order(bytes: &[u8]) -> Self {
let num_modulus_bytes = Self::Parameters::MODULUS_BITS.div_ceil(8) as usize;
let num_bytes_to_directly_convert = min(num_modulus_bytes - 1, bytes.len());
let (leading_bytes, remaining_bytes) = bytes.split_at(num_bytes_to_directly_convert);
let mut bytes_to_directly_convert = leading_bytes.to_vec();
bytes_to_directly_convert.reverse();
let mut res = Self::from_random_bytes(&bytes_to_directly_convert).unwrap();
let window_size = Self::from(256u64);
for byte in remaining_bytes {
res *= window_size;
res += Self::from(*byte);
}
res
}
fn from_bytes_le_mod_order(bytes: &[u8]) -> Self {
let mut bytes_copy = bytes.to_vec();
bytes_copy.reverse();
Self::from_bytes_be_mod_order(&bytes_copy)
}
}