Incrementing 'masked' bitsets

C++CBit ManipulationIntrinsics

C++ Problem Overview


I'm currently in the process of writing a tree enumerator where I've come across the following problem:

I'm looking at masked bitsets, i.e. bitsets where the set bits are a subset of a mask, i.e. 0000101 with mask 1010101. What I want to accomplish is increment the bitset, but only with respect to the masked bits. In this example, the result would be 0010000. To make it a bit clearer, extract only the masked bits, i.e. 0011, increment them to 0100 and distribute them to the mask bits again, giving 0010000.

Does anybody see an efficient way to do this, short of implementing the operation by hand using a combination of bitscans and prefix masks?

C++ Solutions


Solution 1 - C++

Just fill the non mask bits with ones so that they propagate carry:

// increments x on bits belonging to mask
x = ((x | ~mask) + 1) & mask;

Solution 2 - C++

While not intuitive compared to the accepted answer, this works in only 3 steps:

x = -(x ^ mask) & mask;

This can be verified as suggested by zch:

  -(x ^ mask)
= ~(x ^ mask) + 1  // assuming 2's complement
= (x ^ ~mask) + 1
= (x | ~mask) + 1  // since x and ~mask have disjoint set bits

Then it becomes equivalent to the accepted answer.

Solution 3 - C++

If the order of iteration is not that important, and a decrement operation will satisfy your needs, it is possible to use only two operations:

Let's start with

x = mask

and get previous value with

x = (x - 1) & mask

x - 1 part changes the last non-zero bit to zero, and sets all less significant bits to 1's. Then & mask part leaves only mask bits among them.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTobias RibizelView Question on Stackoverflow
Solution 1 - C++zchView Answer on Stackoverflow
Solution 2 - C++ngleeView Answer on Stackoverflow
Solution 3 - C++DAleView Answer on Stackoverflow