4

Assume that the value of test is 1 or 0. Here I can implement the following if statement using bitwise operators as below.

if (test)
    output = a;
else
    output = b;

Using bit wise operators

output = (((test << 31) >> 31) & a) | (((test << 31) >> 31) & b);

Now I want to implement the following if statements using bitwise operators.

if (test1)
    output = a;
else if (test2)
    output = b;
else if (test3)
    output = c;
else
    output = d;

The values of test1, test2, test3 are either 0 or 1.

Any suggestions to do that ?

11
  • Are you allowed to use not !? Commented Jun 2, 2013 at 1:32
  • + is not a bitwise operator. Commented Jun 2, 2013 at 1:35
  • Also, there are no loops here. Commented Jun 2, 2013 at 1:36
  • 1
    What's type of test? Commented Jun 2, 2013 at 1:40
  • 1
    @noufal: Thanks, but you still haven't addressed the very first comment, above. What is the motivation for this requirement? Is it branch-avoidance, an intellectual exercise, homework, or something else? Commented Jun 2, 2013 at 1:56

2 Answers 2

4

I assume you meant this for your original if statement.

output = (((test << 31) >> 31) & a) | (((!test << 31) >> 31) & b);

Not in front of test so that this isn't a+b when test is 1 and 0 when test is 0 and I replaced + with | because each case should be 0 except for the one you want.

To do the cascaded if else if else statements you could rewrite the expression so that they are dependent on the previous test.

if (test1)
    output = a
if (!test1 & test2)
    output = b
if (!test1 & !test2 & test3)
    output = c
if (!test1 & !test2 & !test3)
    output = d

This leads to an expression like this for all the if else ifs.

output = (((test1 << 31) >> 31) & a)
         | ((((!test1 & test2) << 31) >> 31) & b)
         | ((((!test1 & !test2 & test3) << 31) >> 31) & c)
         | ((((!test1 & !test2 & !test3) << 31) >> 31) & d)
Sign up to request clarification or add additional context in comments.

6 Comments

Why the wasteful and unportable ((test << 31) >> 31) instead of (test & 1) ?
@LeeDanielCrocker Its very unportable but its supposed to make a true value 0xFFFFFFFF and a false value 0x00000000. This happens because test1 is assumed to be signed and 32 bits. Shifting the 1 all the way to the highest position and then shifting it back fills it with ones because the computer is doing a signed shift. This is not equivalent to (test & 1)
Then that's just (-(test & 1)). Big shifts just seem wasteful.
@LeeDanielCrocker That would turn 1 into 0xFFFFFFFE and 0 into 0xFFFFFFFF. These aren't the same. Also the test with & 1 is pointless since test is assumed to be 0 or 1 according to the question
Um, no, look again. (test & 1) evaluates to either 0 or 1, then the negative sign makes it 0 or -1, which is 0xFFFFFFFF. If we already know that it's 0 or 1, so much the better, then we just want -test.
|
0

Does it have be bitwise operators? What about:

output = (    test1) * a +
         (1 - test1) * ((    test2) * b +
                        (1 - test2) * ((    test3) * c +
                                       (1 - test3) * d));

Another possibility, only using bit-wise operators, is this:

switch ((test1 << 2) | (test2 << 1) | test3) {
    case 0: output = d; break;
    case 1: output = c; break;
    case 2:
    case 3: output = b; break;
    case 4:
    case 5:
    case 6:
    case 7: output = a; break;
}

If you're lucky (and if it speeds things up), the compiler will implement the switch using a jump table.

You really have to question, though, whether these tricksy solutions offer enough of a speed bump (if they do) to justify the additional complexity. I assume you're trying to avoid branching.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.