4 ms·
I don’t mind a few “as usize” casts because usually you can cast once and be done with it. But the cast that kills me is this one: How do you add an unsigned a
by josephg 4y ago
I don’t mind a few “as usize” casts because usually you can cast once and be done with it. But the cast that kills me is this one:
How do you add an unsigned and a signed number together in rust, in a way which is fast (no branches in release mode), correct and which panics in debug mode in the right places (if the addition over- or under-flows)? Nearly a year in to rust and I’m still stumped!
- steveklabnik 4y agohttps://rust.godbolt.org/z/e377o5148 https://rust.godbolt.org/z/e377o5148 is the first thing I thought of. You didn't specify sizes, or if you wanted the result to be signed or unsigned, but "assume two's compliment wrapping in release and panic in debug on over/underflow" is the default behavior of +.
- mjw1007 4y agoThat fails the "panics in debug mode in the right places" requirement: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f242c49005c7386dfaae45d01b56dc95 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- steveklabnik 4y agoOh duh, yeah, my bad. I was tweaking stuff around and lost that property. And seems like TryInto doesn't compile away entirely. Boo. You can write your own debug_assert! though: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ac1becf96a6f956a5bf8bf7551f2c253 https://play.rust-lang.org/?version=stable&mode=debug&editio... not as nice, but it does work. If you were doing this a lot you could macro it up, impl as a method on all the various types you want... a pain, but it is possible.
- josephg 4y agoAh. I should have specified - I want to do this with usize / isize so the trick of using a larger integer type wouldn’t work reliably. I can use wrapping_add, but how do you detect overflow in a debug_assert statement?
- steveklabnik 4y agoSo, I'm kind of surprised, but using u128 seems to do the trick: https://rust.godbolt.org/z/G63d7qoTW https://rust.godbolt.org/z/G63d7qoTW I was kinda worried the release case would end up being worse, but it seems okay to me. Does that work for you? > how do you detect overflow in a debug_assert statement? compare to usize::MAX cast up to the larger number.
- josephg 4y agoHuh! I was expecting adding u128 integers to be slower because of the cast; but it looks like llvm is (correctly) realising the upcast + downcast has no effect and replacing it with a single u64 add in release mode. It also will happily vectorize and all the rest: https://rust.godbolt.org/z/hn888ezj4 https://rust.godbolt.org/z/hn888ezj4 I want to do some additional testing to check if it also optimizes correctly for wasm and in 32 bit contexts, but generally I'm shocked that works so well. Thanks!
- steveklabnik 4y agoRight? LLVM feels like magic sometimes. You're welcome! And yeah it's certainly a bit non-obvious.