Plz note, it is not a homework problem and I do not need the c code
for it.
Just give me an idea how should I proceed about it.
I know basic bit manipulation , shifting left, right and have done
simple problems like counting 1's etc but this one doesnt seem to
click to me.
Thanks.
Kapil
Create a temp Byte and AND the original byte with mask 0x1 to see if there
is a 1 in the LSB.
If there is a 1 then OR 0x80 to the temp byte
Now AND the original with 0x2 and if its a 1 then OR the temp with 0x4
And so on.
HTH
Allan
The easiest, clearest and most efficient way is just to use a 256-entry
lookup table.
- Kevin.
http://graphics.stanford.edu/~seander/bithacks.html
> The easiest, clearest and most efficient way is just to use a 256-entry
> lookup table.
That might be true. But it's not very helpful.
How is the lookup table generated? You wouldn't do this by hand, would you?
Jirka
OK, fireproof suit and helmet on....
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
int main(void)
{
unsigned char in = 0;
unsigned char out;
int i;
int j;
for(j = 1; j <= UCHAR_MAX ; j++)
{
in = (unsigned char)j;
printf("in %x", (unsigned)in);
for(i = 0, out = 0; i < CHAR_BIT; i++)
{
in >>= (i != 0);
out <<= (i != 0);
out = (unsigned char)(out | (in & 1));
}
out = (unsigned char)(out | (in & 1));
printf(" out %x\n", (unsigned)out);
}
}
Critique and improvrment suggestions welcome :)
Especially about the casts...
Robert
Oops, drop the statement above - sorry
You don't start with 0x80 on clc.
step 1
Use unsigned char for mask variables.
One portable expression for the initial value of the high mask is:
(((unsigned char)-1 >> 1) + 1)
As stated, 1 is the initial value for the low mask.
step 2
Do a bitwise AND of the high mask and the byte, and
a bitwise AND of the low mask and the byte.
step 3
If the results of the bitwise ANDs are not either both zero
or both nonzero, then the values of the bits being tested
are different and they should be flipped.
One way to do that, would be to XOR the value of the byte
with the result of a bitwise OR of the two masks,
and change the value of the byte to the XOR result.
step 4
Change the values of the high and low mask.
Shift the high mask right by 1 and shift the low mask left by 1.
step 5
If the high mask is greater than the low mask,
then repeat, starting at step 2.
And drop the cast, too. The result of (out | (in & 1)) is assigned
to an an unsigned char. The cast is redundant.
Jirka
int main(void)
{
unsigned in;
unsigned out;
int i;
unsigned char j;
j = 0;
while (++j != 0) {
in = j;
printf("in %x", in);
for (i = 0, out = 0; i < CHAR_BIT; i++) {
in >>= (i != 0);
out <<= (i != 0);
out |= in & 1;
}
printf(" out %x\n", out);
}
return 0;
}
int revb(int n) {
n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
return n;
}
click?
--
Joe Wright mailto:joeww...@earthlink.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
j = 1;
do {
in = j;
printf("in %x", in);
i = 1;
out = in & 1;
do {
in >>= 1;
out <<= 1;
out |= in & 1;
++i;
} while (CHAR_BIT > i);
printf(" out %x\n", out);
} while (++j != 0);
return 0;
}
Aren't integer promotions coming into play here?
At least my compiler warns about assigning an int to a char..
Robert
That's the only reason for the cast: Tell the compiler to stop whining.
Jirka
Oviously not. Blind spot, sorry.
Robert
Kapil
"Allan Bruce" <all...@TAKEAWAYf2s.com> wrote in message news:<bl0t6b$fsi$1...@news.freedom2surf.net>...
On the Texas Instruments 2812 that I am writing code for today, it
would require 65,536 entries, because CHAR_BIT is 16, so that's how
many bits a byte has.
On the Analog Devices SHARC I coded for a few years ago, that would
have required a 4GB x 32 bit table, since all the integer types were
32 bits wide.
But I agree, except in very tight memory situations, a look up table
is by far the fastest if CHAR_BIT is 8.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
>
> "Kapil Khosla" <khosl...@yahoo.com> schrieb im Newsbeitrag
> news:919aa2da.03092...@posting.google.com...
> > Hi,
> > I am trying to reverse a byte eg.
> > 11010000 should look like
> > 00001011
> >
> > Plz note, it is not a homework problem and I do not need the c code
> > for it.
> > Just give me an idea how should I proceed about it.
> >
> > I know basic bit manipulation , shifting left, right and have done
> > simple problems like counting 1's etc but this one doesnt seem to
> > click to me.
> >
>
> OK, fireproof suit and helmet on....
>
> #include <stdlib.h>
> #include <limits.h>
> #include <stdio.h>
>
> int main(void)
> {
> unsigned char in = 0;
> unsigned char out;
> int i;
> int j;
>
> for(j = 1; j <= UCHAR_MAX ; j++)
Not all that common (except to embedded programmers like me), but
there is the distinct possibility that UCHAR_MAX is > INT_MAX.
Infinite loop.
> That might be true. But it's not very helpful.
> How is the lookup table generated? You wouldn't do this by hand, would you?
How's this? (note it only goes forward - the reverse one is nearly the same)
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <string.h>
char buf[CHAR_BIT+1];
void get_binary( int n )
{
int i;
for( i=0 ; i < CHAR_BIT ; i++ ) {
if( n % 2 ) {
buf[CHAR_BIT-i-1]='1';
}
else {
buf[CHAR_BIT-i-1]='0';
}
n/=2;
}
}
int main(void)
{
const int size=pow( 2, CHAR_BIT );
char **table;
int i;
buf[CHAR_BIT]=0;
printf( "%s\n", buf );
/* Error checking on malloc() omitted */
table=malloc( size * sizeof(char *) );
for( i=0 ; i < size ; i++ ) {
table[i]=malloc( (1+CHAR_BIT) * sizeof(char) );
get_binary( i );
strcpy( table[i], buf );
}
for( i=0; i < size ; i++ ) {
printf( "%s\n", table[i] );
}
return EXIT_SUCCESS;
}
--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
> > The easiest, clearest and most efficient way is just to use a 256-entry
> > lookup table.
>
> That might be true. But it's not very helpful.
> How is the lookup table generated? You wouldn't do this by hand, would you?
Do what I did, google for one, copy it into your code, presto. Here's
mine:
#define REVERSEBITS(b) (BitReverseTable[b])
unsigned char BitReverseTable[256] =
{
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
};
Brian Rodenborn
Shudder ;)
OK
unsigned i;
unsigned j;
Better?
Thanks
kind regards
Robert
> The easiest, clearest and most efficient way is just to use a 256-entry
> lookup table.
Forgive me for being architecture specific but intel chips have ror and rol
(roll bits right / left) instructions don't they? If the target processor
has similar instructions that would be far more effictient than any lookup
table or bit manipulation presented already.
Z.
This should do it:
#include <stdio.h>
#include <limits.h>
void display_binary(unsigned char val)
{
int i;
for(i = CHAR_BIT - 1; i >= 0; i--)
printf("%d", (val >> i) & 0x01);
printf("\n");
}
int main(void)
{
unsigned char input = 0xD0;
unsigned char output = 0;
unsigned char cur;
int i;
printf("Before: ");
display_binary(input);
for(i = 0; i < CHAR_BIT; i++)
{
cur = (input >> i) & 0x01;
output |= (cur << CHAR_BIT - i - 1);
}
printf("After: ");
display_binary(output);
return 0;
}
Alex
ummm, isn't the reverse table exactly the same?
--
Roger
If we wanted to rotate bits, yes; but the question was how to reverse
bits...
--
Roger
I think the OPs example made it clear that he wanted to reverse an 8 bit
value (due to the zero padding stopping at the 8th bit), rather than
reverse an arbitrary char value.
- Kevin.
I don't see how rotate instructions help you implement the requested
transformation.
- Kevin.
Nope. What if UCHAR_MAX == UINT_MAX.
--
Chuck F (cbfal...@yahoo.com) (cbfal...@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
You are allowed to rotate bits left into the carry, and then right
from the carry into the destination. However no such operations
are built into C.
> Kapil Khosla wrote:
>>
>> Hi,
>> I am trying to reverse a byte eg.
>> 11010000 should look like
>> 00001011
>>
>> Plz note, it is not a homework problem and I do not need the c code
>> for it.
>> Just give me an idea how should I proceed about it.
>>
>> I know basic bit manipulation , shifting left, right and have done
>> simple problems like counting 1's etc but this one doesnt seem to
>> click to me.
>>
>> Thanks.
>> Kapil
>
> int revb(int n) {
> n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
> n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
> n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
> return n;
> }
>
> click?
Clicks for me.
This is really a beautiful solution. The flow of bits from one stage to
the next is just like the flow of data through the classic radix 2 FFT,
which, interestingly enough, is where the problem of reversing bits seems
to be used most of the time.
Too bad it only works when the number of bits to reverse is a power of two.
Mac
--
> ummm, isn't the reverse table exactly the same?
Well, if the idea is to reverse bytes (and generate a lookup table), table[1]
should be 11111110 (assuming 8-bit characters), right?
> If we wanted to rotate bits, yes; but the question was how to reverse
> bits...
Ah... REVERSE, sorry I was working late yesterday. Of course that renders
bit rotation usless.
Z.
/* BEGIN rev_byte.c */
#include <stdio.h>
int main(void)
{
unsigned char byte, revbyte, hi_mask, lo_mask;
byte = 0;
do {
--byte;
revbyte = byte;
hi_mask = ((unsigned char)-1 >> 1) + 1;
lo_mask = 1;
do {
if (!(revbyte & hi_mask) != !(revbyte & lo_mask)) {
revbyte ^= hi_mask | lo_mask;
}
hi_mask >>= 1;
lo_mask <<= 1;
} while (hi_mask > lo_mask);
printf(" byte = %3u, revbyte = %3u\n",
(unsigned)byte, (unsigned)revbyte);
} while (byte);
return 0;
}
/* END rev_byte.c */
--
pete
This is bit-inversion (C operator ~), not reverse.
HTH
Tauno Voipio
tauno voipio @ iki fi
No, thanks.
BTW: You snipped the link to the look-up table and 'google' is not a synonym
for 'web search', even if most users assume this. ;-)
Jirka
> This is bit-inversion (C operator ~), not reverse.
So it is. :( (my little program still gets cool points though, right??)
Your call, but don't bitch about it.
> BTW: You snipped the link to the look-up table
I did even better, posted my results. Why should I post a link?
> and 'google' is not a synonym
> for 'web search', even if most users assume this. ;-)
I don't recommend any other search engine.
Brian Rodenborn
This seems to be a good solution, although as far as I understand it, it
doesn't really expand the solution space of the previous example that
much. Practically speaking, the possible number of bits for unsigned char
is 8, 16, 24, 32, 64. All of those are powers of two except 24, so the
power of two solution will work. Your solution, if I understand correctly,
will also work on the 24-bit unsigned char.
When I had to solve this problem, I wanted to support any number of bits.
Since I was doing this to support a naive radix 2 FFT, I didn't worry
about size. I figured that if the machine could handle the data it was
using for the FFT, it could handle the LUT, since they would be the same
size.
You inspired me to go back and look at what I did. It looks like I
specified the number of bits, and then copied one bit at a time into the
appropriate place in the LUT.
Here it is. I am the sole author of the following code for copyright
purposes, and I hereby formally release it into the public domain. (I
didn't check to see if it violates any software patents. ;-))
int *build_bitrev_lut(unsigned int num_pts, int num_bits)
/**********************************************
allocates array of size num_pts, and creates a
"bitrev" (bit reversing) look-up table (lut)
in the array. Once this is done, bit reversal
can be effected simply by using array indexing.
e.g., temp = data[i]; data[i]=data[bitrev[i]];
data[bitrev[i]]=temp;
**********************************************/
{
int i, j, *bitrev;
bitrev = calloc(num_pts, sizeof *bitrev);
if (NULL == bitrev)
return NULL;
for (i=0; i<num_pts; i++)
for (j=0; j<num_bits; j++)
bitrev[i] = (bitrev[i] << 1) + ((i >> j) & 1);
return bitrev;
}
Mac
--
That's the only kind of code that's really on topic here.
The loop only executes (CHAR_BIT / 2) times.
The bits which match their opposites, don't get overwritten.
--
pete
[snip]
> Mac wrote:
>> When I had to solve this problem,
>> I wanted to support any number of bits.
>
> That's the only kind of code that's really on topic here.
>
I'm not sure what you mean.
> The loop only executes (CHAR_BIT / 2) times.
> The bits which match their opposites, don't get overwritten.
Yeah, that's what I thought. I guess my point is that for an fft of, say,
32 points, you need to swap bit 0 with bit 4, and bit 1 with bit 3. Bit 2
doesn't need to move. In this situation, my code would create a lookup
table with just 32 entries, so there is no need to worry about numbers
bigger than 31.
The cool thing about the algorithm in the post before yours is that it
actually could be made into a loop that executes log base 2 of the number
of bits times. Since the OP had the number of bits fixed at 8 (implied)
the loop was unrolled to 3 iterations.
Anyway, your code is more optimised than mine since it only loops through
number of bits/2, and mine loops through all the bits.
Mac
--
> Hi,
> I am trying to reverse a byte eg.
> 11010000 should look like
> 00001011
>
> Plz note, it is not a homework problem and I do not need the c code
> for it.
> Just give me an idea how should I proceed about it.
>
> I know basic bit manipulation , shifting left, right and have done
> simple problems like counting 1's etc but this one doesnt seem to
> click to me.
>
> Thanks.
> Kapil
>
Thank you for your post, Kapil.
I have a working program that might do what you want,
and I'll give it to you if you want.
Here is how I do it.
I ask the user to enter some digits.
I use a function called "read_line" to store the digits.
I use a function called "reverse" to reverse the digits.
I use printf to print the result.
I got the read_line function from p. 365 of
_C Programming: A Modern Approach_, by K.N. King. Its prototype is
int read_line(char str[], int n);
I got the reverse function from p. 62 of _The C Programming Language_,
second edition, by Kernighan and Ritchie. Its prototype is
void reverse(char s[]);
This program will reverse any string; it doesn't have to be a string
of digits.
--Steve
Who said you should? *You* said, I should google for the look-up table.
And the question is: why? There are two things you obviously missed.
First: A link was already posted. Second: *Copy* the table in my code?
Without testing it? Since testing it requires an algorithm and once I've
written the algorithm in C, I do *not* need to copy the table.
>>and 'google' is not a synonym
>> for 'web search', even if most users assume this. ;-)
>
> I don't recommend any other search engine.
Could turn out to be a mistake.
Jirka
The OP said he wanted to reverse a byte. He said nothing at all about
8-bit values. In C, by definition, a byte has CHAR_BIT bytes, where
CHAR_BIT >= 8.
> > > >
> > > > for(j = 1; j <= UCHAR_MAX ; j++)
> > >
> > > Not all that common (except to embedded programmers like me), but
> > > there is the distinct possibility that UCHAR_MAX is > INT_MAX.
> > > Infinite loop.
> >
> > Shudder ;)
> >
> > OK
> > unsigned i;
> > unsigned j;
> > Better?
>
> Nope. What if UCHAR_MAX == UINT_MAX.
Sh*t :((
OK, what about
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
int main(void)
{
unsigned char in = 0;
unsigned char out;
int i;
int j;
for(j = UCHAR_MAX; j; j--)
{
in = (unsigned char)(UCHAR_MAX - j + 1);
printf("in %x", (unsigned)in);
for(i = 0, out = 0; i < CHAR_BIT; i++)
{
in >>= (i != 0);
out <<= (i != 0);
out = (unsigned char)(out | (in & 1));
}
out = (unsigned char)(out | (in & 1));
printf(" out %x\n", (unsigned)out);
}
return EXIT_SUCCESS;
}
I _hope_ I got it right now.
UINT_MAX can hopefully not be less than UCHAR_MAX
cheers
Robert
> [snip]
> > Mac wrote:
> >> When I had to solve this problem,
> >> I wanted to support any number of bits.
> >
> > That's the only kind of code that's really on topic here.
>
> I'm not sure what you mean.
This group focuses on portable code.
A program which displays the bit reversed values of
all of the possible byte values,
has implementation defined output,
since the width of a byte is implementation defined,
and so is not strictly speaking "a portable program".
However, code which will do what it's supposed to do,
on any system, regardless of what values are in <limits.h>
or any other standard library headers,
seems portable enough to be on topic,
though code which only works when CHAR_BIT equals 8, is off topic.
If you were to ask a question about how to display
the values of each byte in a int variable,
I would expect to see the C keyword "sizeof",
somewhere in the answer, rather than an answer
which assumed what the value of sizeof(int) was.
--
pete
> Who said you should? *You* said, I should google for the look-up table.
> And the question is: why? There are two things you obviously missed.
> First: A link was already posted.
I didn't follow the link, as you started asking how tables would be
generated. I assumed the bithacks was another bit-manipulation routine.
> Second: *Copy* the table in my code?
> Without testing it? Since testing it requires an algorithm and once I've
> written the algorithm in C, I do *not* need to copy the table.
I was able to do it by examination. The pattern is pretty clear.
Brian Rodenborn
> Mac wrote:
>> On Sun, 28 Sep 2003 06:02:32 +0000, pete wrote:
>
>> [snip]
>
>> > Mac wrote:
>> >> When I had to solve this problem,
>> >> I wanted to support any number of bits.
>> >
>> > That's the only kind of code that's really on topic here.
>>
>> I'm not sure what you mean.
>
> This group focuses on portable code.
>
Understood.
> A program which displays the bit reversed values of
> all of the possible byte values,
> has implementation defined output,
> since the width of a byte is implementation defined,
> and so is not strictly speaking "a portable program".
>
> However, code which will do what it's supposed to do,
> on any system, regardless of what values are in <limits.h>
> or any other standard library headers,
> seems portable enough to be on topic,
> though code which only works when CHAR_BIT equals 8, is off topic.
>
I see what you mean.
> If you were to ask a question about how to display
> the values of each byte in a int variable,
> I would expect to see the C keyword "sizeof",
> somewhere in the answer, rather than an answer
> which assumed what the value of sizeof(int) was.
Me too. ;-)
regards,
Mac
--
^^^^^
> CHAR_BIT >= 8.
Of course you mean bits.
Mac
--
The examples, still visisble in the quoted text, had binary values
zero-padded out to 8 bits. Why stop the zero padding at 8 bits if
you're interested in more than 8 bits? That was my reasoning, anyway -
I did consider the issue.
- Kevin.