Rust: Tracking issue for integer methods for Wrapping

Created on 24 Mar 2016  Â·  17Comments  Â·  Source: rust-lang/rust

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:

  • [x] count_ones
  • [x] count_zeroes
  • [x] leading_zeroes
  • [x] trailing_zeroes
  • [x] rotate_left
  • [x] rotate_right
  • [x] swap_bytes
  • [x] from_be (?)
  • [x] from_le (?)
  • [x] to_be
  • [x] to_le
  • [x] pow (?)

Edit: Others added after https://github.com/rust-lang/rust/issues/32463#issuecomment-376663775

and 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

  • [ ] Decide on correct behavior for wrapping_next_power_of_two
B-unstable C-tracking-issue Libs-Small Libs-Tracked T-libs

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.

All 17 comments

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 Ts 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.

Was this page helpful?
0 / 5 - 0 ratings