macro_rules! quotient_map_large_iint {
($field:ty, $field_size:ty, $checked_bounds:literal, $unchecked_bounds:literal, [$(($large_signed_int:ty, $large_int:ty)),*] ) => { ... };
}Expand description
For large signed integer types, a simple method which is usually good enough is to simply check the sign and use this to pass to the equivalent unsigned method.
This will often not be the fastest implementation but should be good enough for most cases.
This macro accepts 4 inputs.
- The name of the prime field
P. - The smallest natural integer type large enough to contain the field characteristic.
- A string giving the range for which from_canonical_checked produces the correct result.
- A string giving the range for which from_canonical_unchecked produces the correct result.
- A list of pairs of large sign and unsigned integer types to auto implement
QuotientMap<LargeSignInt>.
For a concrete example, quotient_map_large_iint!(Mersenne31, i32, "[-2^30, 2^30]", "[1 - 2^31, 2^31 - 1]", [(i128, u128)]) would produce the following code:
ⓘ
impl QuotientMap<i128> for Mersenne31 {
/// Convert a given `i128` integer into an element of the `Mersenne31` field.
///
/// This checks the sign and then makes use of the equivalent method for unsigned integers.
/// This should be avoided in performance critical locations.
#[inline]
fn from_int(int: i128) -> Mersenne31 {
if int >= 0 {
Self::from_int(int as u128)
} else {
-Self::from_int(-int as u128)
}
}
/// Convert a given `i128` integer into an element of the `Mersenne31` field.
///
/// Returns `None` if the input does not lie in the range: `[-2^30, 2^30]`.
#[inline]
fn from_canonical_checked(int: i128) -> Option<Mersenne31> {
// We just check that int fits into an i32 now and then use the i32 method.
let int_small = TryInto::<i32>::try_into(int);
if int_small.is_ok() {
Self::from_canonical_checked(int_small.unwrap())
} else {
None
}
}
/// Convert a given `i128` integer into an element of the `Mersenne31` field.
///
/// # Safety
/// The input must lie in the range:", `[1 - 2^31, 2^31 - 1]`.
#[inline]
unsafe fn from_canonical_unchecked(int: i128) -> Mersenne31 {
unsafe {
Self::from_canonical_unchecked(int as i32)
}
}
}