use crate::fields::models::small_fp::small_fp_backend::{SmallFp, SmallFpConfig};
use crate::{Field, LegendreSymbol, One, PrimeField, SqrtPrecomputation, Zero};
use ark_serialize::{buffer_byte_size, EmptyFlags, Flags};
use core::iter;
impl<P: SmallFpConfig> Field for SmallFp<P> {
type BasePrimeField = Self;
const SQRT_PRECOMP: Option<SqrtPrecomputation<Self>> = P::SQRT_PRECOMP;
const ONE: Self = P::ONE;
const NEG_ONE: Self = P::NEG_ONE;
fn extension_degree() -> u64 {
1
}
fn from_base_prime_field(elem: Self::BasePrimeField) -> Self {
elem
}
fn to_base_prime_field_elements(&self) -> impl Iterator<Item = Self> {
iter::once(*self)
}
fn from_base_prime_field_elems(
elems: impl IntoIterator<Item = Self::BasePrimeField>,
) -> Option<Self> {
let mut iter = elems.into_iter();
let first = iter.next()?;
if iter.next().is_some() {
None
} else {
Some(first)
}
}
#[inline]
fn characteristic() -> &'static [u64] {
Self::MODULUS.as_ref()
}
#[inline]
fn sum_of_products<const T: usize>(a: &[Self; T], b: &[Self; T]) -> Self {
P::sum_of_products(a, b)
}
#[inline]
fn from_random_bytes_with_flags<F: Flags>(bytes: &[u8]) -> Option<(Self, F)> {
if F::BIT_SIZE > 8 {
None
} else {
let shave_bits = Self::num_bits_to_shave();
let mut result_bytes: crate::const_helpers::SerBuffer<1> =
crate::const_helpers::SerBuffer::zeroed();
result_bytes.copy_from_u8_slice(bytes);
let last_limb_mask =
(u64::MAX.checked_shr(shave_bits as u32).unwrap_or(0)).to_le_bytes();
let mut last_bytes_mask = [0u8; 9];
last_bytes_mask[..8].copy_from_slice(&last_limb_mask);
let output_byte_size = buffer_byte_size(Self::MODULUS_BIT_SIZE as usize + F::BIT_SIZE);
let flag_location = output_byte_size - 1;
let flag_location_in_last_limb =
flag_location.saturating_sub(8 * (P::NUM_BIG_INT_LIMBS - 1));
let last_bytes = result_bytes.last_n_plus_1_bytes_mut();
let flags_mask = u8::MAX.checked_shl(8 - (F::BIT_SIZE as u32)).unwrap_or(0);
let mut flags: u8 = 0;
for (i, (b, m)) in last_bytes.zip(&last_bytes_mask).enumerate() {
if i == flag_location_in_last_limb {
flags = *b & flags_mask
}
*b &= m;
}
let bigint = result_bytes.to_bigint();
Self::from_bigint(bigint).and_then(|f| F::from_u8(flags).map(|flag| (f, flag)))
}
}
#[inline]
fn square(&self) -> Self {
let mut temp = *self;
temp.square_in_place();
temp
}
fn square_in_place(&mut self) -> &mut Self {
P::square_in_place(self);
self
}
#[inline]
fn inverse(&self) -> Option<Self> {
P::inverse(self)
}
fn inverse_in_place(&mut self) -> Option<&mut Self> {
self.inverse().map(|inverse| {
*self = inverse;
self
})
}
#[inline]
fn frobenius_map_in_place(&mut self, _: usize) {}
#[inline]
fn legendre(&self) -> LegendreSymbol {
let s = self.pow(Self::MODULUS_MINUS_ONE_DIV_TWO);
if s.is_zero() {
LegendreSymbol::Zero
} else if s.is_one() {
LegendreSymbol::QuadraticResidue
} else {
LegendreSymbol::QuadraticNonResidue
}
}
fn mul_by_base_prime_field(&self, elem: &Self::BasePrimeField) -> Self {
*self * elem
}
fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
Self::from_random_bytes_with_flags::<EmptyFlags>(bytes).map(|f| f.0)
}
fn sqrt(&self) -> Option<Self> {
match Self::SQRT_PRECOMP {
Some(tv) => tv.sqrt(self),
None => ark_std::unimplemented!(),
}
}
fn sqrt_in_place(&mut self) -> Option<&mut Self> {
(*self).sqrt().map(|sqrt| {
*self = sqrt;
self
})
}
fn frobenius_map(&self, power: usize) -> Self {
let mut this = *self;
this.frobenius_map_in_place(power);
this
}
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
let mut res = Self::one();
for i in crate::BitIteratorBE::without_leading_zeros(exp) {
res.square_in_place();
if i {
res *= self;
}
}
res
}
fn pow_with_table<S: AsRef<[u64]>>(powers_of_2: &[Self], exp: S) -> Option<Self> {
let mut res = Self::one();
for (pow, bit) in crate::BitIteratorLE::without_trailing_zeros(exp).enumerate() {
if bit {
res *= powers_of_2.get(pow)?;
}
}
Some(res)
}
}