macro_rules! quotient_map_small_int {
($field:ty, $field_size:ty, [$($small_int:ty),*] ) => { ... };
($field:ty, $field_size:ty, $field_param:ty, [$($small_int:ty),*] ) => { ... };
}Expand description
If the integer type is smaller than the field order all possible inputs are canonical.
In such a case we can easily implement QuotientMap<SmallInt> as all three methods will coincide.
The range of acceptable integer types depends on the size of the field:
- For 31 bit fields,
SmallInt = u8, u16, i8, i16. - For 64 bit fields,
SmallInt = u8, u16, u32, i8, i16, i32. - For large fields (E.g.
Bn254),SmallIntcan be anything except for the largest primitive integer typeu128/i128
This macro accepts 3 inputs.
- The name of the prime field
P - The larger integer type
Intwhich inputs should be cast to. - A list of smaller integer types to auto implement
QuotientMap<SmallInt>.
Then from_int, from_canonical_checked, from_canonical_unchecked are all
implemented by casting the input to an Int and using the from_canonical_unchecked
method from QuotientMap<Int>.
For a concrete example, quotient_map_small_int!(Mersenne31, u32, [u8]) produces the following code:
ⓘ
impl QuotientMap<u8> for Mersenne31 {
/// Convert a given `u8` integer into an element of the `Mersenne31` field.
///
/// Due to the integer type, the input value is always canonical.
#[inline]
fn from_int(int: u8) -> Mersenne31 {
// Check at compile time.
const { assert!(size_of::<u8>() < size_of::<u32>()); }
unsafe {
Self::from_canonical_unchecked(int as u32)
}
}
/// Convert a given `u8` integer into an element of the `Mersenne31` field.
///
/// Due to the integer type, the input value is always canonical.
#[inline]
fn from_canonical_checked(int: u8) -> Option<Mersenne31> {
// Check at compile time.
const { assert!(size_of::<u8>() < size_of::<u32>()); }
Some(unsafe {
Self::from_canonical_unchecked(int as u32)
})
}
/// Convert a given `u8` integer into an element of the `Mersenne31` field.
///
/// Due to the integer type, the input value is always canonical.
#[inline]
unsafe fn from_canonical_unchecked(int: u8) -> Mersenne31 {
// Check at compile time.
const { assert!(size_of::<u8>() < size_of::<u32>()); }
unsafe {
Self::from_canonical_unchecked(int as u32)
}
}
}Fields will often use this method twice. Once for unsigned ints and once for signed ints.
We need two slightly different versions for this macro as MontyField31 uses generic parameters.