Search code examples
cbit-manipulationbitwise-operators

a bitwise expression that returns 1 when mask is all zeros and x when mask is all ones


Let's say we have a mask variable that can either be 0 (all zoers) or -1 (all ones).

I have another variable x which is let's say 42.

What (possibly) is the bitwise expression that results in:

  • 1 when mask == 0
  • x when mask == -1

what I'm trying to do is explore ways to eliminate the following if statement

unsigned x = 3;
unsigned some_number = 42;

// ~~~

if (some_number % x == 0)
{
    some_number /= x;
}

Regarding the type of variables in the particular problem that I'm working on (look below), all of the numbers are unsigned integers for example unsigned.


EDIT 2 (MISTAKE): I made a mistake and forgot that mask is either 0 (all zeros) or, -1 (all ones) which I previously said 1 (only whose least significant bit is one). Please accept my apologies as I wasted your precious time.


EDIT 1:

Overall the point is not to use if-else constructs (including the conditional operator (?:)). Instead I'm looking for bit manipulations similar to those which is used in branchless practices. This question isn't whether it is going to be more performant or not in this case, or whether the answer could be considered a good practice or not. It's just to explore the world of bit manipulation.


Here is my try

// Check whether some_number is divisible by x
unsigned mask = ((some_number % x) - 1) >> 31;
unsigned deonm = // ??
some_number =/ denom

I'm using this to answer project Euler's third question and here's the code

size_t largest_prime_factor(size_t number)
{
    if (number < 2) return 0;
    if (number == 2) return 2;
    while ((number & 1) == 0)
    {
        number >>= 1;
    }
    size_t lpf = 2;
    size_t i = 3;
    size_t max_iter = sqrt(number);
    while (i < max_iter)
    {
        size_t mask = ((number % i) - 1) >> 31;
        lpf = (i & mask) | (lpf & ~mask);
        number /= X; // mask = 0 => X=1; mask = 1 => X=i
        i += 2;
    }
    return lpf;
}

NOTE: Please, if possible, suggest a better title.


Solution

  • I'm going to assume the mask (which I'll call m), x, and the result (which I'll call r) are unsigned integer types of the same size. I shall call that type TYPE.


    For most of the bits, it's easy: ri = xi & mi

    The least significant bit (r0) is different, though. The following shows the desired value for r0 based on the values of m0 and x0:

    r0 m0 = 0 m0 = 1
    x0 = 0 1 0
    x0 = 1 1 1

    So we get r0 = ~m0 | x0

    Now, we just need to combine them.

    We want to apply the first rule to all the bits but the last. This can be done by using a mask that lets through all bits but the last (... & ( ~(TYPE)1 )).

    We want to apply the second rule for just the last bit. This can be done by using a mask that lets through only the last bit (... & 1).

    All together:

    r = ( x & m & ( ~(TYPE)1 ) ) | ( ( ~m | x ) & 1 );
    

    And now we have a solution with just bit operations (and a cast which can maybe be avoided by using the correct numeric literal suffix).