use ic_core::ct::Choice;
macro_rules! dispatch {
($f:ident ( $($arg:expr),* $(,)? )) => {{
#[cfg(all(target_arch = "x86_64", not(any(ic_limb32, ic_ec_portable))))]
{
if crate::fe64::available() {
$f::<crate::fe64::Fe64>($($arg),*)
} else {
$f::<crate::field::Fe>($($arg),*)
}
}
#[cfg(not(all(target_arch = "x86_64", not(any(ic_limb32, ic_ec_portable)))))]
{
$f::<crate::field::Fe>($($arg),*)
}
}};
}
pub(crate) use dispatch;
#[cfg(test)]
pub(crate) fn selected() -> &'static str {
fn name<F: Field>() -> &'static str {
core::any::type_name::<F>()
}
dispatch!(name())
}
pub(crate) trait Field: Copy {
const ZERO: Self;
const ONE: Self;
fn from_limbs51(l: [u64; 5]) -> Self;
fn from_bytes(bytes: &[u8; 32]) -> Self;
fn to_bytes(self) -> [u8; 32];
fn add(&self, other: &Self) -> Self;
fn sub(&self, other: &Self) -> Self;
fn mul(&self, other: &Self) -> Self;
fn square(&self) -> Self;
fn mul121666(&self) -> Self;
fn cmov(a: &mut Self, b: &Self, choice: Choice);
#[cfg(feature = "std")]
#[inline]
fn cmov_bit(a: &mut Self, b: &Self, bit: u64) {
Self::cmov(a, b, Choice::from_u8(bit as u8))
}
#[inline]
fn select_bit(a: &Self, b: &Self, bit: u64) -> Self {
let mut r = *a;
Self::cmov(&mut r, b, Choice::from_u8(bit as u8));
r
}
#[inline]
fn neg(&self) -> Self {
Self::ZERO.sub(self)
}
#[inline]
fn square_n(&self, n: usize) -> Self {
let mut r = *self;
for _ in 0..n {
r = r.square();
}
r
}
#[inline]
fn pow_2_250_1(&self) -> (Self, Self) {
let z2 = self.square();
let z9 = z2.square_n(2).mul(self);
let z11 = z9.mul(&z2);
let z2_5_0 = z11.square().mul(&z9);
let z2_10_0 = z2_5_0.square_n(5).mul(&z2_5_0);
let z2_20_0 = z2_10_0.square_n(10).mul(&z2_10_0);
let z2_40_0 = z2_20_0.square_n(20).mul(&z2_20_0);
let z2_50_0 = z2_40_0.square_n(10).mul(&z2_10_0);
let z2_100_0 = z2_50_0.square_n(50).mul(&z2_50_0);
let z2_200_0 = z2_100_0.square_n(100).mul(&z2_100_0);
(z2_200_0.square_n(50).mul(&z2_50_0), z11)
}
#[inline]
fn invert(&self) -> Self {
let (z2_250_0, z11) = self.pow_2_250_1();
z2_250_0.square_n(5).mul(&z11)
}
#[inline]
fn pow22523(&self) -> Self {
let (z2_250_0, _) = self.pow_2_250_1();
z2_250_0.square_n(2).mul(self)
}
fn pow22523_pair(a: &Self, b: &Self) -> (Self, Self) {
let sq = |x: &Self, y: &Self, n: usize| {
let (mut x, mut y) = (*x, *y);
for _ in 0..n {
x = x.square();
y = y.square();
}
(x, y)
};
let m = |x: (Self, Self), y: (Self, Self)| (x.0.mul(&y.0), x.1.mul(&y.1));
let z1 = (*a, *b);
let z2 = sq(&z1.0, &z1.1, 1);
let t = sq(&z2.0, &z2.1, 2);
let z9 = m(t, z1);
let z11 = m(z9, z2);
let t = sq(&z11.0, &z11.1, 1);
let z2_5_0 = m(t, z9);
let t = sq(&z2_5_0.0, &z2_5_0.1, 5);
let z2_10_0 = m(t, z2_5_0);
let t = sq(&z2_10_0.0, &z2_10_0.1, 10);
let z2_20_0 = m(t, z2_10_0);
let t = sq(&z2_20_0.0, &z2_20_0.1, 20);
let z2_40_0 = m(t, z2_20_0);
let t = sq(&z2_40_0.0, &z2_40_0.1, 10);
let z2_50_0 = m(t, z2_10_0);
let t = sq(&z2_50_0.0, &z2_50_0.1, 50);
let z2_100_0 = m(t, z2_50_0);
let t = sq(&z2_100_0.0, &z2_100_0.1, 100);
let z2_200_0 = m(t, z2_100_0);
let t = sq(&z2_200_0.0, &z2_200_0.1, 50);
let z2_250_0 = m(t, z2_50_0);
let t = sq(&z2_250_0.0, &z2_250_0.1, 2);
m(t, z1)
}
#[inline]
fn is_zero(&self) -> Choice {
ic_core::ct::is_zero(&self.to_bytes())
}
#[inline]
fn ct_eq(&self, other: &Self) -> Choice {
ic_core::ct::eq(&self.to_bytes(), &other.to_bytes())
}
#[inline]
fn is_negative(&self) -> Choice {
Choice::from_u8(self.to_bytes()[0] & 1)
}
}
impl Field for crate::field::Fe {
const ZERO: Self = crate::field::Fe::ZERO;
const ONE: Self = crate::field::Fe::ONE;
#[inline]
fn from_limbs51(l: [u64; 5]) -> Self {
crate::field::Fe::from_limbs51(l)
}
#[inline]
fn from_bytes(bytes: &[u8; 32]) -> Self {
crate::field::Fe::from_bytes(bytes)
}
#[inline]
fn to_bytes(self) -> [u8; 32] {
crate::field::Fe::to_bytes(self)
}
#[inline]
fn add(&self, other: &Self) -> Self {
crate::field::Fe::add(self, other)
}
#[inline]
fn sub(&self, other: &Self) -> Self {
crate::field::Fe::sub(self, other)
}
#[inline]
fn mul(&self, other: &Self) -> Self {
crate::field::Fe::mul(self, other)
}
#[inline]
fn square(&self) -> Self {
crate::field::Fe::square(self)
}
#[inline]
fn mul121666(&self) -> Self {
crate::field::Fe::mul121666(self)
}
#[inline]
fn cmov(a: &mut Self, b: &Self, choice: Choice) {
crate::field::Fe::cmov(a, b, choice)
}
#[inline]
fn neg(&self) -> Self {
crate::field::Fe::neg(self)
}
#[inline]
fn square_n(&self, n: usize) -> Self {
crate::field::Fe::square_n(self, n)
}
#[inline]
fn invert(&self) -> Self {
crate::field::Fe::invert(self)
}
#[inline]
fn pow22523(&self) -> Self {
crate::field::Fe::pow22523(self)
}
#[inline]
fn is_zero(&self) -> Choice {
crate::field::Fe::is_zero(self)
}
#[inline]
fn ct_eq(&self, other: &Self) -> Choice {
crate::field::Fe::ct_eq(self, other)
}
#[inline]
fn is_negative(&self) -> Choice {
crate::field::Fe::is_negative(self)
}
}
#[cfg(all(target_arch = "x86_64", not(any(ic_limb32, ic_ec_portable))))]
impl Field for crate::fe64::Fe64 {
const ZERO: Self = crate::fe64::Fe64::ZERO;
const ONE: Self = crate::fe64::Fe64::ONE;
#[inline]
fn from_limbs51(l: [u64; 5]) -> Self {
crate::fe64::Fe64::from_limbs51(l)
}
#[inline]
fn from_bytes(bytes: &[u8; 32]) -> Self {
crate::fe64::Fe64::from_bytes(bytes)
}
#[inline]
fn to_bytes(self) -> [u8; 32] {
crate::fe64::Fe64::to_bytes(self)
}
#[inline(always)]
fn add(&self, other: &Self) -> Self {
crate::fe64::Fe64::add(self, other)
}
#[inline(always)]
fn sub(&self, other: &Self) -> Self {
crate::fe64::Fe64::sub(self, other)
}
#[inline(always)]
fn mul(&self, other: &Self) -> Self {
crate::fe64::Fe64::mul(self, other)
}
#[inline(always)]
fn square(&self) -> Self {
crate::fe64::Fe64::square(self)
}
#[inline(always)]
fn mul121666(&self) -> Self {
crate::fe64::Fe64::mul121666(self)
}
#[inline(always)]
fn cmov(a: &mut Self, b: &Self, choice: Choice) {
crate::fe64::Fe64::cmov(a, b, choice)
}
#[inline(always)]
fn select_bit(a: &Self, b: &Self, bit: u64) -> Self {
crate::fe64::Fe64::select_mask(a, b, crate::fe64::mask(bit))
}
#[cfg(feature = "std")]
#[inline(always)]
fn cmov_bit(a: &mut Self, b: &Self, bit: u64) {
*a = crate::fe64::Fe64::select_mask(a, b, crate::fe64::mask(bit));
}
#[inline(always)]
fn neg(&self) -> Self {
crate::fe64::Fe64::neg(self)
}
#[inline]
fn invert(&self) -> Self {
crate::fe64::Fe64::invert(self)
}
}