Partial-stabilize the basics from bigint_helper_methods#144494
Merged
bors merged 1 commit intorust-lang:masterfrom Aug 30, 2025
Merged
Partial-stabilize the basics from bigint_helper_methods#144494bors merged 1 commit intorust-lang:masterfrom
bigint_helper_methods#144494bors merged 1 commit intorust-lang:masterfrom
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Direct link to p-FCP comment: #144494 (comment)
After libs-api discussion, this is now the following methods:
uN::carrying_add: uN + uN + bool -> (uN, bool)uN::borrowing_sub: uN + uN + bool -> (uN, bool)uN::carrying_mul: uN * uN + uN -> (uN, uN)uN::carrying_mul_add: uN * uN + uN + uN -> (uN, uN)Specifically, these are the ones that are specifically about working with
uNas a "digit" (or "limb") where the output, despite being larger than can fit in a single digit, wants to be phrased in terms of those digits, not in terms of a wider type.(This leaves open the possibility of things like
widening_mul: u32 * u32 -> u64for places where one wants to only think in terms of the numbers, rather than as carries between multiple digits. Though of course discussions about how best to phrase such a thing are best for the tracking issue, not for this PR.)Original PR description:
A conversation on IRLO the other day pushed me to write this up 🙂
This PR proposes a partial stabilization of
bigint_helper_methods(#85532), focusing on a basic set that hopefully can be non-controversial. Specifically:uN::carrying_add: uN + uN + bool -> (uN, bool)uN::widening_mul: uN * uN -> (uN, uN)uN::carrying_mul_add: uN * uN + uN + uN -> (uN, uN)Why these?
carrying_add, which doesn't seem that complicated, actually broke in 1.82 (see Fix chainingcarrying_adds #133674) so we should just offer something fit-for-purpose rather than making people keep up with whatever the secret sauce is today. We also get to do things that users cannot, like have the LLVM version emit operations oni256in the implementation ofu128::carrying_mul_add(https://rust.godbolt.org/z/cjG7eKcxd).iN * iNshould give(uN, iN)) and carries can only happen in one direction (vs questions about whether the carry from-128_u8 + -128_u8should be considered-1).carrying_addis the core full adder primitive for implementing addition.carrying_mul_addis the core primitive for grade school multiplication (see the example in its docs for why both carries are needed).widening_muleven though it's not strictly needed (its implementation is justcarrying_mul_add(a, b, 0, 0)right now) as the simplest way for users to get to cranelift'sumulhi, RISC-V'sMULHU, Arm'sUMULL, etc. (For example, I added an ISLE pattern bytecodealliance/wasmtime@d12e423#diff-2041f67049d5ac3d8f62ea91d3cb45cdb8608d5f5cdab988731ae2addf90ef01 so Cranelift can notice what's happening from the fallback, even if the intrinsics aren't overridden specifically. And on x86 this is one of the simplest possible non-trivial functions https://rust.godbolt.org/z/4oadWKTc1 becauseMULputs the results in exactly the registers that the scalar pair result happens to want.)(I did not const-stabilize them in this PR because the fallbacks are using
#[const_trait]plus there's two new intrinsics involved, so I didn't want to also open those cans of worms here. Given that both intrinsics have fallbacks, and thus don't do anything that can't already be expressed in existing Rust, const-stabilizing these should be straight-forward once the underlying machinery is allowed on stable. But that doesn't need to keep these from being usable at runtime in the mean time.)