use super::{Fp, FpBackend};
use hybrid_array::Array;
use subtle::{Choice, ConstantTimeEq};
impl<L: FpBackend> Default for Fp<L> {
fn default() -> Self {
Self::zero()
}
}
impl<L: FpBackend> Fp<L> {
#[inline]
pub fn zero() -> Self {
let mut limbs = Array::<u64, L::FpLimbs>::default();
L::set_zero(&mut limbs);
Self { limbs }
}
#[inline]
pub fn one() -> Self {
let mut limbs = Array::<u64, L::FpLimbs>::default();
L::set_one(&mut limbs);
Self { limbs }
}
#[inline]
pub fn from_limbs(limbs: &[u64]) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
debug_assert_eq!(limbs.len(), out.len());
out.as_mut_slice().copy_from_slice(limbs);
Self { limbs: out }
}
#[inline]
pub fn from_small(val: u64) -> Self {
let mut limbs = Array::<u64, L::FpLimbs>::default();
L::set_small(&mut limbs, val);
Self { limbs }
}
#[inline]
pub fn ct_equal(&self, other: &Self) -> Choice {
L::is_equal(&self.limbs, &other.limbs)
}
#[inline]
pub fn ct_is_zero(&self) -> Choice {
L::is_zero(&self.limbs)
}
#[inline]
pub fn add(&self, rhs: &Self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::add(&mut out, &self.limbs, &rhs.limbs);
Self { limbs: out }
}
#[inline]
pub fn sub(&self, rhs: &Self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::sub(&mut out, &self.limbs, &rhs.limbs);
Self { limbs: out }
}
#[inline]
pub fn neg(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::neg(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn mul(&self, rhs: &Self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::mul(&mut out, &self.limbs, &rhs.limbs);
Self { limbs: out }
}
#[inline]
pub fn sqr(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::sqr(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn mul_small(&self, val: u32) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::mul_small(&mut out, &self.limbs, val);
Self { limbs: out }
}
#[inline]
pub fn inv(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::inv(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn sqrt(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::sqrt(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn is_square(&self) -> Choice {
L::is_square(&self.limbs)
}
#[inline]
pub fn half(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::half(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn div3(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::div3(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn exp3div4(&self) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::exp3div4(&mut out, &self.limbs);
Self { limbs: out }
}
#[inline]
pub fn encode(&self) -> Array<u8, L::FpEncodedBytes> {
let mut out = Array::<u8, L::FpEncodedBytes>::default();
L::encode(&mut out, &self.limbs);
out
}
#[inline]
pub fn decode(bytes: &[u8]) -> Option<Self> {
let mut limbs = Array::<u64, L::FpLimbs>::default();
let ok = L::decode(&mut limbs, bytes);
if bool::from(ok) {
Some(Self { limbs })
} else {
None
}
}
#[inline]
pub fn decode_reduce(bytes: &[u8]) -> Self {
let mut limbs = Array::<u64, L::FpLimbs>::default();
L::decode_reduce(&mut limbs, bytes);
Self { limbs }
}
#[inline]
pub fn cswap(&mut self, other: &mut Self, ctl: Choice) {
L::cswap(&mut self.limbs, &mut other.limbs, ctl);
}
#[inline]
pub fn select(a0: &Self, a1: &Self, ctl: Choice) -> Self {
let mut out = Array::<u64, L::FpLimbs>::default();
L::select(&mut out, &a0.limbs, &a1.limbs, ctl);
Self { limbs: out }
}
}
impl<L: FpBackend> ConstantTimeEq for Fp<L> {
#[inline]
fn ct_eq(&self, other: &Self) -> Choice {
self.ct_equal(other)
}
}