I saw a some solutions but its look complex.
What are the most effective way to swap between two bits in n,m postions?
int swapBits(int num, int nPostion, int mPosition); Given integer n in which we wants to swap bit at location p1 and p2 : Algorithm : if both bits are same then just return same value else toggle both bits using XOR.
unsigned int swapBits(unsigned int n, unsigned int p1, unsigned int p2) { return (((n >> p1) & 1) == ((n >> p2) & 1) ? n : ((n ^ (1 << p2)) ^ (1 << p1))); } (1 << p2) should be (1U << p2) to avoid undefined behavior if p2 is one less than the width of unsigned int. Same remark for (1 << p1)Not sure it is the most effective, but I think this is a rather simple solution:
int bitValue(int num, int nPosition) { return ( num >> nPosition ) % 2; } int swapBits(int num, int nPosition, int mPosition) { int nVal = bitValue(num, nPosition); int mVal = bitValue(num, mPosition); if (nVal != mVal) { if (1 == nVal) { num -= 1<<nPosition; num += 1<<mPosition; } else { num += 1<<nPosition; num -= 1<<mPosition; } } return num; } Same solution in a more efficient (but less readable) way:
int swapBits2(int num, int nPosition, int mPosition) { int nVal = ( num >> nPosition ) % 2; int mVal = ( num >> mPosition ) % 2; if (nVal != mVal) { num += (-1)*(2*mVal-1)*(1<<mPosition) + (-1)*(2*nVal-1)*(1<<nPosition); } return num; } and last:
int swapBits3(int num, int nPosition, int mPosition) { int k = ((num >> nPosition) & 1) - (num >> mPosition) & 1; return num + k*(1<<mPosition) - k*(1<<nPosition); } Parth Bera's answer contains a branch, but the xor-idea is correct.
Assume the bits of p are ????A????B???. To turn A into B and B into A, we need to xor them with (A^B). For convenience, let X=A^B
????A????B??? 0000X0000X000 ^ ============= ????B????A??? How do we generate 0000X0000X000 ?
????A????B??? >> (nPostion-mPostion) ?????????A??? ^ ?????????X??? & (1<<mPosition) 000000000X000 << (nPostion-mPostion) 0000X00000000 + 0000X0000X000 ^ ????A????B??? == ????B????A??? You can use the following macro to avoid temporary variables or a stack allocation, and it will work with any numeric type:
#define SWAP_BITS(v,b1,b2) \ (((v)>>(b1)&1)==((v)>>(b2)&1)?(v):(v^(1ULL<<(b1))^(1ULL<<(b2)))) int, long and long long if b1 or b2 refer to the most significant bit as shifting 1 cast to the destination type by that much has undefined behavior.1ULL, updated my answer now as well. About multiple evaluation: Yes that may happen but shouldn't the compiler optimize that away, at least if it knows to be free of side-effects? The macro may no be the best choice if you pass in a function call as expression. But if you want to use it for multiple types you'd need to define your function multiple times, don't you?_Generic construct allows a macro to expand to the appropriate function call as determined from the type of the argument eg: #define swap_bits(v,b1,b2) _Generic(+(v), unsigned int: swap_bits_uint, unsigned long: swap_bits_ulong, unsigned long long: swap_bits_ullong)(v, b1, b2)Building on Shay Gold's solution, here is one with a few bug fixes:
unsigned int swapBits(unsigned int num, int nPosition, int mPosition) { unsigned int k = ((num >> nPosition) & 1) - ((num >> mPosition) & 1); return num + k * ((1U << mPosition) - (1U << nPosition)); } int swapBits(int num... and unsigned int ...position? Also I don't get why shifting negative numbers should be undefined (although your link suggests this), if we shift bits into the sign bit or out of the sign bit, the number would just swap signs. It's not particularly undefined but maybe unexpected...>> is defined to perform sign replication, and some C implementations do that but the C Standard does not mandate this behavior, nor the one you describe.unsigned int swapbits(unsigned int num, unsigned int pos1, unsigned int pos2) { unsigned int bits_of_interest_mask = (1 << pos1) | (1 << pos2); unsigned int bits_of_interest = num & bits_of_interest_mask; unsigned int null_factor = ((bits_of_interest != 0) & (bits_of_interest != bits_of_interest_mask)); unsigned int xor_mask = null_factor * bits_of_interest_mask; return num ^ xor_mask; } (Compilers remove the multiplication by the boolean: https://godbolt.org/z/a4z3jnh7c, https://godbolt.org/z/aM3TK7bq1)
int num?