u32
and other primitive integer types implement a number of bit-manipulation methods like rotate_left
, but Wrapping<_>
does not. At the moment this can be worked around with code like Wrapping(x.0.rotate_left(n))
instead of x.rotate_left(n)
.
It would be nice to implement:
count_ones
count_zeroes
leading_zeroes
trailing_zeroes
rotate_left
rotate_right
swap_bytes
from_be
(?)from_le
(?)to_be
to_le
pow
(?)Edit: Others added after https://github.com/rust-lang/rust/issues/32463#issuecomment-376663775
is_power_of_two
(?)next_power_of_two
(?)min_value
(?)max_value
(?)from_str_radix
(?)reverse_bits
abs
https://github.com/rust-lang/rust/pull/49393signum
https://github.com/rust-lang/rust/pull/49393is_positive
https://github.com/rust-lang/rust/pull/49393is_negative
https://github.com/rust-lang/rust/pull/49393and maybe other methods, for:
Wrapping<u8>
Wrapping<u16>
Wrapping<u32>
Wrapping<u64>
Wrapping<usize>
Wrapping<i8>
Wrapping<i16>
Wrapping<i32>
Wrapping<i64>
Wrapping<isize>
Edit: From https://github.com/rust-lang/rust/pull/50465
wrapping_next_power_of_two
I want to take this. Would you review my PR?
I can have a look, but I’m not one of the reviewers who can approve PRs for merging into this repository.
sure that helps. thanks.
I would be open to considering a PR that adds these methods.
This is a tracking issue, so, it shouldn't be closed.
Also, a quick search yields that we are missing:
min_value
and max_value
(mostly useful for macros)from_str_radix
(changes behaviour)reverse_bits
(added after initial PR)abs
(missing; should call wrapping_abs
)signum
(presumably missed, as this is specific to signed integers)is_positive
and is_negative
(same as above)is it worth changing the top post into a checklist to track completion? since this is a tracking issue.
I guess now mod_euc
and div_euc
need to go on the list too? https://github.com/rust-lang/rust/pull/49389
Bit-shifting would be useful to have here too.
I would like to propose that all of the ones that have been implemented already be stabilized, and that we separate the ones that haven't been implemented into a separate feature. Otherwise stabilization is likely to lose many races with adding new methods to integer types that then should be added to Wrapping
.
Any movement on the semantics of next_power_of_two
for wrapping types? There are comments for this scattered around other threads, but it would be good if someone on the lib team could summarize the current thinking.
I strongly believe that wrapping_next_power_of_two
should be 0 on overflow. If we do not treat integer types as a truncation of the number line, and instead treat them as proper cyclic monoids, then 0 is a power of two.
Adding the other argument: if you see integers as infinite, rather than finite, zero is never a power of two; therefore, the wrapping version should wrap to one. It's been argued that there is a way to make both versions as performant as one another (and hence the argument is just over preference of the result) but I don't actually know the code for this case. (Maybe @nagisa can comment on that.)
I consider Wrapping<T>
types to be (mod 2^b)
where b
is the number of bits in T
. With that wrapping_next_power_of_two
should be 0 after an overflow (2^(n*b) = 0 (mod 2^b)
for all integer n
).
As for implementation, since the of next_power_of_two
is mostly bit-fiddling to achieve T::max_value().wrapping_next_power_of_two() = 1
one would have to replace semantic multiplication by 2 with the previous power of 2 with a rotation left by a single position – both equally cheap operations.
Maybe this is too much, but given that we're implementing the same methods for a bunch of different T
s for Wrapping<T>
, would it be worthwhile extracting the relevant methods out into a trait? In my case for example, I'd like to be generic over "any number type that can wrap", and unless I'm missing something, I don't think that's currently doable (except by adding a trait and impls myself).
Pre-1.0 Rust had a Num
trait that was explicitly removed in favour of inherent methods, and so far that's what we've stuck with. If you're looking for those traits, the num
crates have your back.
I was specifically thinking of a Wrapping
trait for this set of methods, not a general Num
trait, though I see the similarities. It was mostly an idle observation though, and I will leave it to those much more familiar with the innards to decide what makes sense :)
leading_ones
and trailing_ones
were stabilized for the regular integer types, but don't even exist for Wrapping
(whereas leading_zeros
and trailing_zeros
do). They should probably be on the list too.
Most helpful comment
I would like to propose that all of the ones that have been implemented already be stabilized, and that we separate the ones that haven't been implemented into a separate feature. Otherwise stabilization is likely to lose many races with adding new methods to integer types that then should be added to
Wrapping
.