K&R Exercise 2-7, optimisations? - c

I'm currently learning C with "The C Programming Language" from K&R. I solved the exercise 2-7, which says:
Write a function invert(x,p,n) that returns x with the n bits that begin at position p inverted (i.e., 1 changed into 0 and vice versa), leaving the other bits unchanged.
Here is my code (I voluntarily used chars here):
#include <stdio.h>
#define NUMBER 235
#define POSITION 2
#define AMOUNT 4
unsigned invert(unsigned char x, char p, char n)
{
unsigned char bitsToInvert = 0, i;
for (i = 1; i < n; i++) { // Make a number n-bits width, full of 1
bitsToInvert |= 1;
bitsToInvert <<= 1;
}
bitsToInvert |= 1;
bitsToInvert <<= p;
x ^= bitsToInvert;
return x;
}
int main()
{
printf("%d\n", invert(NUMBER, POSITION, AMOUNT));
}
Is there any optimisation I could bring to my code? Especially on the for loop which create a number of n 1 bits?
Thanks!

2^n - 1 is always a number with all n LSB bits set.
For eg:
2 ^ 3 - 1 = 7 => 111
2 ^ 5 - 1 = 31 => 11111
In your case, you can do away with the for loop to construct this number by simply saying:
bitsToConvert = (1<<n) - 1;
Dont forget to take care of extreme situations.

An alternative to what Thrustmaster said, that would work for any "n" without the need for specifying it, would be using a bitwise not on an empty value.
variable = ~(variable ^ variable);

Related

Convert int to binary string of certain size

I'm struggling to adapt to C after programming in Java for some time and I need help. What I'm looking for is a method that takes following input:
Integer n, the one to be converted to binary string (character array).
Integer length, which defines the length of the string (positions from the left not filled with the binary numbers are going to be set to default 0).
//Here's some quick code in Java to get a better understanding of what I'm looking for:
public static String convertToBinary(int length, int n) {
return String.format("%1$" + bit + "s", Integer.toBinaryString(value)).replace(' ', '0');
}
System.out.println(convertToBinary(8,1));
// OUTPUT:
00000001 (not just 1 or 01)
Any hints on what the equivalent of this would be in C? Also, could you provide me with an example of how the resulting binary string should be returned?
(not a duplicate, since what I'm looking for is '00000001', not simply '1')
The C standard library does not contain an equivalent function to Integer.toBinaryString(). The good news is, writing such a function won't be too complicated, and if you're in the process of learning C, this problem is fairly ideal for learning how to use the bitwise operators.
You'll want to consult an existing tutorial or manual for all the details, but here are a few examples of the sort of things that would be useful for this or similar tasks. All numbers are unsigned integers in these examples.
n >> m shifts all bits in n right by m steps, and fills in zeros on the left side. So if n = 13 (1101 in binary), n >> 1 would be 6 (i.e. 110), and n >> 2 would be 3 (i.e. 11).
n << m does the same thing, but shifting left. 3 << 2 == 12. This is equivalent to multiplying n by 2 to the power of m. (If it isn't obvious why that is, you'll want to think about how binary numbers are represented for awhile until you understand it clearly; it'll make things easier if you have an intuitive understanding of that property.)
n & m evaluates to a number such that each bit of the result is 1 if and only if it's 1 in both n and m. e.g. 12 & 5 == 4, (1100, 0101, and 0100 being the respective representations of 12, 5, and 4).
So putting those together, n & (1 << i) will be nonzero if and only if bit i is set: 1 obviously only has a single bit set, 1 << i moves it to the appropriate position, and n & (1 << i) checks if that position also has a 1 bit for n. (keeping in mind that the rightmost/least significant bit is bit 0, not bit 1.) So using that, it's a simple matter of checking each bit individually to see if it's 1 or 0, and you have your binary conversion function.
like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
char *convertToBinary(int length, int n) {
unsigned num = (unsigned)n;
int n_bit = CHAR_BIT * sizeof(num);
if(length > n_bit){
fprintf(stderr, "specified length greater than maximum length.\n");
length = n_bit;//or expand size?
}
char *bin = malloc(n_bit + 1);//static char bin[CHAR_BIT * sizeof(num)+1]; If you change, memmove(-->return p;), free is not necessary.
memset(bin, '0', n_bit);
bin[n_bit] = 0;
char *p = bin + n_bit;
do {
*--p = "01"[num & 1];
num >>= 1;
}while(num);
int bits = bin + n_bit - p;
if(bits < length){
p -= length - bits;
return memmove(bin, p, length + 1);
} else if(bits > length){
fprintf(stderr, "Specified length is not enough.(%s but length is %d)\n", p, length);
return memmove(bin, p, bits+1);//or cut off
/*
free(bin);
return ""; or return NULL;
*/
}// else if(bits == length)
return bin;
}
int main(void){
char *sbin = convertToBinary(8, 1);
puts(sbin);
free(sbin);
return 0;
}

Iterate through bits in C

I have a big char *str where the first 8 chars (which equals 64 bits if I'm not wrong), represents a bitmap. Is there any way to iterate through these 8 chars and see which bits are 0? I'm having alot of trouble understanding the concept of bits, as you can't "see" them in the code, so I can't think of any way to do this.
Imagine you have only one byte, a single char my_char. You can test for individual bits using bitwise operators and bit shifts.
unsigned char my_char = 0xAA;
int what_bit_i_am_testing = 0;
while (what_bit_i_am_testing < 8) {
if (my_char & 0x01) {
printf("bit %d is 1\n", what_bit_i_am_testing);
}
else {
printf("bit %d is 0\n", what_bit_i_am_testing);
}
what_bit_i_am_testing++;
my_char = my_char >> 1;
}
The part that must be new to you, is the >> operator. This operator will "insert a zero on the left and push every bit to the right, and the rightmost will be thrown away".
That was not a very technical description for a right bit shift of 1.
Here is a way to iterate over each of the set bits of an unsigned integer (use unsigned rather than signed integers for well-defined behaviour; unsigned of any width should be fine), one bit at a time.
Define the following macros:
#define LSBIT(X) ((X) & (-(X)))
#define CLEARLSBIT(X) ((X) & ((X) - 1))
Then you can use the following idiom to iterate over the set bits, LSbit first:
unsigned temp_bits;
unsigned one_bit;
temp_bits = some_value;
for ( ; temp_bits; temp_bits = CLEARLSBIT(temp_bits) ) {
one_bit = LSBIT(temp_bits);
/* Do something with one_bit */
}
I'm not sure whether this suits your needs. You said you want to check for 0 bits, rather than 1 bits — maybe you could bitwise-invert the initial value. Also for multi-byte values, you could put it in another for loop to process one byte/word at a time.
It's true for little-endian memory architecture:
const int cBitmapSize = 8;
const int cBitsCount = cBitmapSize * 8;
const unsigned char cBitmap[cBitmapSize] = /* some data */;
for(int n = 0; n < cBitsCount; n++)
{
unsigned char Mask = 1 << (n % 8);
if(cBitmap[n / 8] & Mask)
{
// if n'th bit is 1...
}
}
In the C language, chars are 8-bit wide bytes, and in general in computer science, data is organized around bytes as the fundamental unit.
In some cases, such as your problem, data is stored as boolean values in individual bits, so we need a way to determine whether a particular bit in a particular byte is on or off. There is already an SO solution for this explaining how to do bit manipulations in C.
To check a bit, the usual method is to AND it with the bit you want to check:
int isBitSet = bitmap & (1 << bit_position);
If the variable isBitSet is 0 after this operation, then the bit is not set. Any other value indicates that the bit is on.
For one char b you can simply iterate like this :
for (int i=0; i<8; i++) {
printf("This is the %d-th bit : %d\n",i,(b>>i)&1);
}
You can then iterate through the chars as needed.
What you should understand is that you cannot manipulate directly the bits, you can just use some arithmetic properties of number in base 2 to compute numbers that in some way represents some bits you want to know.
How does it work for example ? In a char there is 8 bits. A char can be see as a number written with 8 bits in base 2. If the number in b is b7b6b5b4b3b2b1b0 (each being a digit) then b>>i is b shifted to the right by i positions (in the left 0's are pushed). So, 10110111 >> 2 is 00101101, then the operation &1 isolate the last bit (bitwise and operator).
If you want to iterate through all char.
char *str = "MNO"; // M=01001101, N=01001110, O=01001111
int bit = 0;
for (int x = strlen(str)-1; x > -1; x--){ // Start from O, N, M
printf("Char %c \n", str[x]);
for(int y=0; y<8; y++){ // Iterate though every bit
// Shift bit the the right with y step and mask last position
if( str[x]>>y & 0b00000001 ){
printf("bit %d = 1\n", bit);
}else{
printf("bit %d = 0\n", bit);
}
bit++;
}
}
output
Char O
bit 0 = 1
bit 1 = 1
bit 2 = 1
bit 3 = 1
bit 4 = 0
bit 5 = 0
bit 6 = 1
bit 7 = 0
Char N
bit 8 = 0
bit 9 = 1
bit 10 = 1
...

Return 1 if any bits in an integer equal 1 using bit operations in C

I've been thinking about this problem for hours. Here it is:
Write an expression that returns 1 if a given integer "x" has any bits equal to 1. return 0 otherwise.
I understand that I'm essentially just trying to figure out if x == 0 because that is the only int that has no 1 bits, but I can't figure out a solution. You may not use traditional control structures. You may use bitwise operators, addition, subtraction, and bit shifts. Suggestions?
Here's the best I could come up with:
y = (((-x) | x) >> (BITS - 1)) & 1;
where BITS = 32 for 32 bit ints, i.e. BITS = sizeof(int) * CHAR_BIT;
Here's a test program:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char *argv[])
{
const int BITS = sizeof(int) * CHAR_BIT;
if (argc == 2)
{
int x = atoi(argv[1]);
int y = (((-x) | x) >> (BITS - 1)) & 1;
printf("%d -> %d\n", x, y);
}
return 0;
}
Using !!x will give you the right answer. Since !0 = 1 and !(any nonzero number) = 0.
For a 32-bit value, the following will work for all bit-patterns.
return (a | -a) >> 31;
Mask each of the bits individually, shift them all down to the lsb position, and or them together.
You could just cast your int to a bool. But I doubt that's the purpose of your homework ;-)
For 32 bit integers
int return_not_zero(int v)
{
r=v;
r=(r&0xFFFF) | (r>>16);
r=(r&0xFF) | (r>>8);
r=(r&0x0F) | (r>>4);
r=(r&0x03) | (r>>2);
r=(r&0x01) | (r>>1);
return r;
}
0 || number - this will return 0 only if the number is 0 and will return 1 if the number is any other number than 0. Since a number without any bit as 1 will be equal to 0, we need to check it with 0.
untested, that's the first thing that came to my mind:
while(n & pow(2, e) == 0 && e++ <= 16) ; // 16 or 32
if e == 16 after the loop n is 0.
int any_bits_to_one(unsigned int n) {
int result = 0, i;
for (i=0; !result && i < sizeof(unsigned int) * 8; i++)
result |= (n & (1<<i)) ? 1 : 0;
return result;
}
Bitwise AND with 0 and any number must equal zero, but the only foolproof test would be with 0xFFFF, or every bit being set. To get all bits set, you should have a signed int, and assign it -1. You will then have an int with all bits set to 1, regardless of size.
So my answer would be to bitwise AND it with -1
How about !(x&&~x)&&x ?
#include <stdio.h>
void main(){
int x;
scanf("%d",&x);
printf("%d\n",(!(x&&~x)&&x));
}
It seems work, but I'm not sure when overflow happens.
I believe this is the simplest way.
return !!(0|x);
The only time your x will not have a 1 in it is when all bits are 0, or x == 0. So 0|0 -> 0 else 0|x -> non zero.
In C language, any value other than ZERO (either positive or negative) is treated as TRUE. And there should be a condition to check either your question's solution returns a ZERO or ONE (or other than ZERO). Therefore this answer is perfectly as per your requirement. This uses only bit-wise operators.
return (x & 0xFFFF);
This line returns ZERO when neither of any bit in "x" is 1, and returns Non-Zero (TRUE in a sense) when any of the bit is 1 in "x".

Fastest way to count number of bit transitions in an unsigned int

I'm looking for the fastest way of counting the number of bit transitions in an unsigned int.
If the int contains: 0b00000000000000000000000000001010
The number of transitions are: 4
If the int contains: 0b00000000000000000000000000001001
The number of transitions are: 3
Language is C.
int numTransitions(int a)
{
int b = a >> 1; // sign-extending shift properly counts bits at the ends
int c = a ^ b; // xor marks bits that are not the same as their neighbors on the left
return CountBits(c); // count number of set bits in c
}
For an efficient implementation of CountBits see http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
Fastest depends on your scenario:
As you specified your datatype as constant sized (unsigned int), it is possible with lookup table. But when you need this operation only once the constant overhead to init the table is too big, and scanning+counting through the int is far faster despite.
I guess the overall best would be a combination: Look up table for a byte or word (256 or 64k entries is not so much), and then combine the bytes/words by their last/first bit.
In C/C++ I would do the following:
unsigned int Transitions(unsigned int value)
{
unsigned int result = 0;
for (unsigned int markers = value ^ (value >> 1); markers; markers = markers >> 1)
{
if (markers & 0x01) result++;
}
return result;
}
Here's the code using arithmetic shift + xor and Kernighan's method for bit counting:
int count_transitions(int x)
{
assert((-1 >> 1) < 0); // check for arithmetic shift
int count = 0;
for(x ^= (x >> 1); x; x &= x - 1)
++count;
return count;
}
What language?
I would loop 64 times and then bit shift your number to inspect of the bits, then store the previous bit and compare it to the current one. If it's different, incremember your count.
Ok, with transitions you mean if you walk through the string of 0-s and 1-s, you count each occurance that a 0 follows a 1 or a 1 follows a 0.
This is easy by shifting bits out and counting the changes:
transitions(n)
result = 0
prev = n mod 2
n = n div 2
while n<>0
if n mod 2 <> prev then
result++
prev = n mod 2
fi
n = n div 2
elihw
return result
you can replace the mod and div with shifts.

Bit reversal of an integer, ignoring integer size and endianness

Given an integer typedef:
typedef unsigned int TYPE;
or
typedef unsigned long TYPE;
I have the following code to reverse the bits of an integer:
TYPE max_bit= (TYPE)-1;
void reverse_int_setup()
{
TYPE bits= (TYPE)max_bit;
while (bits <<= 1)
max_bit= bits;
}
TYPE reverse_int(TYPE arg)
{
TYPE bit_setter= 1, bit_tester= max_bit, result= 0;
for (result= 0; bit_tester; bit_tester>>= 1, bit_setter<<= 1)
if (arg & bit_tester)
result|= bit_setter;
return result;
}
One just needs first to run reverse_int_setup(), which stores an integer with the highest bit turned on, then any call to reverse_int(arg) returns arg with its bits reversed (to be used as a key to a binary tree, taken from an increasing counter, but that's more or less irrelevant).
Is there a platform-agnostic way to have in compile-time the correct value for max_int after the call to reverse_int_setup(); Otherwise, is there an algorithm you consider better/leaner than the one I have for reverse_int()?
Thanks.
#include<stdio.h>
#include<limits.h>
#define TYPE_BITS sizeof(TYPE)*CHAR_BIT
typedef unsigned long TYPE;
TYPE reverser(TYPE n)
{
TYPE nrev = 0, i, bit1, bit2;
int count;
for(i = 0; i < TYPE_BITS; i += 2)
{
/*In each iteration, we swap one bit on the 'right half'
of the number with another on the left half*/
count = TYPE_BITS - i - 1; /*this is used to find how many positions
to the left (and right) we gotta move
the bits in this iteration*/
bit1 = n & (1<<(i/2)); /*Extract 'right half' bit*/
bit1 <<= count; /*Shift it to where it belongs*/
bit2 = n & 1<<((i/2) + count); /*Find the 'left half' bit*/
bit2 >>= count; /*Place that bit in bit1's original position*/
nrev |= bit1; /*Now add the bits to the reversal result*/
nrev |= bit2;
}
return nrev;
}
int main()
{
TYPE n = 6;
printf("%lu", reverser(n));
return 0;
}
This time I've used the 'number of bits' idea from TK, but made it somewhat more portable by not assuming a byte contains 8 bits and instead using the CHAR_BIT macro. The code is more efficient now (with the inner for loop removed). I hope the code is also slightly less cryptic this time. :)
The need for using count is that the number of positions by which we have to shift a bit varies in each iteration - we have to move the rightmost bit by 31 positions (assuming 32 bit number), the second rightmost bit by 29 positions and so on. Hence count must decrease with each iteration as i increases.
Hope that bit of info proves helpful in understanding the code...
The following program serves to demonstrate a leaner algorithm for reversing bits, which can be easily extended to handle 64bit numbers.
#include <stdio.h>
#include <stdint.h>
int main(int argc, char**argv)
{
int32_t x;
if ( argc != 2 )
{
printf("Usage: %s hexadecimal\n", argv[0]);
return 1;
}
sscanf(argv[1],"%x", &x);
/* swap every neigbouring bit */
x = (x&0xAAAAAAAA)>>1 | (x&0x55555555)<<1;
/* swap every 2 neighbouring bits */
x = (x&0xCCCCCCCC)>>2 | (x&0x33333333)<<2;
/* swap every 4 neighbouring bits */
x = (x&0xF0F0F0F0)>>4 | (x&0x0F0F0F0F)<<4;
/* swap every 8 neighbouring bits */
x = (x&0xFF00FF00)>>8 | (x&0x00FF00FF)<<8;
/* and so forth, for say, 32 bit int */
x = (x&0xFFFF0000)>>16 | (x&0x0000FFFF)<<16;
printf("0x%x\n",x);
return 0;
}
This code should not contain errors, and was tested using 0x12345678 to produce 0x1e6a2c48 which is the correct answer.
typedef unsigned long TYPE;
TYPE reverser(TYPE n)
{
TYPE k = 1, nrev = 0, i, nrevbit1, nrevbit2;
int count;
for(i = 0; !i || (1 << i && (1 << i) != 1); i+=2)
{
/*In each iteration, we swap one bit
on the 'right half' of the number with another
on the left half*/
k = 1<<i; /*this is used to find how many positions
to the left (or right, for the other bit)
we gotta move the bits in this iteration*/
count = 0;
while(k << 1 && k << 1 != 1)
{
k <<= 1;
count++;
}
nrevbit1 = n & (1<<(i/2));
nrevbit1 <<= count;
nrevbit2 = n & 1<<((i/2) + count);
nrevbit2 >>= count;
nrev |= nrevbit1;
nrev |= nrevbit2;
}
return nrev;
}
This works fine in gcc under Windows, but I'm not sure if it's completely platform independent. A few places of concern are:
the condition in the for loop - it assumes that when you left shift 1 beyond the leftmost bit, you get either a 0 with the 1 'falling out' (what I'd expect and what good old Turbo C gives iirc), or the 1 circles around and you get a 1 (what seems to be gcc's behaviour).
the condition in the inner while loop: see above. But there's a strange thing happening here: in this case, gcc seems to let the 1 fall out and not circle around!
The code might prove cryptic: if you're interested and need an explanation please don't hesitate to ask - I'll put it up someplace.
#ΤΖΩΤΖΙΟΥ
In reply to ΤΖΩΤΖΙΟΥ 's comments, I present modified version of above which depends on a upper limit for bit width.
#include <stdio.h>
#include <stdint.h>
typedef int32_t TYPE;
TYPE reverse(TYPE x, int bits)
{
TYPE m=~0;
switch(bits)
{
case 64:
x = (x&0xFFFFFFFF00000000&m)>>16 | (x&0x00000000FFFFFFFF&m)<<16;
case 32:
x = (x&0xFFFF0000FFFF0000&m)>>16 | (x&0x0000FFFF0000FFFF&m)<<16;
case 16:
x = (x&0xFF00FF00FF00FF00&m)>>8 | (x&0x00FF00FF00FF00FF&m)<<8;
case 8:
x = (x&0xF0F0F0F0F0F0F0F0&m)>>4 | (x&0x0F0F0F0F0F0F0F0F&m)<<4;
x = (x&0xCCCCCCCCCCCCCCCC&m)>>2 | (x&0x3333333333333333&m)<<2;
x = (x&0xAAAAAAAAAAAAAAAA&m)>>1 | (x&0x5555555555555555&m)<<1;
}
return x;
}
int main(int argc, char**argv)
{
TYPE x;
TYPE b = (TYPE)-1;
int bits;
if ( argc != 2 )
{
printf("Usage: %s hexadecimal\n", argv[0]);
return 1;
}
for(bits=1;b;b<<=1,bits++);
--bits;
printf("TYPE has %d bits\n", bits);
sscanf(argv[1],"%x", &x);
printf("0x%x\n",reverse(x, bits));
return 0;
}
Notes:
gcc will warn on the 64bit constants
the printfs will generate warnings too
If you need more than 64bit, the code should be simple enough to extend
I apologise in advance for the coding crimes I committed above - mercy good sir!
There's a nice collection of "Bit Twiddling Hacks", including a variety of simple and not-so simple bit reversing algorithms coded in C at http://graphics.stanford.edu/~seander/bithacks.html.
I personally like the "Obvious" algorigthm (http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious) because, well, it's obvious. Some of the others may require less instructions to execute. If I really need to optimize the heck out of something I may choose the not-so-obvious but faster versions. Otherwise, for readability, maintainability, and portability I would choose the Obvious one.
Here is a more generally useful variation. Its advantage is its ability to work in situations where the bit length of the value to be reversed -- the codeword -- is unknown but is guaranteed not to exceed a value we'll call maxLength. A good example of this case is Huffman code decompression.
The code below works on codewords from 1 to 24 bits in length. It has been optimized for fast execution on a Pentium D. Note that it accesses the lookup table as many as 3 times per use. I experimented with many variations that reduced that number to 2 at the expense of a larger table (4096 and 65,536 entries). This version, with the 256-byte table, was the clear winner, partly because it is so advantageous for table data to be in the caches, and perhaps also because the processor has an 8-bit table lookup/translation instruction.
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};
const unsigned short masks[17] =
{0,0,0,0,0,0,0,0,0,0X0100,0X0300,0X0700,0X0F00,0X1F00,0X3F00,0X7F00,0XFF00};
unsigned long codeword; // value to be reversed, occupying the low 1-24 bits
unsigned char maxLength; // bit length of longest possible codeword (<= 24)
unsigned char sc; // shift count in bits and index into masks array
if (maxLength <= 8)
{
codeword = table[codeword << (8 - maxLength)];
}
else
{
sc = maxLength - 8;
if (maxLength <= 16)
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc];
}
else if (maxLength & 1) // if maxLength is 17, 19, 21, or 23
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc] |
(table[(codeword & masks[sc]) >> (sc - 8)] << 8);
}
else // if maxlength is 18, 20, 22, or 24
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc]
| (table[(codeword & masks[sc]) >> (sc >> 1)] << (sc >> 1));
}
}
How about:
long temp = 0;
int counter = 0;
int number_of_bits = sizeof(value) * 8; // get the number of bits that represent value (assuming that it is aligned to a byte boundary)
while(value > 0) // loop until value is empty
{
temp <<= 1; // shift whatever was in temp left to create room for the next bit
temp |= (value & 0x01); // get the lsb from value and set as lsb in temp
value >>= 1; // shift value right by one to look at next lsb
counter++;
}
value = temp;
if (counter < number_of_bits)
{
value <<= counter-number_of_bits;
}
(I'm assuming that you know how many bits value holds and it is stored in number_of_bits)
Obviously temp needs to be the longest imaginable data type and when you copy temp back into value, all the extraneous bits in temp should magically vanish (I think!).
Or, the 'c' way would be to say :
while(value)
your choice
We can store the results of reversing all possible 1 byte sequences in an array (256 distinct entries), then use a combination of lookups into this table and some oring logic to get the reverse of integer.
Here is a variation and correction to TK's solution which might be clearer than the solutions by sundar. It takes single bits from t and pushes them into return_val:
typedef unsigned long TYPE;
#define TYPE_BITS sizeof(TYPE)*8
TYPE reverser(TYPE t)
{
unsigned int i;
TYPE return_val = 0
for(i = 0; i < TYPE_BITS; i++)
{/*foreach bit in TYPE*/
/* shift the value of return_val to the left and add the rightmost bit from t */
return_val = (return_val << 1) + (t & 1);
/* shift off the rightmost bit of t */
t = t >> 1;
}
return(return_val);
}
The generic approach hat would work for objects of any type of any size would be to reverse the of bytes of the object, and the reverse the order of bits in each byte. In this case the bit-level algorithm is tied to a concrete number of bits (a byte), while the "variable" logic (with regard to size) is lifted to the level of whole bytes.
Here's my generalization of freespace's solution (in case we one day get 128-bit machines). It results in jump-free code when compiled with gcc -O3, and is obviously insensitive to the definition of foo_t on sane machines. Unfortunately it does depend on shift being a power of 2!
#include <limits.h>
#include <stdio.h>
typedef unsigned long foo_t;
foo_t reverse(foo_t x)
{
int shift = sizeof (x) * CHAR_BIT / 2;
foo_t mask = (1 << shift) - 1;
int i;
for (i = 0; shift; i++) {
x = ((x & mask) << shift) | ((x & ~mask) >> shift);
shift >>= 1;
mask ^= (mask << shift);
}
return x;
}
int main() {
printf("reverse = 0x%08lx\n", reverse(0x12345678L));
}
In case bit-reversal is time critical, and mainly in conjunction with FFT, the best is to store the whole bit reversed array. In any case, this array will be smaller in size than the roots of unity that have to be precomputed in FFT Cooley-Tukey algorithm. An easy way to compute the array is:
int BitReverse[Size]; // Size is power of 2
void Init()
{
BitReverse[0] = 0;
for(int i = 0; i < Size/2; i++)
{
BitReverse[2*i] = BitReverse[i]/2;
BitReverse[2*i+1] = (BitReverse[i] + Size)/2;
}
} // end it's all

Resources