| /// Provides both inherent and trait impls for a field element type which are |
| /// backed by a core set of arithmetic functions specified as macro arguments. |
| /// |
| /// # Inherent impls |
| /// - `const ZERO: Self` |
| /// - `const ONE: Self` (multiplicative identity) |
| /// - `pub fn from_be_bytes` |
| /// - `pub fn from_be_slice` |
| /// - `pub fn from_le_bytes` |
| /// - `pub fn from_le_slice` |
| /// - `pub fn from_uint` |
| /// - `fn from_uint_unchecked` |
| /// - `pub fn to_be_bytes` |
| /// - `pub fn to_le_bytes` |
| /// - `pub fn to_canonical` |
| /// - `pub fn is_odd` |
| /// - `pub fn is_zero` |
| /// - `pub fn double` |
| /// |
| /// NOTE: field implementations must provide their own inherent impls of |
| /// the following methods in order for the code generated by this macro to |
| /// compile: |
| /// |
| /// - `pub fn invert` |
| /// - `pub fn sqrt` |
| /// |
| /// # Trait impls |
| /// - `AsRef<$arr>` |
| /// - `ConditionallySelectable` |
| /// - `ConstantTimeEq` |
| /// - `ConstantTimeGreater` |
| /// - `ConstantTimeLess` |
| /// - `Default` |
| /// - `DefaultIsZeroes` |
| /// - `Eq` |
| /// - `Field` |
| /// - `PartialEq` |
| /// |
| /// ## Ops |
| /// - `Add` |
| /// - `AddAssign` |
| /// - `Sub` |
| /// - `SubAssign` |
| /// - `Mul` |
| /// - `MulAssign` |
| /// - `Neg` |
| #[macro_export] |
| macro_rules! impl_field_element { |
| ( |
| $fe:tt, |
| $bytes:ty, |
| $uint:ty, |
| $modulus:expr, |
| $arr:ty, |
| $from_mont:ident, |
| $to_mont:ident, |
| $add:ident, |
| $sub:ident, |
| $mul:ident, |
| $neg:ident, |
| $square:ident |
| ) => { |
| impl $fe { |
| /// Zero element. |
| pub const ZERO: Self = Self(<$uint>::ZERO); |
| |
| /// Multiplicative identity. |
| pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE); |
| |
| /// Create a [` |
| #[doc = stringify!($fe)] |
| /// `] from a canonical big-endian representation. |
| pub fn from_be_bytes(repr: $bytes) -> $crate::subtle::CtOption<Self> { |
| use $crate::bigint::ArrayEncoding as _; |
| Self::from_uint(<$uint>::from_be_byte_array(repr)) |
| } |
| |
| /// Decode [` |
| #[doc = stringify!($fe)] |
| /// `] from a big endian byte slice. |
| pub fn from_be_slice(slice: &[u8]) -> $crate::Result<Self> { |
| <$uint as $crate::bigint::Encoding>::Repr::try_from(slice) |
| .ok() |
| .and_then(|array| Self::from_be_bytes(array.into()).into()) |
| .ok_or($crate::Error) |
| } |
| |
| /// Create a [` |
| #[doc = stringify!($fe)] |
| /// `] from a canonical little-endian representation. |
| pub fn from_le_bytes(repr: $bytes) -> $crate::subtle::CtOption<Self> { |
| use $crate::bigint::ArrayEncoding as _; |
| Self::from_uint(<$uint>::from_le_byte_array(repr)) |
| } |
| |
| /// Decode [` |
| #[doc = stringify!($fe)] |
| /// `] from a little endian byte slice. |
| pub fn from_le_slice(slice: &[u8]) -> $crate::Result<Self> { |
| <$uint as $crate::bigint::Encoding>::Repr::try_from(slice) |
| .ok() |
| .and_then(|array| Self::from_le_bytes(array.into()).into()) |
| .ok_or($crate::Error) |
| } |
| |
| /// Decode [` |
| #[doc = stringify!($fe)] |
| /// `] |
| /// from [` |
| #[doc = stringify!($uint)] |
| /// `] converting it into Montgomery form: |
| /// |
| /// ```text |
| /// w * R^2 * R^-1 mod p = wR mod p |
| /// ``` |
| pub fn from_uint(uint: $uint) -> $crate::subtle::CtOption<Self> { |
| use $crate::subtle::ConstantTimeLess as _; |
| let is_some = uint.ct_lt(&$modulus); |
| $crate::subtle::CtOption::new(Self::from_uint_unchecked(uint), is_some) |
| } |
| |
| /// Parse a [` |
| #[doc = stringify!($fe)] |
| /// `] from big endian hex-encoded bytes. |
| /// |
| /// Does *not* perform a check that the field element does not overflow the order. |
| /// |
| /// This method is primarily intended for defining internal constants. |
| #[allow(dead_code)] |
| pub(crate) const fn from_be_hex(hex: &str) -> Self { |
| Self::from_uint_unchecked(<$uint>::from_be_hex(hex)) |
| } |
| |
| /// Parse a [` |
| #[doc = stringify!($fe)] |
| /// `] from little endian hex-encoded bytes. |
| /// |
| /// Does *not* perform a check that the field element does not overflow the order. |
| /// |
| /// This method is primarily intended for defining internal constants. |
| #[allow(dead_code)] |
| pub(crate) const fn from_le_hex(hex: &str) -> Self { |
| Self::from_uint_unchecked(<$uint>::from_le_hex(hex)) |
| } |
| |
| /// Decode [` |
| #[doc = stringify!($fe)] |
| /// `] from [` |
| #[doc = stringify!($uint)] |
| /// `] converting it into Montgomery form. |
| /// |
| /// Does *not* perform a check that the field element does not overflow the order. |
| /// |
| /// Used incorrectly this can lead to invalid results! |
| pub(crate) const fn from_uint_unchecked(w: $uint) -> Self { |
| Self(<$uint>::from_words($to_mont(w.as_words()))) |
| } |
| |
| /// Returns the big-endian encoding of this [` |
| #[doc = stringify!($fe)] |
| /// `]. |
| pub fn to_be_bytes(self) -> $bytes { |
| use $crate::bigint::ArrayEncoding as _; |
| self.to_canonical().to_be_byte_array() |
| } |
| |
| /// Returns the little-endian encoding of this [` |
| #[doc = stringify!($fe)] |
| /// `]. |
| pub fn to_le_bytes(self) -> $bytes { |
| use $crate::bigint::ArrayEncoding as _; |
| self.to_canonical().to_le_byte_array() |
| } |
| |
| /// Translate [` |
| #[doc = stringify!($fe)] |
| /// `] out of the Montgomery domain, returning a [` |
| #[doc = stringify!($uint)] |
| /// `] in canonical form. |
| #[inline] |
| pub const fn to_canonical(self) -> $uint { |
| <$uint>::from_words($from_mont(self.0.as_words())) |
| } |
| |
| /// Determine if this [` |
| #[doc = stringify!($fe)] |
| /// `] is odd in the SEC1 sense: `self mod 2 == 1`. |
| /// |
| /// # Returns |
| /// |
| /// If odd, return `Choice(1)`. Otherwise, return `Choice(0)`. |
| pub fn is_odd(&self) -> Choice { |
| use $crate::bigint::Integer; |
| self.to_canonical().is_odd() |
| } |
| |
| /// Determine if this [` |
| #[doc = stringify!($fe)] |
| /// `] is even in the SEC1 sense: `self mod 2 == 0`. |
| /// |
| /// # Returns |
| /// |
| /// If even, return `Choice(1)`. Otherwise, return `Choice(0)`. |
| pub fn is_even(&self) -> Choice { |
| !self.is_odd() |
| } |
| |
| /// Determine if this [` |
| #[doc = stringify!($fe)] |
| /// `] is zero. |
| /// |
| /// # Returns |
| /// |
| /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`. |
| pub fn is_zero(&self) -> Choice { |
| self.ct_eq(&Self::ZERO) |
| } |
| |
| /// Add elements. |
| pub const fn add(&self, rhs: &Self) -> Self { |
| Self(<$uint>::from_words($add( |
| self.0.as_words(), |
| rhs.0.as_words(), |
| ))) |
| } |
| |
| /// Double element (add it to itself). |
| #[must_use] |
| pub const fn double(&self) -> Self { |
| self.add(self) |
| } |
| |
| /// Subtract elements. |
| pub const fn sub(&self, rhs: &Self) -> Self { |
| Self(<$uint>::from_words($sub( |
| self.0.as_words(), |
| rhs.0.as_words(), |
| ))) |
| } |
| |
| /// Multiply elements. |
| pub const fn mul(&self, rhs: &Self) -> Self { |
| Self(<$uint>::from_words($mul( |
| self.0.as_words(), |
| rhs.0.as_words(), |
| ))) |
| } |
| |
| /// Negate element. |
| pub const fn neg(&self) -> Self { |
| Self(<$uint>::from_words($neg(self.0.as_words()))) |
| } |
| |
| /// Compute modular square. |
| #[must_use] |
| pub const fn square(&self) -> Self { |
| Self(<$uint>::from_words($square(self.0.as_words()))) |
| } |
| } |
| |
| impl AsRef<$arr> for $fe { |
| fn as_ref(&self) -> &$arr { |
| self.0.as_ref() |
| } |
| } |
| |
| impl Default for $fe { |
| fn default() -> Self { |
| Self::ZERO |
| } |
| } |
| |
| impl Eq for $fe {} |
| |
| impl PartialEq for $fe { |
| fn eq(&self, rhs: &Self) -> bool { |
| self.0.ct_eq(&(rhs.0)).into() |
| } |
| } |
| |
| impl $crate::subtle::ConditionallySelectable for $fe { |
| fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { |
| Self(<$uint>::conditional_select(&a.0, &b.0, choice)) |
| } |
| } |
| |
| impl $crate::subtle::ConstantTimeEq for $fe { |
| fn ct_eq(&self, other: &Self) -> $crate::subtle::Choice { |
| self.0.ct_eq(&other.0) |
| } |
| } |
| |
| impl $crate::subtle::ConstantTimeGreater for $fe { |
| fn ct_gt(&self, other: &Self) -> $crate::subtle::Choice { |
| self.0.ct_gt(&other.0) |
| } |
| } |
| |
| impl $crate::subtle::ConstantTimeLess for $fe { |
| fn ct_lt(&self, other: &Self) -> $crate::subtle::Choice { |
| self.0.ct_lt(&other.0) |
| } |
| } |
| |
| impl $crate::zeroize::DefaultIsZeroes for $fe {} |
| |
| impl $crate::ff::Field for $fe { |
| fn random(mut rng: impl $crate::rand_core::RngCore) -> Self { |
| // NOTE: can't use ScalarCore::random due to CryptoRng bound |
| let mut bytes = <$bytes>::default(); |
| |
| loop { |
| rng.fill_bytes(&mut bytes); |
| if let Some(fe) = Self::from_be_bytes(bytes).into() { |
| return fe; |
| } |
| } |
| } |
| |
| fn zero() -> Self { |
| Self::ZERO |
| } |
| |
| fn one() -> Self { |
| Self::ONE |
| } |
| |
| fn is_zero(&self) -> Choice { |
| Self::ZERO.ct_eq(self) |
| } |
| |
| #[must_use] |
| fn square(&self) -> Self { |
| self.square() |
| } |
| |
| #[must_use] |
| fn double(&self) -> Self { |
| self.double() |
| } |
| |
| fn invert(&self) -> CtOption<Self> { |
| self.invert() |
| } |
| |
| fn sqrt(&self) -> CtOption<Self> { |
| self.sqrt() |
| } |
| } |
| |
| $crate::impl_field_op!($fe, $uint, Add, add, $add); |
| $crate::impl_field_op!($fe, $uint, Sub, sub, $sub); |
| $crate::impl_field_op!($fe, $uint, Mul, mul, $mul); |
| |
| impl AddAssign<$fe> for $fe { |
| #[inline] |
| fn add_assign(&mut self, other: $fe) { |
| *self = *self + other; |
| } |
| } |
| |
| impl AddAssign<&$fe> for $fe { |
| #[inline] |
| fn add_assign(&mut self, other: &$fe) { |
| *self = *self + other; |
| } |
| } |
| |
| impl SubAssign<$fe> for $fe { |
| #[inline] |
| fn sub_assign(&mut self, other: $fe) { |
| *self = *self - other; |
| } |
| } |
| |
| impl SubAssign<&$fe> for $fe { |
| #[inline] |
| fn sub_assign(&mut self, other: &$fe) { |
| *self = *self - other; |
| } |
| } |
| |
| impl MulAssign<&$fe> for $fe { |
| #[inline] |
| fn mul_assign(&mut self, other: &$fe) { |
| *self = *self * other; |
| } |
| } |
| |
| impl MulAssign for $fe { |
| #[inline] |
| fn mul_assign(&mut self, other: $fe) { |
| *self = *self * other; |
| } |
| } |
| |
| impl Neg for $fe { |
| type Output = $fe; |
| |
| #[inline] |
| fn neg(self) -> $fe { |
| Self($neg(self.as_ref()).into()) |
| } |
| } |
| }; |
| } |
| |
| /// Emit impls for a `core::ops` trait for all combinations of reference types, |
| /// which thunk to the given function. |
| #[macro_export] |
| macro_rules! impl_field_op { |
| ($fe:tt, $uint:ty, $op:tt, $op_fn:ident, $func:ident) => { |
| impl ::core::ops::$op for $fe { |
| type Output = $fe; |
| |
| #[inline] |
| fn $op_fn(self, rhs: $fe) -> $fe { |
| $fe($func(self.as_ref(), rhs.as_ref()).into()) |
| } |
| } |
| |
| impl ::core::ops::$op<&$fe> for $fe { |
| type Output = $fe; |
| |
| #[inline] |
| fn $op_fn(self, rhs: &$fe) -> $fe { |
| $fe($func(self.as_ref(), rhs.as_ref()).into()) |
| } |
| } |
| |
| impl ::core::ops::$op<&$fe> for &$fe { |
| type Output = $fe; |
| |
| #[inline] |
| fn $op_fn(self, rhs: &$fe) -> $fe { |
| $fe($func(self.as_ref(), rhs.as_ref()).into()) |
| } |
| } |
| }; |
| } |