Tracking issue for integer methods for Wrapping

fa51393
Opened by Simon Sapin at 2025-02-24 22:39:35

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

  • [ ] is_power_of_two (?)
  • [ ] next_power_of_two (?)
  • [ ] min_value (?)
  • [ ] max_value (?)
  • [ ] from_str_radix (?)
  • [x] reverse_bits
  • [ ] abs https://github.com/rust-lang/rust/pull/49393
  • [ ] signum https://github.com/rust-lang/rust/pull/49393
  • [ ] is_positive https://github.com/rust-lang/rust/pull/49393
  • [ ] is_negative https://github.com/rust-lang/rust/pull/49393

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

    • [x] is_power_of_two (?)
    • [x] next_power_of_two (?)
    • [x] min_value (?)
    • [x] max_value (?)
    • [x] from_str_radix (?)
    • [x] reverse_bits
    • [x] abs ~~https://github.com/rust-lang/rust/pull/49393~~ https://github.com/rust-lang/rust/pull/50465
    • [x] signum ~~https://github.com/rust-lang/rust/pull/49393~~ https://github.com/rust-lang/rust/pull/50465
    • [x] is_positive ~~https://github.com/rust-lang/rust/pull/49393~~ https://github.com/rust-lang/rust/pull/50465
    • [x] is_negative ~~https://github.com/rust-lang/rust/pull/49393~~ https://github.com/rust-lang/rust/pull/50465

    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

    Dylan DPC at 2019-12-21 06:13:07

  2. I want to take this. Would you review my PR?

    Srinivas Reddy Thatiparthy (తాటిపర్తి శ్రీనివాస్ రెడ్డి) at 2016-03-24 12:10:32

  3. I can have a look, but I’m not one of the reviewers who can approve PRs for merging into this repository.

    Simon Sapin at 2016-03-25 06:41:46

  4. sure that helps. thanks.

    Srinivas Reddy Thatiparthy (తాటిపర్తి శ్రీనివాస్ రెడ్డి) at 2016-03-25 08:45:05

  5. I would be open to considering a PR that adds these methods.

    David Tolnay at 2017-11-17 17:37:13

  6. 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)

    Clar Fon at 2018-03-26 20:29:38

  7. is it worth changing the top post into a checklist to track completion? since this is a tracking issue.

    Joe ST at 2018-03-27 20:27:36

  8. I guess now mod_euc and div_euc need to go on the list too? https://github.com/rust-lang/rust/pull/49389

    scottmcm at 2018-04-18 01:56:28

  9. Bit-shifting would be useful to have here too.

    varkor at 2018-05-21 23:31:42

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

    Brian Smith at 2018-12-01 14:14:45

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

    bstrie at 2019-05-17 19:32:19

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

    Clar Fon at 2019-05-17 19:47:20

  13. 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.)

    Clar Fon at 2019-05-17 19:54:25

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

    Simonas Kazlauskas at 2019-06-01 17:52:36

  15. 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).

    Jon Gjengset at 2020-04-03 22:21:59

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

    Clar Fon at 2020-04-05 23:22:56

  17. 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 :)

    Jon Gjengset at 2020-04-06 05:01:27

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

    Jonas Platte at 2020-06-30 16:31:21

  19. There is a further argument for wrapping_next_power_of_two to be zero on overflow. One might use

    m.wrapping_next_power_of_two().wrapping_sub(1)
    

    to obtain the bitmask of all numbers in 0..m.

    Finn at 2020-11-24 15:09:46

  20. ... to be zero on overflow

    Note that next_power_of_two is already stable as wrapping to 0 in release mode, so I think it would be very surprising for wrapping_next_power_of_two to do anything different. (Regardless of which answer is actually better.)

    ... to obtain the bitmask of ...

    If people want that, I would encourage them to propose it as a separate method. It's nicer than next_power_of_two since it has no overflow hazards, so doesn't need the full checked/wrapping/saturating set.

    Strawman for a bikeshed: fill_lower_bits.

    scottmcm at 2020-11-24 22:23:48

  21. Is there still debate around the behavior of wrapping_next_power_of_two? I think that next_power_of_two evaluates to 0 (in release mode) on overflow pretty much requires that wrapping_next_power_of_two does the same; it'd be insanely surprising to behave differently.

    If there is a debate around this, how can I get involved to push for stabilization?

    Michael Bradshaw at 2021-03-17 13:48:40

  22. Seconding @briansmith 's comment from soon 5 years ago, is there anything blocking stabilization of the basic and uncontroversial methods like rotate_left|right, count_zeroes|ones, etc.?

    It doesn't seem to me that requiring the nightly compiler is justified for trivial 1-line methods that have been around for many years now.

    Given the lack of discussion here, can one directly send a PR to stabilize some methods?

    Guillaume E at 2023-07-21 11:38:45

  23. How can this be driven forward? Right now Wrapping is less useful than it should be.

    Given the lack of discussion here, can one directly send a PR to stabilize some methods?

    I hope so!

    Elias Gabriel Amaral da Silva at 2024-05-27 07:00:08

  24. Would it make sense to make this also include the recently-stabilised cast_unsigned and cast_signed (tracking issue #125882)?

    Gabriel Bjørnager Jensen at 2025-02-24 22:39:35