use crate::{arcis_type, DataSize, EvalValue, Number, PackLocation};
use arcis_compiler::utils::{field::BaseField, used_field::UsedField};
use arcis_interpreter_proc_macros::ArcisType;
use ff::Field;
use num_traits::ToPrimitive;
use paste::paste;
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
macro_rules! impl_from_inner {
($t:ty) => {
paste! {
#[doc = "Converts"]
#[doc = concat!("`", stringify!($t), "`")]
#[doc = "to `Self`."]
pub fn [<from_$t>](x: $t) -> Self {
Self(Number::from(x).into())
}
#[doc = "Converts `Self` to "]
#[doc = concat!("`", stringify!($t), "`.")]
#[doc = "Is UB if the number is not within"]
#[doc = concat!("`", stringify!($t), "`'s")]
#[doc = "range."]
pub fn [<to_$t _unchecked>](self) -> $t {
self.0.to_signed_number().[<to_$t>]().expect("Conversion failed")
}
}
};
}
macro_rules! impl_from {
($($t:ty),*) => {
$(impl_from_inner!($t);)*
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ArcisType)]
pub struct BaseField25519(pub(crate) BaseField);
impl BaseField25519 {
impl_from!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
pub fn from_bool(x: bool) -> Self {
Self(Number::from(x).into())
}
pub fn to_bool_unchecked(self) -> bool {
self.0 == BaseField::from(true)
}
pub fn power_of_two(exponent: usize) -> Self {
Self(<BaseField as UsedField>::power_of_two(exponent))
}
pub fn to_le_bytes(&self) -> [u8; 32] {
self.0.to_le_bytes()
}
pub fn safe_inverse(self) -> Self {
Self(self.0.invert().unwrap_or(BaseField::ZERO))
}
pub fn field_division(self, divisor: Self) -> Self {
self * divisor.safe_inverse()
}
pub fn euclidean_division(self, divisor: Self) -> Self {
if divisor.0 == BaseField::ZERO {
panic!("Division by zero");
}
Self(self.0.signed_euclidean_division(divisor.0))
}
}
macro_rules! impl_binary_assign_trait {
($t:ident, $f:ident) => {
impl $t for BaseField25519 {
fn $f(&mut self, rhs: Self) {
self.0.$f(&rhs.0);
}
}
};
}
macro_rules! impl_binary_self_trait {
($t:ident, $f:ident) => {
impl $t for BaseField25519 {
type Output = Self;
fn $f(self, rhs: Self) -> Self {
Self(self.0.$f(rhs.0))
}
}
};
}
impl_binary_assign_trait!(AddAssign, add_assign);
impl_binary_assign_trait!(SubAssign, sub_assign);
impl_binary_assign_trait!(MulAssign, mul_assign);
impl_binary_self_trait!(Add, add);
impl_binary_self_trait!(Sub, sub);
impl_binary_self_trait!(Mul, mul);
impl Neg for BaseField25519 {
type Output = Self;
fn neg(self) -> Self {
Self(self.0.neg())
}
}