Uh oh!
There was an error while loading. Please reload this page.
core: Fix overflow in int::mod_euc when self < 0 && rhs == MIN - #50185
Conversation
rust-highfive
commented
Apr 23, 2018
r? @Kimundi (rust_highfive has picked a reviewer for you, use r? to override) |
| let r = self % rhs; | ||
| if r < 0 { | ||
| r + rhs.abs() | ||
| if rhs.is_negative() { |
There was a problem hiding this comment.
This line and the previous might as well be consistent (whichever of < 0 or is_negative you prefer).
varkor
left a comment
There was a problem hiding this comment.
This was my fault for not paying close enough attention during review! Thanks for catching it!
kennytm
commented
Apr 24, 2018
@bors r+ rollup |
bors
commented
Apr 24, 2018
📌 Commit 104c64d has been approved by |
core: Fix overflow in `int::mod_euc` when `self < 0 && rhs == MIN` This commit removes usage of `abs`, which overflows when `self == MIN`.
Rollup of 11 pull requests Successful merges: - #49461 (std: Child::kill() returns error if process has already exited) - #49727 (Add Cell::update) - #49812 (Fix revision support for UI tests.) - #49829 (Add doc links to `std::os` extension traits) - #49906 (Stabilize `std::hint::unreachable_unchecked`.) - #49970 (Deprecate Read::chars and char::decode_utf8) - #49985 (don't see issue #0) - #50118 (fix search bar bug) - #50139 (encourage descriptive issue titles) - #50174 (Use FxHashMap in syntax_pos::symbol::Interner::intern.) - #50185 (core: Fix overflow in `int::mod_euc` when `self < 0 && rhs == MIN`) Failed merges:
bors
commented
Apr 24, 2018
☔ The latest upstream changes (presumably #50191) made this pull request unmergeable. Please resolve the merge conflicts. |
Boscop
commented
May 3, 2018
I'd prefer pubfnmod_euc(self,rhs:Self) -> Self{let r = self % rhs;if r < 0{if rhs < 0{
r - rhs
}else{
r + rhs
}}else{
r
}}Something like this: pubfnmod_euc(self,rhs:Self) -> Self{let r = self % rhs;let r_pos = [r + rhs, r - rhs][(rhs < 0)asusize];[r, r_pos][(r < 0)asusize)]}The compiler should be able to remove the array bounds checks, right? |
varkor
commented
May 3, 2018
@Boscop: I'm curious to know how differently this performs — have you written a benchmark to see? (Also, maybe it would be better to continue this on the tracking issue where it's more discoverable!) |
Boscop
commented
May 4, 2018
@varkor Is this the correct way to write a benchmark? #[cfg(test)]mod tests {use test::{Bencher, black_box};pubfnmod_euc_branching(slf:i64,rhs:i64) -> i64{let r = slf % rhs;if r < 0{if rhs < 0{
r - rhs
}else{
r + rhs
}}else{
r
}}pubfnmod_euc_branchless(slf:i64,rhs:i64) -> i64{let r = slf % rhs;let r_pos = [r + rhs, r - rhs][(rhs < 0)asusize];[r, r_pos][(r < 0)asusize]}pubfnmod_euc_branchless_u(slf:i64,rhs:i64) -> i64{let r = slf % rhs;unsafe{let r_pos = *[r + rhs, r - rhs].get_unchecked((rhs < 0)asusize);*[r, r_pos].get_unchecked((r < 0)asusize)}}pubfnmod_euc_branchless_2(slf:i64,rhs:i64) -> i64{let r = slf % rhs;let r_pos = r + rhs - 2* rhs *(rhs < 0)asi64;
r + (r_pos - r)*(r < 0)asi64}#[bench]fnbench_mod_euc_branching(b:&mutBencher){
b.iter(|| {for a in -1000..1000{for b in -1000..1000{if b == 0{continue;}black_box(mod_euc_branching(a, b));}}});}#[bench]fnbench_mod_euc_branchless(b:&mutBencher){
b.iter(|| {for a in -1000..1000{for b in -1000..1000{if b == 0{continue;}black_box(mod_euc_branchless(a, b));}}});}#[bench]fnbench_mod_euc_branchless_u(b:&mutBencher){
b.iter(|| {for a in -1000..1000{for b in -1000..1000{if b == 0{continue;}black_box(mod_euc_branchless_u(a, b));}}});}#[bench]fnbench_mod_euc_branchless_2(b:&mutBencher){
b.iter(|| {for a in -1000..1000{for b in -1000..1000{if b == 0{continue;}black_box(mod_euc_branchless_2(a, b));}}});}} |
varkor
commented
May 4, 2018
@Boscop: yeah, that looks fine to me. Thanks for checking it out! |
This commit removes usage of
abs, which overflows whenself == MIN.