• Anonymous (unregistered)

    Wow....

    bitfield = 0;

    Anyone? Bueller?

  • Brian (unregistered)

    This is the stupidest thing I have ever seen.

  • Anonymous (unregistered)

    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).

  • (cs)

    WITFF?

     

    Essentially, create a function that does this:


    <FONT color=#000099>unsigned int</FONT> resetBits(<FONT color=#000099>unsigned int</FONT> bitfield)
    {
      <FONT color=#000099>return</FONT> 0;
    }

     

     

  • (cs) in reply to Anonymous

    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 :)

  • (cs)

    I don't know C++ well enough, what do the first line and the tilde (~) do?

  • (cs)

    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.

  • Robin Lavall&#233;e (unregistered) in reply to Mike R

    If you use a decent compiler, it will be optimized to the same instruction(s) for your platform.

  • (cs)

    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.

  • (cs)

    Very, very hard to believe this one is real.
    It would be interesting to see how various optimizers handle this code.

  • (cs) in reply to Manni

    NOT / flips the bit

  • (cs) in reply to Sweets
    Sweets:
    NOT / flips the bit


    that was in response to Manni
  • (cs)

    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!

     

  • (cs) in reply to Sweets

    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.

  • Brian (unregistered)

    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

  • (cs) in reply to 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?

  • cdog (unregistered) in reply to Manni
    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.
  • Brent Railey (unregistered) in reply to Manni

    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#.

  • (cs) in reply to Manni
    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.

  • diaphanein (unregistered) in reply to Brian
    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.

  • (cs) in reply to Sweets
    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<<X bit<br x(index) the to over shifts which ,> 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.

  • Matt B (unregistered) in reply to Sweets

    Sadly, the first thing that came to my head was:

    return bitfield & 0

  • (cs) in reply to Sweets

    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.

  • (cs) in reply to diaphanein
    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.

     

     

  • (cs) in reply to Apoch
    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

  • Anonymous (unregistered) in reply to Mike R
    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.

     

  • Ifeanyi Echeruo (unregistered) in reply to Brian

    But we can all agree that

    unsigned long int i = 0;

    will be 32 bits worth of zeros;

  • (cs) in reply to Anonymous
    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.

  • (cs) in reply to Ifeanyi Echeruo
    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....

  • (cs) in reply to Ifeanyi Echeruo
    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.
  • Grant (unregistered) in reply to Mike R
    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.

  • (cs) in reply to Anonymous
    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.

  • (cs)

    That code would be horrible in anything time critical! He should really use Duff's Device to unroll that loop:

    <font size="1">unsigned int resetBits(unsigned int bitfield)</font>
    <font size="1">{</font>
    <font size="1">    unsigned int n=(NUMBITS+7)/8;</font>
    <font size="1">    unsigned int index=0;</font>
    <font size="1">    unsigned int flag;</font>
    <font size="1">    switch (index % 8)
        {</font>
    <font size="1">        case 0: do{ flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 7:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 6:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 5:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 4:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 3:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 2:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">        case 1:     flag=GENBIT(index++);flag=~flag;bitfield=bitfield&flag;</font>
    <font size="1">                  } while (--n>0);</font>
    <font size="1">    }</font>
    <font size="1">    return bitfield;</font>
    <font size="1">}</font>
  • diaphanein (unregistered) in reply to CornedBee
    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.

  • Newbie (unregistered)

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

     

    What a dumbass!

  • (cs)

    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!

  • (cs)

    Today I did this:

    showTheThingy |= true;

    Not even drunk.

  • (cs) in reply to Free
    Free:

    Not even drunk.

    There's a cure for that...

  • MR. IDUNNOCNOMO (unregistered) in reply to Bustaz Kool

    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....

  • Nice Day (unregistered) in reply to Bustaz Kool
    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 ?

  • Anonymoose (unregistered) in reply to Grant

    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.

  • (cs) in reply to Brent Railey
    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.

  • Trev (unregistered) in reply to Bustaz Kool
    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.
  • Mike (unregistered) in reply to Trev

    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...

  • Alex Feinman (unregistered)

    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.

  • (cs) in reply to Mike

    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 :-)

  • Gary (unregistered) in reply to diaphanein

    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?)

  • derean (unregistered) in reply to Alex Papadimoulis

    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"

  • Julien (unregistered) in reply to derean

    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 */

  • PO8 (unregistered) in reply to Brian

    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.

Leave a comment on “Flipping Out Over Nothin'”

Log In or post as a guest

Replying to comment #:

« Return to Article