While there are multiple ways to reverse bit order in a byte, I'm curious as to what is the "simplest" for a developer to implement. And by reversing I mean:
1110 -> 0111
0010 -> 0100
This is similar to, but not a duplicate of this PHP question.
While there are multiple ways to reverse bit order in a byte, I'm curious as to what is the "simplest" for a developer to implement. And by reversing I mean:
1110 -> 0111
0010 -> 0100
This is similar to, but not a duplicate of this PHP question.
If you are talking about a single byte, a table-lookup is probably the best bet, unless for some reason you don't have 256 bytes available.
You may be interested in std::vector<bool> (that is bit-packed) and std::bitset
It should be the simplest as requested.
#include <iostream>
#include <bitset>
using namespace std;
int main() {
bitset<8> bs = 5;
bitset<8> rev;
for(int ii=0; ii!= bs.size(); ++ii)
rev[bs.size()-ii-1] = bs[ii];
cerr << bs << " " << rev << endl;
}
Other options may be faster.
EDIT: I owe you a solution using std::vector<bool>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<bool> b{0,0,0,0,0,1,0,1};
reverse(b.begin(), b.end());
copy(b.begin(), b.end(), ostream_iterator<int>(cerr));
cerr << endl;
}
The second example requires c++0x extension (to initialize the array with {...}). The advantage of using a bitset or a std::vector<bool> (or a boost::dynamic_bitset) is that you are not limited to bytes or words but can reverse an arbitrary number of bits.
HTH
See the bit twiddling hacks for many solutions. Copypasting from there is obviously simple to implement. =)
This should work:
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
First the left four bits are swapped with the right four bits. Then all adjacent pairs are swapped and then all adjacent single bits. This results in a reversed order.
Although probably not portable, I would use assembly language.
Many assembly languages have instructions to rotate a bit into the carry flag and to rotate the carry flag into the word (or byte).
The algorithm is:
for each bit in the data type:
rotate bit into carry flag
rotate carry flag into destination.
end-for
The high level language code for this is much more complicated, because C and C++ do not support rotating to carry and rotating from carry. The carry flag has to modeled.
Edit: Assembly language for example
; Enter with value to reverse in R0.
; Assume 8 bits per byte and byte is the native processor type.
LODI, R2 8 ; Set up the bit counter
Loop:
RRC, R0 ; Rotate R0 right into the carry bit.
RLC, R1 ; Rotate R1 left, then append carry bit.
DJNZ, R2 Loop ; Decrement R2 and jump if non-zero to "loop"
LODR, R0 R1 ; Move result into R0.
I think a look up table has to be one of the simplest methods. However, you don't need a full lookup table.
uint8_t lookup[16] = {
0x0, 0x8, 0x4, 0xC,
0x2, 0xA, 0x6, 0xE,
0x1, 0x9, 0x5, 0xD,
0x3, 0xB, 0x7, 0xF };
uint8_t flip( uint8_t n )
{
//This should be just as fast and it is easier to understand.
//return (lookup[n%16] << 4) | lookup[n/16];
return (lookup[n&0x0F] << 4) | lookup[n>>4];
}
This isn't quite a fast as a full lookup table but it's simpler to code and verify.
Before implementing any algorithmic solution, check the assembly language for whatever CPU architecture you are using. Your architecture may include instructions which handle bitwise manipulations like this (and what could be simpler than a single assembly instruction?).
If such an instruction is not available, then I would suggest going with the lookup table route. You can write a script/program to generate the table for you, and the lookup operations would be faster than any of the bit-reversing algorithms here (at the cost of having to store the lookup table somewhere).
The simplest way is probably to iterate over the bit positions in a loop:
unsigned char reverse(unsigned char c) {
int shift;
unsigned char result = 0;
for (shift = 0; shift < CHAR_BITS; shift++) {
if (c & (0x01 << shift))
result |= (0x80 >> shift);
}
return result;
}
a slower but simpler implementation:
static int swap_bit(unsigned char unit)
{
/*
* swap bit[7] and bit[0]
*/
unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01)) << 7) | (unit & 0x7f));
unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01))) | (unit & 0xfe));
unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01)) << 7) | (unit & 0x7f));
/*
* swap bit[6] and bit[1]
*/
unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02)) << 5) | (unit & 0xbf));
unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02))) | (unit & 0xfd));
unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02)) << 5) | (unit & 0xbf));
/*
* swap bit[5] and bit[2]
*/
unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04)) << 3) | (unit & 0xdf));
unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04))) | (unit & 0xfb));
unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04)) << 3) | (unit & 0xdf));
/*
* swap bit[4] and bit[3]
*/
unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08)) << 1) | (unit & 0xef));
unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08))) | (unit & 0xf7));
unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08)) << 1) | (unit & 0xef));
return unit;
}
Since nobody posted a complete table lookup solution, here is mine:
unsigned char reverse_byte(unsigned char x)
{
static const unsigned char table[] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
return table[x];
}