Skip to content

Commit e09c55d

Browse files
authored
primefield: remove field_element_type_core! macro (#1272)
This macro was a workaround for when it wasn't possible to use the `field_element_type!` macro for all fields we implement in this repo. However, all crates now use `field_element_type!`, so we can (re)combine the two macros again.
1 parent b92289e commit e09c55d

File tree

1 file changed

+184
-199
lines changed

1 file changed

+184
-199
lines changed

primefield/src/lib.rs

Lines changed: 184 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,190 @@ macro_rules! field_element_type {
7474
$decode_uint:path,
7575
$encode_uint:path
7676
) => {
77-
$crate::field_element_type_core!($fe, $bytes, $uint, $modulus, $decode_uint, $encode_uint);
77+
impl $fe {
78+
/// Zero element.
79+
pub const ZERO: Self = Self(<$uint>::ZERO);
80+
81+
/// Multiplicative identity.
82+
pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE);
83+
84+
/// Create a [`
85+
#[doc = stringify!($fe)]
86+
/// `] from a canonical big-endian representation.
87+
pub fn from_bytes(repr: &$bytes) -> $crate::subtle::CtOption<Self> {
88+
Self::from_uint($decode_uint(repr))
89+
}
90+
91+
/// Decode [`
92+
#[doc = stringify!($fe)]
93+
/// `] from a big endian byte slice.
94+
pub fn from_slice(slice: &[u8]) -> Option<Self> {
95+
let array = <$bytes>::try_from(slice).ok()?;
96+
Self::from_bytes(&array).into()
97+
}
98+
99+
/// Decode [`
100+
#[doc = stringify!($fe)]
101+
/// `]
102+
/// from [`
103+
#[doc = stringify!($uint)]
104+
/// `] converting it into Montgomery form:
105+
///
106+
/// ```text
107+
/// w * R^2 * R^-1 mod p = wR mod p
108+
/// ```
109+
pub fn from_uint(uint: $uint) -> $crate::subtle::CtOption<Self> {
110+
use $crate::subtle::ConstantTimeLess as _;
111+
let is_some = uint.ct_lt(&$modulus);
112+
$crate::subtle::CtOption::new(Self::from_uint_unchecked(uint), is_some)
113+
}
114+
115+
/// Parse a [`
116+
#[doc = stringify!($fe)]
117+
/// `] from big endian hex-encoded bytes.
118+
///
119+
/// Does *not* perform a check that the field element does not overflow the order.
120+
///
121+
/// This method is primarily intended for defining internal constants.
122+
#[allow(dead_code)]
123+
pub(crate) const fn from_hex(hex: &str) -> Self {
124+
Self::from_uint_unchecked(<$uint>::from_be_hex(hex))
125+
}
126+
127+
/// Convert a `u64` into a [`
128+
#[doc = stringify!($fe)]
129+
/// `].
130+
pub const fn from_u64(w: u64) -> Self {
131+
Self::from_uint_unchecked(<$uint>::from_u64(w))
132+
}
133+
134+
/// Returns the big-endian encoding of this [`
135+
#[doc = stringify!($fe)]
136+
/// `].
137+
pub fn to_bytes(self) -> $bytes {
138+
$encode_uint(&self.to_canonical())
139+
}
140+
141+
/// Determine if this [`
142+
#[doc = stringify!($fe)]
143+
/// `] is odd in the SEC1 sense: `self mod 2 == 1`.
144+
///
145+
/// # Returns
146+
///
147+
/// If odd, return `Choice(1)`. Otherwise, return `Choice(0)`.
148+
pub fn is_odd(&self) -> $crate::subtle::Choice {
149+
use $crate::bigint::Integer;
150+
self.to_canonical().is_odd()
151+
}
152+
153+
/// Determine if this [`
154+
#[doc = stringify!($fe)]
155+
/// `] is even in the SEC1 sense: `self mod 2 == 0`.
156+
///
157+
/// # Returns
158+
///
159+
/// If even, return `Choice(1)`. Otherwise, return `Choice(0)`.
160+
pub fn is_even(&self) -> $crate::subtle::Choice {
161+
!self.is_odd()
162+
}
163+
164+
/// Determine if this [`
165+
#[doc = stringify!($fe)]
166+
/// `] is zero.
167+
///
168+
/// # Returns
169+
///
170+
/// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`.
171+
pub fn is_zero(&self) -> $crate::subtle::Choice {
172+
self.ct_eq(&Self::ZERO)
173+
}
174+
175+
/// Returns `self^exp`, where `exp` is a little-endian integer exponent.
176+
///
177+
/// **This operation is variable time with respect to the exponent.**
178+
///
179+
/// If the exponent is fixed, this operation is constant time.
180+
pub const fn pow_vartime(&self, exp: &[u64]) -> Self {
181+
let mut res = Self::ONE;
182+
let mut i = exp.len();
183+
184+
while i > 0 {
185+
i -= 1;
186+
187+
let mut j = 64;
188+
while j > 0 {
189+
j -= 1;
190+
res = res.square();
191+
192+
if ((exp[i] >> j) & 1) == 1 {
193+
res = res.multiply(self);
194+
}
195+
}
196+
}
197+
198+
res
199+
}
200+
201+
/// Right shifts the [`
202+
#[doc = stringify!($fe)]
203+
/// `].
204+
pub const fn shr(&self, shift: u32) -> Self {
205+
Self(self.0.wrapping_shr(shift))
206+
}
207+
208+
/// Right shifts the [`
209+
#[doc = stringify!($fe)]
210+
/// `].
211+
///
212+
/// Note: not constant-time with respect to the `shift` parameter.
213+
pub const fn shr_vartime(&self, shift: u32) -> Self {
214+
Self(self.0.wrapping_shr_vartime(shift))
215+
}
216+
}
217+
218+
impl $crate::ff::Field for $fe {
219+
const ZERO: Self = Self::ZERO;
220+
const ONE: Self = Self::ONE;
221+
222+
fn try_from_rng<R: $crate::rand_core::TryRngCore + ?Sized>(
223+
rng: &mut R,
224+
) -> ::core::result::Result<Self, R::Error> {
225+
let mut bytes = <$bytes>::default();
226+
227+
loop {
228+
rng.try_fill_bytes(&mut bytes)?;
229+
if let Some(fe) = Self::from_bytes(&bytes).into() {
230+
return Ok(fe);
231+
}
232+
}
233+
}
234+
235+
fn is_zero(&self) -> Choice {
236+
Self::ZERO.ct_eq(self)
237+
}
238+
239+
#[must_use]
240+
fn square(&self) -> Self {
241+
self.square()
242+
}
243+
244+
#[must_use]
245+
fn double(&self) -> Self {
246+
self.double()
247+
}
248+
249+
fn invert(&self) -> CtOption<Self> {
250+
self.invert()
251+
}
252+
253+
fn sqrt(&self) -> CtOption<Self> {
254+
self.sqrt()
255+
}
256+
257+
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
258+
$crate::ff::helpers::sqrt_ratio_generic(num, div)
259+
}
260+
}
78261

79262
$crate::field_op!($fe, Add, add, add);
80263
$crate::field_op!($fe, Sub, sub, sub);
@@ -313,204 +496,6 @@ macro_rules! field_element_type {
313496
};
314497
}
315498

316-
/// Core field element functionality
317-
#[macro_export]
318-
macro_rules! field_element_type_core {
319-
(
320-
$fe:tt,
321-
$bytes:ty,
322-
$uint:ty,
323-
$modulus:expr,
324-
$decode_uint:path,
325-
$encode_uint:path
326-
) => {
327-
impl $fe {
328-
/// Zero element.
329-
pub const ZERO: Self = Self(<$uint>::ZERO);
330-
331-
/// Multiplicative identity.
332-
pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE);
333-
334-
/// Create a [`
335-
#[doc = stringify!($fe)]
336-
/// `] from a canonical big-endian representation.
337-
pub fn from_bytes(repr: &$bytes) -> $crate::subtle::CtOption<Self> {
338-
Self::from_uint($decode_uint(repr))
339-
}
340-
341-
/// Decode [`
342-
#[doc = stringify!($fe)]
343-
/// `] from a big endian byte slice.
344-
pub fn from_slice(slice: &[u8]) -> Option<Self> {
345-
let array = <$bytes>::try_from(slice).ok()?;
346-
Self::from_bytes(&array).into()
347-
}
348-
349-
/// Decode [`
350-
#[doc = stringify!($fe)]
351-
/// `]
352-
/// from [`
353-
#[doc = stringify!($uint)]
354-
/// `] converting it into Montgomery form:
355-
///
356-
/// ```text
357-
/// w * R^2 * R^-1 mod p = wR mod p
358-
/// ```
359-
pub fn from_uint(uint: $uint) -> $crate::subtle::CtOption<Self> {
360-
use $crate::subtle::ConstantTimeLess as _;
361-
let is_some = uint.ct_lt(&$modulus);
362-
$crate::subtle::CtOption::new(Self::from_uint_unchecked(uint), is_some)
363-
}
364-
365-
/// Parse a [`
366-
#[doc = stringify!($fe)]
367-
/// `] from big endian hex-encoded bytes.
368-
///
369-
/// Does *not* perform a check that the field element does not overflow the order.
370-
///
371-
/// This method is primarily intended for defining internal constants.
372-
#[allow(dead_code)]
373-
pub(crate) const fn from_hex(hex: &str) -> Self {
374-
Self::from_uint_unchecked(<$uint>::from_be_hex(hex))
375-
}
376-
377-
/// Convert a `u64` into a [`
378-
#[doc = stringify!($fe)]
379-
/// `].
380-
pub const fn from_u64(w: u64) -> Self {
381-
Self::from_uint_unchecked(<$uint>::from_u64(w))
382-
}
383-
384-
/// Returns the big-endian encoding of this [`
385-
#[doc = stringify!($fe)]
386-
/// `].
387-
pub fn to_bytes(self) -> $bytes {
388-
$encode_uint(&self.to_canonical())
389-
}
390-
391-
/// Determine if this [`
392-
#[doc = stringify!($fe)]
393-
/// `] is odd in the SEC1 sense: `self mod 2 == 1`.
394-
///
395-
/// # Returns
396-
///
397-
/// If odd, return `Choice(1)`. Otherwise, return `Choice(0)`.
398-
pub fn is_odd(&self) -> $crate::subtle::Choice {
399-
use $crate::bigint::Integer;
400-
self.to_canonical().is_odd()
401-
}
402-
403-
/// Determine if this [`
404-
#[doc = stringify!($fe)]
405-
/// `] is even in the SEC1 sense: `self mod 2 == 0`.
406-
///
407-
/// # Returns
408-
///
409-
/// If even, return `Choice(1)`. Otherwise, return `Choice(0)`.
410-
pub fn is_even(&self) -> $crate::subtle::Choice {
411-
!self.is_odd()
412-
}
413-
414-
/// Determine if this [`
415-
#[doc = stringify!($fe)]
416-
/// `] is zero.
417-
///
418-
/// # Returns
419-
///
420-
/// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`.
421-
pub fn is_zero(&self) -> $crate::subtle::Choice {
422-
self.ct_eq(&Self::ZERO)
423-
}
424-
425-
/// Returns `self^exp`, where `exp` is a little-endian integer exponent.
426-
///
427-
/// **This operation is variable time with respect to the exponent.**
428-
///
429-
/// If the exponent is fixed, this operation is constant time.
430-
pub const fn pow_vartime(&self, exp: &[u64]) -> Self {
431-
let mut res = Self::ONE;
432-
let mut i = exp.len();
433-
434-
while i > 0 {
435-
i -= 1;
436-
437-
let mut j = 64;
438-
while j > 0 {
439-
j -= 1;
440-
res = res.square();
441-
442-
if ((exp[i] >> j) & 1) == 1 {
443-
res = res.multiply(self);
444-
}
445-
}
446-
}
447-
448-
res
449-
}
450-
451-
/// Right shifts the [`
452-
#[doc = stringify!($fe)]
453-
/// `].
454-
pub const fn shr(&self, shift: u32) -> Self {
455-
Self(self.0.wrapping_shr(shift))
456-
}
457-
458-
/// Right shifts the [`
459-
#[doc = stringify!($fe)]
460-
/// `].
461-
///
462-
/// Note: not constant-time with respect to the `shift` parameter.
463-
pub const fn shr_vartime(&self, shift: u32) -> Self {
464-
Self(self.0.wrapping_shr_vartime(shift))
465-
}
466-
}
467-
468-
impl $crate::ff::Field for $fe {
469-
const ZERO: Self = Self::ZERO;
470-
const ONE: Self = Self::ONE;
471-
472-
fn try_from_rng<R: $crate::rand_core::TryRngCore + ?Sized>(
473-
rng: &mut R,
474-
) -> ::core::result::Result<Self, R::Error> {
475-
let mut bytes = <$bytes>::default();
476-
477-
loop {
478-
rng.try_fill_bytes(&mut bytes)?;
479-
if let Some(fe) = Self::from_bytes(&bytes).into() {
480-
return Ok(fe);
481-
}
482-
}
483-
}
484-
485-
fn is_zero(&self) -> Choice {
486-
Self::ZERO.ct_eq(self)
487-
}
488-
489-
#[must_use]
490-
fn square(&self) -> Self {
491-
self.square()
492-
}
493-
494-
#[must_use]
495-
fn double(&self) -> Self {
496-
self.double()
497-
}
498-
499-
fn invert(&self) -> CtOption<Self> {
500-
self.invert()
501-
}
502-
503-
fn sqrt(&self) -> CtOption<Self> {
504-
self.sqrt()
505-
}
506-
507-
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
508-
$crate::ff::helpers::sqrt_ratio_generic(num, div)
509-
}
510-
}
511-
};
512-
}
513-
514499
/// Emit a `core::ops` trait wrapper for an inherent method which is expected to be provided by a
515500
/// backend arithmetic implementation (e.g. `fiat-crypto`)
516501
#[macro_export]

0 commit comments

Comments
 (0)