Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Is there's a similar to:
if((bitmap & BIT_WATER) && (bitmap & BIT_FIRE)) bitmap &= ~BIT_FIRE
or
if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE

In a single statement using only bitwise operations, removing the need of a comparation (if)?

I totally mean that if two flag, each completly opposite to the other, are set clear one of them.

share|improve this question
    
bitmap &= ~(bit_fire * static_cast<bool>(bitmap & bit_water));, but it uses multiplication... –  Petr Budnik Sep 13 '13 at 1:00

6 Answers 6

up vote 1 down vote accepted

Promoting my comment to an answer. Note, it uses multiplication, but maybe it will be still useful to you (code on ideone.com):

#include <iostream>

int main() 
{
 int long unsigned bitmap_with_water = 0xF300003F;
 int long unsigned bitmap_without_water = 0xF300000F;
 int long unsigned bit_fire = 0x03000000;
 int long unsigned bit_water = 0x00000030;

 bitmap_with_water &= ~(bit_fire * static_cast<bool>(bitmap_with_water & bit_water));
 bitmap_without_water &= ~(bit_fire * static_cast<bool>(bitmap_without_water & bit_water));

 std::cout << (void*)(bitmap_with_water) << "\t" << (void*)(bitmap_without_water) << std::endl;

 return (0);
}

Program output:

0xf000003f  0xf300000f
share|improve this answer

You can avoid the bitmap & BIT_FIRE in the first case, since bitmap &= ~BIT_FIRE; will do nothing to the bitmap if BIT_FIRE is not set.

There is no "set bit X if bit Y is set" in an arbitrary way.

Of course, if you KNOW that, say, BIT_FIRE is one bit higher than BIT_WATER, you could do bitmap &= ~(BIT_WATER << 1), which will clear the "one bit higher than BIT_WATER".

share|improve this answer
    
Sorry, my bad, edited the question with the corrected code, it was supposed to be ~BIT_FIRE not ~BIT_WATER. –  LINK2012 Sep 13 '13 at 0:43
    
@LINK2012: Ok, edited to reflect your know question. The short answer is still "there is no general/simple way to achieve this". –  Mats Petersson Sep 13 '13 at 0:55
    
Could you also do bitmap &= ~((bitmap & BIT_WATER) * (BIT_FIRE/BIT_WATER)) if you know BIT_FIRE > BIT_WATER ? –  Mike Dunlavey Sep 13 '13 at 1:05
    
@MikeDunlavey And if BIT_FIRE/BIT_WATER == 432, for example? –  Petr Budnik Sep 13 '13 at 1:09
2  
@Petr: I suppose, but the OP did call them "bit" :) –  Mike Dunlavey Sep 13 '13 at 1:17

Probably premature optimization, but you could do

bitmap &= ~((bitmap & BIT_WATER) * (BIT_FIRE/BIT_WATER)) & ~((bitmap & BIT_WATER) * (BIT_WATER/BIT_FIRE))

as long as BIT_FIRE and BIT_WATER are single bits (powers of 2). You probably also want bitmap to be unsigned to insure that the compiler can easily optimize this down to a single shift, two bitwise ands, and a complement.

Of course, a good compiler would optimize your original code down to the same 4 instructions with no branch.

edit

Of course, I realized the above is incorrect -- only works if BIT_FIRE > BIT_WATER.

So just stick with the original if and let the compiler optimize it...

share|improve this answer
    
+ OK, you can have my answer :) –  Mike Dunlavey Sep 13 '13 at 1:22

If you need to write a general purpose clear_if_set(int test, int clear, int bitmap) then this answer is useless.

If this is a specialized function and you know the shift distance from fire to water:

int water = bitmap & BIT_WATER;
int shifted = water << WATER_TO_FIRE_LSHIFT; // for example
bitmap &= ~shifted;

One-liner:

bitmap &= ~((bitmap & BIT_WATER) << WATER_TO_FIRE_LSHIFT);
share|improve this answer

If using bit numbers instead of pre-shifted bit masks is acceptable:

bitmap &= ~(((bitmap >> SHIFT_WATER) & 1) << SHIFT_FIRE)
share|improve this answer

Assuming BIT_WATER and BIT_FIRE are not the same bit then

the truth table for

if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE

is (BIT_WATER, old BIT_FIRE, new BIT_FIRE)

0 0   0
0 1   1
1 0   0
1 1   0

So from a bit perspective that is

BIT_FIRE = (~BIT_WATER)&BIT_FIRE;

1 0   0
1 1   1
0 0   0
0 1   0

Since I dont know the gap between your two bits then something like this which is excessive.

newbit = ((~(bitmap>>BIT_WATER_BIT))&(bitmap>>BIT_FIRE_BIT))&1;
bitmap&=~BIT_FIRE;
bitmap|=newbit<<BIT_FIRE_BIT;

Assuming I didnt make a typo...Also which I assume can be simplified if you take advantage of the specific bit numbers and not do something generic (shift BIT_WATER bit over to land on BIT_FIRE rather than shift everything right then left again. May not make it simpler though.

if bit water bit is 7 and bit fire bit is 3

bitmap = (((~(bitmap>>4))>>4)&(1<<3))&bitmap;

Or maybe this

bitmap = (((bitmap&(~BIT_WATER))^BIT_WATER)>>4)&bitmap;

where >>4 is the direction and delta between BIT_WATER and BIT_FIRE. fill in the proper delta.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.