Comment On Flipping Out Over Nothin'

Christoph (Derean's coworker) was presented with a daunting challenge: flip all of the bits of an integer (representing a bitfield) to zero. Many programmers would run away and never look back at just the thought of being given such a task. But not Christoph; being the courageous coder he was, he took this vexing problem head-on and engineered a rather elegant solution ... [expand full text]
« PrevPage 1 | Page 2Next »

Re: Flipping Out Over Nothin'

2005-05-13 13:25 • by Anonymous
Wow....



bitfield = 0;



Anyone? Bueller?

Re: Flipping Out Over Nothin'

2005-05-13 13:27 • by Brian
This is the stupidest thing I have ever seen.

Re: Flipping Out Over Nothin'

2005-05-13 13:28 • by Anonymous
What's even more hilarious is that the guy knows how to use bitwise
operators and yet iterates through bit by bit instead of just bitfield
& ~bitfield (which would still be a WTF of course).

Re: Flipping Out Over Nothin'

2005-05-13 13:29 • by Mike R

WITFF?


 


Essentially, create a function that does this:



unsigned int resetBits(unsigned int bitfield)
{
  return 0;
}


 


 

Re: Flipping Out Over Nothin'

2005-05-13 13:30 • by Mike R
34372 in reply to 34370

Anonymous:
What's even more hilarious is that the guy knows how to use bitwise operators and yet iterates through bit by bit instead of just bitfield & ~bitfield (which would still be a WTF of course).


No. bitfield ^ bitfield does the job in half the instructions :)

Re: Flipping Out Over Nothin'

2005-05-13 13:31 • by Manni
I don't know C++ well enough, what do the first line and the tilde (~) do?

Re: Flipping Out Over Nothin'

2005-05-13 13:33 • by Sweets
this is the most f-ing ridiculous solution I have ever seen.



How can anyone that understands the bit operations not realize that
0  and  0000000000000000000000000000000 are the same thing?



a teacher in my cs200 class asked a similiar question on a test, most the class put i=0;

but there were a few kids sweating and writing away at a solution.  This guy must of been one of those guys.

Re: Flipping Out Over Nothin'

2005-05-13 13:33 • by Robin Lavallée
34375 in reply to 34372
If you use a decent compiler, it will be optimized to the same instruction(s) for your platform.

Re: Flipping Out Over Nothin'

2005-05-13 13:34 • by stewie
Apart from the obvious WTFs, I also love the NUMBITS macro, and the re-initialization of index to 0. You know, just to be safe.

Re: Flipping Out Over Nothin'

2005-05-13 13:34 • by Rick
Very, very hard to believe this one is real.

It would be interesting to see how various optimizers handle this code.

Re: Flipping Out Over Nothin'

2005-05-13 13:34 • by Sweets
34378 in reply to 34373
NOT / flips the bit

Re: Flipping Out Over Nothin'

2005-05-13 13:35 • by Sweets
34379 in reply to 34378
Sweets:
NOT / flips the bit




that was in response to Manni

Re: Flipping Out Over Nothin'

2005-05-13 13:41 • by Miszou

flip all of the bits of an integer (representing a bitfield) to zero


I had to read this several times, just to be sure I wasn't missing anything... The obvious "solution" seemed too simple to warrant writing any actual "code", let alone an entire function with macros and everything!


 

Re: Flipping Out Over Nothin'

2005-05-13 13:41 • by Manni
34381 in reply to 34378

Sweets:
NOT / flips the bit


Cool yeah I figured you were replying to me. Then I'm completely retarded, I can't see how this is returning 0. Help me so I never make this mistake.

Re: Flipping Out Over Nothin'

2005-05-13 13:46 • by Brian

Remember:


int i=0 DOES NOT guarantee that all bits will be 0.


If this is "C", see:  http://groups-beta.google.com/group/comp.lang.c/msg/fed3e094bd617097?dmode=source&hl=en


It discusses the two situtations in which 0 is NOT all bits 0

Re: Flipping Out Over Nothin'

2005-05-13 13:48 • by Manni
34384 in reply to 34381

I don't know the language very well, but it looks like the function was supposed to take the number passed into it and flip every bit, not simply flip them all to 0. The WTFs I *am* capable of spotting are that he never uses the parameter he passed into it except for creating his output value, and the fact that he declared the index integer and initialized it to 0, when that could have been easily done in the declaration of the for loop.


If index keeps growing, what will GENBIT(index) return?

Re: Flipping Out Over Nothin'

2005-05-13 14:02 • by cdog
34385 in reply to 34384
Manni:

I don't know the language very well, but it
looks like the function was supposed to take the number passed into it
and flip every bit, not simply flip them all to 0. The WTFs I *am*
capable of spotting are that he never uses the parameter he passed into
it except for creating his output value, and the fact that he declared
the index integer and initialized it to 0, when that could have been
easily done in the declaration of the for loop.


If index keeps growing, what will GENBIT(index) return?





It does in fact zero out the integer.



For each bit in the integer, it first creates a bitmask like this:

00000000000000000000000000000001  (where the 1 is in the correct position for the current bit)



Then he negates it:

11111111111111111111111111111110



Then he ANDs it with the number, thus making the current bit 0.

Re: Flipping Out Over Nothin'

2005-05-13 14:02 • by Brent Railey
34386 in reply to 34384

This guy is retarded in both cases, with case 1 being flip all bits to zero and case 2 being flip all bits to the opposite value. In either case, it could have been done in a single line of code:


In the case of  0 not being all zeros, this is true only if you will be compiling for a processor that is capable of have a 0 with 1 bits for parity or padding. This probably did not apply in this case--for it was submitted to this site.


case 0:


return 0x00000000;  //This will get rid of those wascally 1s.


case 1:


return bitfield ^ 0xFFFFFFFF;


^ is the bitwise XOR operator in C++, C, and C#.

Re: Flipping Out Over Nothin'

2005-05-13 14:06 • by Sweets
34387 in reply to 34384
Manni:

I don't know the language very well, but it
looks like the function was supposed to take the number passed into it
and flip every bit, not simply flip them all to 0. The WTFs I *am*
capable of spotting are that he never uses the parameter he passed into
it except for creating his output value, and the fact that he declared
the index integer and initialized it to 0, when that could have been
easily done in the declaration of the for loop.


If index keeps growing, what will GENBIT(index) return?





my c/c++ is a little rusty, but



GENBIT is a macro that just does 1<<x , which shifts over to the x(index) bit

this guy then finds the opposite value of that bit and then AND s them ultimatley giving you a 0 in all cases

ie)

flag =       0000000

bitfield=   0100001

ANDed

          =   0100000



then

flag =       0000010


bitfield=   0100000


ANDed


          =   0100000

etc.

At a glance that looks like what it does, I'm sure sombody will correct me if I'm wrong.

Re: Flipping Out Over Nothin'

2005-05-13 14:26 • by diaphanein
34388 in reply to 34383
Anonymous:

Remember:


int i=0 DOES NOT guarantee that all bits will be 0.


If this is "C", see:  http://groups-beta.google.com/group/comp.lang.c/msg/fed3e094bd617097?dmode=source&hl=en


It discusses the two situtations in which 0 is NOT all bits 0



Even so, i ^ i should be a faster way to all zeros.


And to the poster of the comment that i ^i  is faster than i & ~i:  This is not necessarily the case.  The xor operation decomposes into seperate operations.  Some architectures this is done at the hardware level, some through a psuedoinstruction.  Remember:


A ^ B === ( ~A & B ) | ( A & ~B )


At the hardware level, doing A & ~A would be approximately 33-50% faster than the above, due to transistor latency and propagation delays.

Re: Flipping Out Over Nothin'

2005-05-13 14:30 • by Apoch
34389 in reply to 34387
Sweets:
Manni:

I don't know the language very well, but it looks like the function was supposed to take the number passed into it and flip every bit, not simply flip them all to 0. The WTFs I *am* capable of spotting are that he never uses the parameter he passed into it except for creating his output value, and the fact that he declared the index integer and initialized it to 0, when that could have been easily done in the declaration of the for loop.


If index keeps growing, what will GENBIT(index) return?




my c/c++ is a little rusty, but

GENBIT is a macro that just does 1< this guy then finds the opposite value of that bit and then AND s them ultimatley giving you a 0 in all cases
ie)
flag =       0000000
bitfield=   0100001
ANDed
          =   0100000

then
flag =       0000010
bitfield=   0100000
ANDed
          =   0100000
etc.
At a glance that looks like what it does, I'm sure sombody will correct me if I'm wrong.


Your bitwise logic is incorrect. 0 AND x = 0, regardless of x, so 0000000 AND 0100001 is 0000000.

Re: Flipping Out Over Nothin'

2005-05-13 14:33 • by Matt B
34390 in reply to 34387
Sadly, the first thing that came to my head was:



return bitfield & 0

Re: Flipping Out Over Nothin'

2005-05-13 14:37 • by Manni
34391 in reply to 34387

Sweets I appreciate you taking the time to try to explain exactly what the various pieces are doing. Everyone else was too busy trying to figure out how to reduce the operation to a flawless solution considering buffering bits or whatever, and so that it takes less than 2 microseconds.

Re: Flipping Out Over Nothin'

2005-05-13 14:52 • by Mike R
34392 in reply to 34388
Anonymous:

And to the poster of the comment that i ^i  is faster than i & ~i:  This is not necessarily the case.  The xor operation decomposes into seperate operations.  Some architectures this is done at the hardware level, some through a psuedoinstruction.  Remember:


A ^ B === ( ~A & B ) | ( A & ~B )


At the hardware level, doing A & ~A would be approximately 33-50% faster than the above, due to transistor latency and propagation delays.



Another way to see if it's faster or not is to look at the number of clock cycles it takes to complete the instruction. Its likely the instruction just passes bits through the logic gates, which would only take a single pulse of the clock. I believe this is an optimized way of clearing registers in x86 assembly.. I may be wrong, but it seems like every high performace compiler, even Intel's does this when it needs to empty a register..


Of course, doing that to a variable in a memory location can be a different story, depending on if/how the compiler optimizes. & ~ works just as well, too... but, generally on any modern processor, it will be 2 instructions instead of a single instruction.


 


 

Re: Flipping Out Over Nothin'

2005-05-13 15:06 • by Sweets
34393 in reply to 34389
Apoch:

Your bitwise logic is incorrect. 0 AND x = 0, regardless of x, so 0000000 AND 0100001 is 0000000.





You're right.  I typed it out kinda quickly and wasn't going for correctness since I knew someone would correct me.


Anyway, I try to avoid bitwise operations on Friday

Re: Flipping Out Over Nothin'

2005-05-13 15:06 • by Anonymous
34394 in reply to 34392
Mike R:
Anonymous:

And to the poster of the comment that i ^i  is faster than i & ~i:  This is not necessarily the case.  The xor operation decomposes into seperate operations.  Some architectures this is done at the hardware level, some through a psuedoinstruction.  Remember:


A ^ B === ( ~A & B ) | ( A & ~B )


At the hardware level, doing A & ~A would be approximately 33-50% faster than the above, due to transistor latency and propagation delays.



Another way to see if it's faster or not is to look at the number of clock cycles it takes to complete the instruction. Its likely the instruction just passes bits through the logic gates, which would only take a single pulse of the clock. I believe this is an optimized way of clearing registers in x86 assembly.. I may be wrong, but it seems like every high performace compiler, even Intel's does this when it needs to empty a register..


Of course, doing that to a variable in a memory location can be a different story, depending on if/how the compiler optimizes. & ~ works just as well, too... but, generally on any modern processor, it will be 2 instructions instead of a single instruction.


 


 



You are wrong. i & ~i is not a single instruction :


1) negate i


2) And the negated i with i


By the way  XOR is a single instruction.


 

Re: Flipping Out Over Nothin'

2005-05-13 15:14 • by Ifeanyi Echeruo
34395 in reply to 34383

But we can all agree that


unsigned long int i = 0;


will be 32 bits worth of zeros;

Re: Flipping Out Over Nothin'

2005-05-13 15:18 • by Mike R
34396 in reply to 34394
Anonymous:
Mike R:

Of course, doing that to a variable in a memory location can be a different story, depending on if/how the compiler optimizes. & ~ works just as well, too... but, generally on any modern processor, it will be 2 instructions instead of a single instruction.



You are wrong. i & ~i is not a single instruction :


1) negate i


2) And the negated i with i


By the way  XOR is a single instruction.



Hm. I must not have been clear: Let me rephrase:


"... AND NOT will be 2 instructions instead of XOR's single instruction"


I think what the post I was replying to was eluding to the fact that XOR may be more complex in microcode. I don't necessarily think this is so.

Re: Flipping Out Over Nothin'

2005-05-13 15:20 • by Mike R
34397 in reply to 34395
Anonymous:

But we can all agree that


unsigned long int i = 0;


will be 32 bits worth of zeros;



Not necessarily, it could be 48 bits of zeros with 16 bits worth of "padding" which could be either 0's or 1's.


Of course, I know of no compiler or archetecture that does this....

Re: Flipping Out Over Nothin'

2005-05-13 15:38 • by CornedBee
34398 in reply to 34395
Anonymous:

But we can all agree that


unsigned long int i = 0;


will be 32 bits worth of zeros;





Working on an Athlon64 on Linux, I most definitely cannot agree.

unsigned long int i = 0;

On my machine, this is 64 bits worth of zeros.





The padding bits are irrelevant. They are not part of the value, and as
such may not influence comparisons, may not be used by bitfields - they
are a hardware-level detail and might as well not be there as far as
the programmer is concerned.

Re: Flipping Out Over Nothin'

2005-05-13 15:40 • by Grant
34399 in reply to 34396
Mike R:
Anonymous:
Mike R:

Of course, doing that to a variable in a memory location can be a different story, depending on if/how the compiler optimizes. & ~ works just as well, too... but, generally on any modern processor, it will be 2 instructions instead of a single instruction.



You are wrong. i & ~i is not a single instruction :


1) negate i


2) And the negated i with i


By the way  XOR is a single instruction.



Hm. I must not have been clear: Let me rephrase:


"... AND NOT will be 2 instructions instead of XOR's single instruction"


I think what the post I was replying to was eluding to the fact that XOR may be more complex in microcode. I don't necessarily think this is so.



If it's x86, everyone (or at least everyone doing assembly) knows that XOR is the fastest way to zero out a register.  This is so common it's even done to set something to zero in unoptimized code.

Re: Flipping Out Over Nothin'

2005-05-13 15:41 • by CornedBee
34400 in reply to 34394
Anonymous:

You are wrong. i & ~i is not a single instruction :


1) negate i


2) And the negated i with i


By the way  XOR is a single instruction.





andnot t0, t0, t0


Perfectly valid Alpha assembly. AND NOT can indeed be a single instruction.


Re: Flipping Out Over Nothin'

2005-05-13 16:00 • by allanc
That code would be horrible in anything time critical! He should really use Duff's Device to unroll that loop:



unsigned int resetBits(unsigned int bitfield)

{

    unsigned int n=(NUMBITS+7)/8;

    unsigned int index=0;

    unsigned int flag;


    switch (index % 8)
    {

        case 0: do{ flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 7:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 6:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 5:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 4:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 3:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 2:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

        case 1:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;

                  } while (--n>0);

    }

    return bitfield;

}

Re: Flipping Out Over Nothin'

2005-05-13 16:30 • by diaphanein
34403 in reply to 34400
CornedBee:
Anonymous:

You are wrong. i & ~i is not a single instruction :


1) negate i


2) And the negated i with i


By the way  XOR is a single instruction.




andnot t0, t0, t0


Perfectly valid Alpha assembly. AND NOT can indeed be a single instruction.



Thanks!  To those that missed it, my original point is that xor is not necessarily the fastest way **on all architectures**.  Even if it is the "simplest" from an assembler standpoint.  Every way I've seen the operation designed in hardware, using either static or dynamic logic, xor is always slower than the "and not" approach.  x86 is not all there is in the world, people.

Re: Flipping Out Over Nothin'

2005-05-13 16:32 • by Newbie

Finally, a WTF I get, being a new programmer!


 


What a dumbass!

Re: Flipping Out Over Nothin'

2005-05-13 16:38 • by Bustaz Kool

Advantages to this code:


Allows for scalability - If the INTEGER size changes from 32 bit to, say, 33 bit, a single define allows the new hardware to be supported.


Handles different types of zeros (Binary, decimal and hexadecimal - Might handle Octal, too, but I'm not too sure about that one.)


Actually works for unsigned AND signed integers though the code only calls out unsigned.


Renders DeMorgan's Theorem moot!

Re: Flipping Out Over Nothin'

2005-05-13 16:46 • by Free

Today I did this:


showTheThingy |= true;


Not even drunk.

Re: Flipping Out Over Nothin'

2005-05-13 16:52 • by Bustaz Kool
34408 in reply to 34407
Free:

Not even drunk.



There's a cure for that...

Re: Flipping Out Over Nothin'

2005-05-13 17:03 • by MR. IDUNNOCNOMO
34409 in reply to 34408
unsigned int = QWORD? =  byte[0000]-byte[0000]-byte[0000]-byte[0000]?  ok not FFFF-FFFF-FFFF-FFFF but 0000-0000-0000-0000? I don't know I'm just like um macro? WTF?  WTH I got paid....

Re: Flipping Out Over Nothin'

2005-05-13 17:19 • by Nice Day
34410 in reply to 34405
Bustaz Kool:

Advantages to this code:


Allows for scalability - If the INTEGER size changes from 32 bit to, say, 33 bit, a single define allows the new hardware to be supported.



An integer in C would never have an odd number of bits - it used to generally be 16 bits, now it is usually 32 bits - it is always a power of two multiple of the basic data element (char in C)


PS: how come the CAPTCHA validation never works the first time round ?

Re: Flipping Out Over Nothin'

2005-05-13 18:19 • by Anonymoose
34411 in reply to 34399

Anonymous:
If it's x86, everyone (or at least everyone doing assembly) knows that XOR is the fastest way to zero out a register.  This is so common it's even done to set something to zero in unoptimized code.


It's not necessarily the fastest way on very late-model x86 architectures. The instruction decoder/scheduler might decide that "xor eax,eax" is dependent upon the result of a previous instruction which modifies eax (obviously it's not - but they might use the same logic for "xor ebx, eax", which is obviously dependent on eax). "mov eax, 0", or any other immediate load, on the other hand is obviously not dependent on any previous value of eax, so even though it's a more complex instruction to decode, it could conceivably be faster.


Basically, it's never a good idea to say that "Foo is the fastest way to do Bar on x86", because there's so much wackiness going on in the architecture from generation to generation.

Re: Flipping Out Over Nothin'

2005-05-13 18:28 • by fluffy
34412 in reply to 34386
Anonymous:

This guy is retarded in both cases, with case 1 being flip all bits to zero and case 2 being flip all bits to the opposite value. In either case, it could have been done in a single line of code:


In the case of  0 not being all zeros, this is true only if you will be compiling for a processor that is capable of have a 0 with 1 bits for parity or padding. This probably did not apply in this case--for it was submitted to this site.


case 0:


return 0x00000000;  //This will get rid of those wascally 1s.


case 1:


return bitfield ^ 0xFFFFFFFF;


^ is the bitwise XOR operator in C++, C, and C#.



Or just ~bitfield, which is size-independent and thus 64-bit clean.

Re: Flipping Out Over Nothin'

2005-05-13 18:50 • by Trev
34413 in reply to 34405
Bustaz Kool:

Allows for scalability - If the INTEGER
size changes from 32 bit to, say, 33 bit, a single define allows the
new hardware to be supported.





..except that on x86 machines (and probably others), shifting by 32
bits is a null operation.  C/C++ may be able to catch it in a
literal case, but otherwise I don't think it'll prevent you from doing
something stupid.

Re: Flipping Out Over Nothin'

2005-05-13 19:35 • by Mike
34414 in reply to 34413

At least genbit is a macro vs. a function.  You've got
to give him credit for that little stroke of efficiency.



Seriously though - you're making this stuff up right?  I mean yesterday
was the vbscript that generated html links and today we're circumventing simple
assignment.  This stuff can't be real...I hope...



Re: Flipping Out Over Nothin'

2005-05-13 19:56 • by Alex Feinman
Reminds me that in the good old days when every CPU cycle counted, the fastest way to zero a register was to XOR it with itself. It was both less cycles (2 or 3) and less bytes (1 byte) than assigning literal zero to it.

Re: Flipping Out Over Nothin'

2005-05-13 21:15 • by Alex Papadimoulis
34416 in reply to 34414

Anonymous:

Seriously though - you're making this stuff up right?  I mean yesterday was the vbscript that generated html links and today we're circumventing simple assignment.  This stuff can't be real...I hope...


Sadly, it is real -- really real (as in, not from message boards and whatnot).


Ever watch the JERRY SPRINGER show? It's kinda like that with programming. I've contributed a good 6 or 7 posts from a single place I worked at for less than two years. Multiply that by the number of readers and you have TDWTF :-)

Re: Flipping Out Over Nothin'

2005-05-13 21:24 • by Gary
34417 in reply to 34403
Wait a minute, there. I can certainly agree that if you are restricted
to working at the gate level, XOR would be slower, but if you are
working directly in, say, CMOS, could you not have something with
cross-wired P vs. N gates?  (I know that's not very clear, but I
can't draw a picture here.  I mean can you make an XOR directly in
transistors that is smaller, simpler, and faster than if you did it
using AND/OR primitives?)

Re: Flipping Out Over Nothin'

2005-05-13 23:47 • by derean
34418 in reply to 34416
the guy who wrote that was at one point training to be a police officer, nuff said...



and that genbit macro and most of those bitwise operations he copy
pasted from someone else's code and hacked at it until it did what he
"wanted"



Re: Flipping Out Over Nothin'

2005-05-14 05:00 • by Julien
34421 in reply to 34418
I think the really fastest way to tell the compiler what this function _really_ does is a preprocessor macro:



#define resetBits(x) 0



Or if you really want to explain what it does:



#defin resetBits(x) ((x) & 0)



And with a fool-proof comment:



#define resetBits(x) ((x) & 0) /* reset bits of x */

Re: Flipping Out Over Nothin'

2005-05-14 05:17 • by PO8
34422 in reply to 34383
Uh, not in this case.  First of all, the argument and result are
unsigned, so sign bits are irrelevant.  Second, padding would be
irrelevant here too, since only the non-padded bits would be returned
from the function.  No, every caller of this function should just
be replaced with an assignment of 0 (the compiler will do a nice job of
optimizing this, BTW) and the function and the programmer should be
discarded.

« PrevPage 1 | Page 2Next »

Add Comment