Module compiler_builtins::int::specialized_div_rem
source · Expand description
This specialized_div_rem module is originally from version 1.0.0 of the
specialized-div-rem crate. Note that for loops with ranges are not used in this
module, since unoptimized compilation may generate references to memcpy.
The purpose of these macros is to easily change the both the division algorithm used for a given integer size and the half division used by that algorithm. The way functions call each other is also constructed such that linkers will find the chain of software and hardware divisions needed for every size of signed and unsigned division. For example, most target compilations do the following:
- Many 128 bit division functions like
u128::wrapping_divusestd::intrinsics::unchecked_div, which gets replaced by__udivti3because there is not a 128 bit by 128 bit hardware division function in most architectures.__udivti3usesu128_div_rem(this extra level of function calls exists because__umodti3and__udivmodti4also exist, andspecialized_div_remsupplies just one function to calculate both the quotient and remainder. If configuration flags enable it,impl_trifecta!definesu128_div_remto use the trifecta algorithm, which requires the half sized divisionu64_by_u64_div_rem. If the architecture supplies a 64 bit hardware division instruction,u64_by_u64_div_remwill be reduced to those instructions. Note that we do not specify the half size division directly to be__udivdi3, because hardware division would never be introduced. - If the architecture does not supply a 64 bit hardware division instruction, u64
divisions will use functions such as
__udivdi3. This will callu64_div_remwhich is defined byimpl_delegate!. The half division for this algorithm isu32_by_u32_div_remwhich in turn becomes hardware division instructions or more software division algorithms. - If the architecture does not supply a 32 bit hardware instruction, linkers will
look for
__udivsi3.impl_binary_long!is used, but this algorithm uses no half division, so the chain of calls ends here.
On some architectures like x86_64, an asymmetrically sized division is supplied, in
which 128 bit numbers can be divided by 64 bit numbers. impl_asymmetric! is used to
extend the 128 by 64 bit division to a full 128 by 128 bit division.
Modules
Constants
- USE_LZ 🔒
Functions
- Divides
duobydivand returns a tuple of the quotient and the remainder.checked_divandchecked_remare used to avoid bringing in panic function dependencies. - Computes the quotient and remainder of
duodivided bydivand returns them as a tuple. - Finds the shift left that the divisor
divwould need to be normalized for a binary long division step with the dividendduo. NOTE: This function assumes that these edge cases have been handled before reaching it:if div == 0 { panic!("attempt to divide by zero") } if duo < div { return (0, duo) } - Divides
duobydivand returns a tuple of the quotient and the remainder.checked_divandchecked_remare used to avoid bringing in panic function dependencies. - Computes the quotient and remainder of
duodivided bydivand returns them as a tuple. - Finds the shift left that the divisor
divwould need to be normalized for a binary long division step with the dividendduo. NOTE: This function assumes that these edge cases have been handled before reaching it:if div == 0 { panic!("attempt to divide by zero") } if duo < div { return (0, duo) } - Divides
duobydivand returns a tuple of the quotient and the remainder. - Computes the quotient and remainder of
duodivided bydivand returns them as a tuple. - The behavior of all divisions by zero is controlled by this function. This function should be impossible to reach by Rust users, unless
compiler-builtinspublic division functions orcore/std::unchecked_div/remare directly used without a zero check in front.