-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve imulc
Performance
#21
Comments
As expected, Since there is no can trivially be replaced with
The redundant multiplication is tiny next to a division. |
tl;dr: nlordell's idea of verifying the sign afterwards should work and his concern of wrapping problems is unfounded. There is a tiny caveat with The advantage of two's complement is that the values wrap around correctly, and are congruent modulo 2bits to their binary representation reinterpreted as an unsigned integer. This means that we can do modulo arithmetic on congruence classes and apply it to signed and unsigned integers simultaneously.
Let's define functions that interpret the congruence classes as regular integers. signed(x) interprets x as a signed integer while unsigned(x) interprets x as an unsigned integer. So for example signed(-1̅0256) = -10 while unsigned(-1̅0256) = 2256 - 10. overflow should return positive iff signed(a̅256) * signed(b̅256) ≠ signed(c̅256). Equivalently, overflow should return false iff signed(
That makes sense. If
We wan't to be able to "undo" the absolute value at the end by negating the product if exactly one of the inputs was negative. So the question is whether or not c̅256 ≡ 0̅256 - (0̅256 - a̅256) * b̅256 and c̅256 ≡ (0̅256 - a̅256) * (0̅256 - b̅256) With modulo arithmetic, congruence is preserved with addition, subtraction, and multiplication. Therefor we can rewrite the question more simply: "Does a * b = -(-a * b) and a * b = -a * - b?" This is clearly true. |
This is how llvm does it. This function is called on Aarch64 for i128 mul. https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/int_mulo_impl.inc |
Checked signed integer multiplication (
imulc
andI256::checked_mul
) use division to verify overflows. This is, I think, quite inefficient and unnecessary.This issue captures the work to:
One idea would be to multiply absolutes and then verify the sign afterwards. I'm not sure if this will work for
I256::overflowing_mul
(in that the wrapping produces different results), but it might be worth a try!The text was updated successfully, but these errors were encountered: