quotient_map_small_int

Macro quotient_map_small_int 

Source
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), SmallInt can be anything except for the largest primitive integer type u128/i128

This macro accepts 3 inputs.

  • The name of the prime field P
  • The larger integer type Int which 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.