Adding unsigned and signed integers
Today I had a really simple problem: add a signed and unsigned number of the same size. No solution I (and rkruppe on #rust) found were 100% satisfactory:
unsigned.wrapping_add(signed as usize): Doesn't panic whenunsignedoverflows like normal addition in debug. Eg0usize.wrapping_add(-1isize as usize)won't panic.(unsigned as isize + signed) as usize: Panics in debug if the signed addition overflows, even though that would not have overflown the unsigned integer. Also like the above, it doesn't panic if the unsigned value overflows negatively.if signed < 0 { unsigned -= -signed as usize; } else { unsigned += signed as usize; }: Long code is long. Also, it cannot be used as an expression in the same way the prior two solutions can.
I can of course create a function that does all the necessary checks, but shouldn't something like this be part of the standard library (or even standard operators)?
20 comments · 94% upvoted · other discussions
is an expression. It can be made into a macro if you aren't fond of the size.
Noctune [OP] 2 points · Sep 2015
-isize::min_value()will panic, unfortunately. So this isn't a solution and neither is the third one I wrote above.heinrich5991 3 points · Sep 2015
Try replacing
(-signed) as u*with-(signed as u*), that will remove the overflow check.Noctune [OP] 2 points · Sep 2015
Seems to work, but Rustc warns that unsigned negation will be feature gated in the future.
heinrich5991 3 points · Sep 2015
You can simulate unsigned negation by writing
(!(signed as u*)).wrapping_add(1). LLVM will optimize this to unsigned negation.EDIT: Checked that LLVM actually optimizes this (removed "likely") and changed
wrapped_addtowrapping_add.[deleted] 3 points · Sep 2015
.wrapping_neg()seems to exist, too