• Daniel Persson (unregistered)

    Actually, when comparing the assembler output from gcc with optimization those lines of code produce the same output as the "else-if" version.

    However, the "switch-case-version", gets worse.

  • (cs) in reply to Alan
    Alan:
    Pfft. You C guys and your silly switch statements. All we really need is a map!
    types = {
        7: 4,
        9: 6,
        11: 9,
    }
    

    if baseType not in types: return None

    return types[baseType]

    Python FTW!

    (of course it'd be better to avoid the magic numbers altogether, but we don't seem to have that luxury here)

    What if mainType (your baseType) is not defined in the map? Whoops! Your clever solution failed. Maybe the original coder came from a python background.

  • lesle (unregistered) in reply to the beholder
    the beholder:
    frits:
    If mainType is 7, 9 AND 11 your screwed anyway because you either have major thread sync issues, or you have landed in an alternate universe.
    No, he's just using Schrodinger's integers.
    Beholder: your comment made me laugh out loud. Thanks!
  • zeno (unregistered) in reply to z

    We all know here that the best way to write that code was something along the lines of an asm block calculating the offset to jump to by using maintype and cleverly placing the code to execute at the proper place, thus making any execution only take 2 branches, ala: __asm { offset = 11 - mainType; jump to here + offset + 1; subType = 9; // offset 0 (11 - 11) jump to OUT; subType = 6; // offset 2 (11 - 9) jump to OUT; subType = 4; // offset 4 (11 - 7) OUT: }; QED;

  • Steve the Cynic (unregistered) in reply to Nicolai Jørgensen
    Nicolai Jørgensen:
    Actually, the professor is right about the NAND gates (and the poster should have paid more attention in class).

    It IS the most basic 2-input-gate to use and all other gates are designed from NAND-gates (using only 4 transistors) and then the redundant transistors are removed for optimization.

    Even an AND-gate is just a NAND-gate with and inverter (2 transistors) in any processor design you'll find.

    Check this wiki for further info: http://en.wikipedia.org/wiki/NAND_logic

    Be careful about what you read, and remember that maxim about a little knowledge. CMOS gates don't follow this rule; a CMOS NAND is four transistors, as is a NOR, but so are AND and OR, provided you arrange them correctly.

  • Wade (unregistered)

    I have to deal with a lot of this kind of thing:

    subType = (mainType == 7 || mainType == 9) ? (mainType - 3) : (mainType == 11) ? (mainType - 2) : mainType;

  • Ahruman (unregistered) in reply to Consultuning
    Consultuning:
    if( mainType > 6 && mainType < 12) {
        subType = mainType - 3 ;
        if( subType == 8 )
            ++subType;
    }
    
    This is in my mind way more legible and does exactly the same. Or I'm completely confused?
    Two ifs? How abhorrently sloppy. Won’t someone _please_ think of the branch predictors!
    const int LUT[16] = { 16, 16, 16, 16, 16, 16, 16, 4, 16, 6, 16, 9, 16, 16, 16, 16 };
    int val = LUT[mainType & 15];
    int isRemapped = !(mainType &~ 15) &~ (val >> 4);
    subType = subType & isRemapped - 1 | val & isRemapped * 15;
  • JohnFx (unregistered)

    (To a backdrop of country music)

    I was clever....when clever wasn't coooool.

  • (cs)

    this should have been:

    do { blablabla-with-some-breaks; } while (false);

    which does not require the extraneous "break", and works as expected. Actually this is widely used.

  • gerard (unregistered)

    Isn't the real WTF that this code even exists? Granted we don't know the meaning of mainType and subType, but if subType is slaved to mainType, at least in these few instances, why even bother with the extra variable? If you want to check that subType=4, why not just check that mainType==7 without all this witchcraft?

  • RandomNameOfHiding (unregistered)

    I personally like:

    int tmp = ((mainType - 1) / 2); if (tmp >= 3 and tmp <= 5) { subType = mainType - (3 - ((int) (tmp - 3) / 2)); }

  • bury (unregistered)

    subType = {7: 4, 9: 6, 11: 9, }[mainType]

  • Ajonos (unregistered) in reply to frits

    Or mainType could be of a user-defined type with a custom == operator. I mean, isn't that obvious?

  • bramster (unregistered)

    The original coder was Billy Ray Cyrus.

    Hit him with a switch, in case he tries it again. . . else we'll have to keep putting up with broken code at the heart of the routine.

  • ath (unregistered)

    You guys know nothing about C++. You don't need a fractured space-time continuum to get x == 7 AND x == 9.

    class MainType
    {
    bool operator==(int y) const { return y == 7 || y == 9;}
    };
    
    x = MainType();
    x == 6; // False
    x == 7; // True
    x == 9; // True
    

    Thanks C++ for saving the universe!

  • Anonymous Coward (unregistered) in reply to Nicolai Jørgensen
    Nicolai Jørgensen:
    Actually, the professor is right about the NAND gates (and the poster should have paid more attention in class).

    It IS the most basic 2-input-gate to use and all other gates are designed from NAND-gates (using only 4 transistors) and then the redundant transistors are removed for optimization.

    Even an AND-gate is just a NAND-gate with and inverter (2 transistors) in any processor design you'll find.

    Check this wiki for further info: http://en.wikipedia.org/wiki/NAND_logic

    The post didn't say anything about disagreeing with the professor...

  • Hanky (unregistered) in reply to frits
    frits:
    If mainType is 7, 9 AND 11 your screwed anyway because you either have major thread sync issues, or you have landed in an alternate universe.
    class AlternateUniverse {
      public:
        int foo;
        AlternateUniverse(n) : foo(n) {}
        bool operator==(const int other) {
          return other == 7 || other == 9 || other == 11;
        }
    };
    
    AlternateUniverse mainType(3);
    
  • (cs) in reply to po8crg

    C# case statements don't fall through. You must have a flow control statement at the end of each case. See the C# 3.0 language specification §8.7.2.

  • (cs) in reply to ath
    ath:
    You guys know nothing about C++. You don't need a fractured space-time continuum to get x == 7 AND x == 9.
    class MainType
    {
    bool operator==(int y) const { return y == 7 || y == 9;}
    };
    
    x = MainType();
    x == 6; // False
    x == 7; // True
    x == 9; // True
    

    Thanks C++ for saving the universe!

    People who write code like this should be relegated to work on unimportant, single-programmer, write-only projects.
  • blaz (unregistered) in reply to Sir Twist
    Sir Twist:
    C# case statements don't fall through. You must have a flow control statement at the end of each case. See the C# 3.0 language specification §8.7.2.

    I'm glad someone else noticed this WTFy comment.

    Actually C# case statements do fall through if they have nothing in them, which is handy. IMO C# has perfect switch statements.

  • Aris (unregistered) in reply to frits
    frits:
    ath:
    You guys know nothing about C++. You don't need a fractured space-time continuum to get x == 7 AND x == 9.
    class MainType
    {
    bool operator==(int y) const { return y == 7 || y == 9;}
    };
    
    x = MainType();
    x == 6; // False
    x == 7; // True
    x == 9; // True
    

    Thanks C++ for saving the universe!

    People who write code like this should be relegated to work on unimportant, single-programmer, write-only projects.
    Hell no, I'd prefer to keep them far of my code. Promote them as team managers or project leaders instead
  • EatenByAGrue (unregistered) in reply to frits
    frits:
    Alan:
    Pfft. You C guys and your silly switch statements. All we really need is a map!
    types = {
        7: 4,
        9: 6,
        11: 9,
    }
    

    if baseType not in types: return None

    return types[baseType]

    Python FTW!

    (of course it'd be better to avoid the magic numbers altogether, but we don't seem to have that luxury here)

    What if mainType (your baseType) is not defined in the map? Whoops! Your clever solution failed. Maybe the original coder came from a python background.

    He handled that case with "if baseType not in types ...".

  • True that (unregistered) in reply to lesle
    lesle:
    the beholder:
    frits:
    If mainType is 7, 9 AND 11 your screwed anyway because you either have major thread sync issues, or you have landed in an alternate universe.
    No, he's just using Schrodinger's integers.
    Beholder: your comment made me laugh out loud. Thanks!
    +1 for the cat
  • Spoe (unregistered)

    Why not:

    tmp = 0xF;
    switch (mainType) {
        case 7:
            tmp ^= 0x2;
        case 9:
            tmp ^= 0xF;
        case 11:
            subType = tmp ^ 0x6;
            break;
    }
  • Andrea D'Alessandro (unregistered)

    I disagree ! It's a explicit application of the Bohm-Jacopini theorem, that say that any program can be constructed with only two formation rules (IF and WHILE).

    See http://en.wikipedia.org/wiki/Bohm-Jacopini_theorem

  • (cs) in reply to EatenByAGrue
    EatenByAGrue:
    frits:
    Alan:
    Pfft. You C guys and your silly switch statements. All we really need is a map!
    types = {
        7: 4,
        9: 6,
        11: 9,
    }
    

    if baseType not in types: return None

    return types[baseType]

    Python FTW!

    (of course it'd be better to avoid the magic numbers altogether, but we don't seem to have that luxury here)

    What if mainType (your baseType) is not defined in the map? Whoops! Your clever solution failed. Maybe the original coder came from a python background.

    He handled that case with "if baseType not in types ...".

    Oh, I see.

  • Bim Job (unregistered) in reply to ath
    ath:
    You guys know nothing about C++. You don't need a fractured space-time continuum to get x == 7 AND x == 9.
    class MainType
    {
    bool operator==(int y) const { return y == 7 || y == 9;}
    };
    
    x = MainType();
    x == 6; // False
    x == 7; // True
    x == 9; // True
    

    Thanks C++ for saving the universe!

    Strictly speaking, that would be x == 7 OR x == 9.

    Funny how those built-in C++ operators work.

  • Spoe (unregistered) in reply to Bim Job

    Ah, but (x == 7 && x == 9) would evaluate to true.

  • Seminymous Coward (unregistered) in reply to alvieboy
    alvieboy:
    this should have been:

    do { blablabla-with-some-breaks; } while (false);

    which does not require the extraneous "break", and works as expected. Actually this is widely used.

    do { blablabla-with-some-breaks; } while (false); is a terrible way to write { blablabla-with-some-breaks; } .

  • mruffalo (unregistered) in reply to Steve the Cynic

    CMOS AND and OR gates may be the same number of transistors, but they're totally unsuitable for digital logic applications.

    NMOS transistors pass strong 0s and weak 1s (PMOS is the opposite), so with static CMOS gates, you always have NMOS connected to ground and PMOS connected to Vdd (+5V).

    If you have a non-inverting CMOS gate, your signal is degraded by the threshold voltage (usually 0.7V) and you'll have to pass it through a buffer (two inverters) to recover a strong signal.

  • Jerkface (unregistered)

    Anything to make a turd.

  • JimmyMcJimbo (unregistered)

    bool breakout = false; bool loopstarted = false; setbreakout: breakout = true; if (loopstarted) goto inloop; startloop: loopstarted = true; breakout = false; while(!breakout) { if(mainType == 7) { subType = 4; goto setbreakout; }

    if(mainType == 9)
    {
        subType = 6;
        goto setbreakout;
    }
    
    if(mainType == 11)
    {
        subType = 9;
        goto setbreakout;
    }
    
    inloop:
    

    }

    captcha - haero: Me for making such awesome improvements to some already awesome code!

  • (cs)

    Or maybe even a switch statement.

  • (cs) in reply to apaq11

    They were cheaper because the typical AND gate was actually a NAND gate which fed both inputs of a second NAND gate to invert the output.

    I also recall converting circuits into all NORs also.

  • Jay (unregistered) in reply to halcyon1234
    halcyon1234:
    Else if and switch sound good, but what are you going to do when mainType == 7 AND mainType == 9, huh?

    Good point. Clearly the correct solution is:

    if(mainType == 7) 
      subType = 4; 
    if(mainType!=7 && mainType == 9) 
      subType = 6; 
    if(mainType!=7 && mainType!=9 && mainType == 11) 
      subType = 9; 
    

    Actually, I see a lot of code like that every day. I just saw a program the other day filled with statements of the form:

    if (value!=null && !value.equals("") && value.equals("X"))
    

    i.e. they repeatedly checked that the value was not an empty string before comparing it to the string they actually wanted. Just in case, I suppose, it might be both "" and "X" at the same time.

  • (cs) in reply to gerard

    because you only see a small snippet here.

    what if

    crap code that sets subType, based on mainType; . . . more crap code that modifies mainType; . . . even more crap code that examines subType (no guarantee that mainType is even remotely related to subType here);

  • (cs) in reply to Anonymous

    "a profession where proper understanding is the exception" - I've just been waiting for the chance to use the word 'oxymoron' and I think this might be it!

  • Bim Job (unregistered) in reply to Spoe
    Spoe:
    Ah, but (x == 7 && x == 9) would evaluate to true.
    Splendid. Sarcasm PLUS proof that it's funny how those built-in C++ operators work.

    The definition of the PLUS operator is an exercise left to the reader.

  • me (unregistered)
    subType = (mainType == 11) ? 9 : (mainType - 3) ;

    But that does not explain why 9 is a subtype of 11.

  • Thg (unregistered) in reply to Consultuning
    Consultuning:
    [ ... ] the whole thing can be reduced to
    subType = mainType - 3 ;
    if( subType == 8 )
        ++subType;
    
    True, the original code does not alter the value of the subType if mainType is outside the 7,9,11 range. [ ... ]

    This is awesome.

    Compromise solution:

    switch (mainType) 
    {
      int offset = -3;
      
      case 8:
        offset = -2;
      case 7: 
      case 9: 
      case 10: 
      case 11: 
        subType = mainType - offset ;
      default:
        break;
    }
    
  • Crabs (unregistered)

    So, I've never seen something this ridiculous, but I've heard that in some government run software projects, removing code takes more paperwork than writing new code. So maybe, just maybe, this guy just didn't want to fill out the "removing while loop" form.

  • Thg (unregistered) in reply to Thg

    Argh, self .. FAIL!

    subType = mainType + offset;

    Thg:

    Compromise solution:

    switch (mainType) 
    {
      int offset = -3;
        case 8:
        offset = -2;
      case 7: 
      case 9: 
      case 10: 
      case 11: 
        subType = mainType - offset ;
      default:
        break;
    }
    
  • noway! (unregistered)

    Reminds me of when i poked around in the source code of VICE and found that in a lot of places they had wrapped code in:

    do { /*code here*/ } while (0);

    when probably only the curly thingies would be enough...

    (2nd try)

  • Oxyd (unregistered)
    #include <iostream>
    #include <map>
    #include <utility>
    #include <string>
    
    int main() {
      class _ {
        typedef std::map< int, std::pair< std::string, bool > > M;
        typedef int dynamic;
        M m; M::iterator it;
      public:
        _() {
          m[4] = std::make_pair(std::string("\n"), false);
          m[5] = std::make_pair(std::string("to "), false);
          m[6] = std::make_pair(std::string("us."), false);
          m[7] = std::make_pair(std::string("All "), false);
          m[8] = std::make_pair(std::string("your "), false);
          m[9] = std::make_pair(std::string("base "), false);
          m[10] = std::make_pair(std::string("is "), false);
          m[11] = std::make_pair(std::string("belong "), true);
        }
    
        ~_() {
          static dynamic dynamo = false;
          if (it != m.end() && !dynamo)
            std::cout << it ---> second.first;
          dynamo = true;
        }
    
        bool operator == (int x) {
          M::iterator a = m.find(x);
          M::iterator b = m.find(++x);
    
          a != m.end() && std::cout << a ---> second.first;
          b != m.end() && std::cout << b ---> second.first;
    
          it = --b;
    
          return
            (a != m.end() ? a->second.second : true)
            || (b != m.end() ? b->second.second : true);
        }
    
        void operator = (int x) {
          operator == (x - 4);
        }
      } mainType, subType;
    
      while (true) {
        if (mainType == 7) {
          subType = 4;
          break;
        }
        if (mainType == 9) {
          subType = 6;
          break;
        }
        if (mainType == 11) {
          subType = 9;
          break;
        }
        break;
      }
    }

    I can see nothing wrong with that code.

  • unknown (unregistered)

    with all the talk of switch and if.. else, a simpler solution has been ignored, the goto of course

    if(mainType == 7) { subType = 4; goto end; }

    if(mainType == 9)
    {
        subType = 6;
        goto end;
    }
    
    if(mainType == 11)
    {
        subType = 9;
        goto end;
    }
    

    end:

  • joe (unregistered)

    subType = (int)(0.125 * mainType * mainType - mainType + 4.875)

  • (cs) in reply to noway!

    If this code:

    do { /code here/ } while (0);

    was used in a #define, than considering the while(0) to be boilerplate doesn't bother me. Easier than trying to remember the rules of when you do and do not need it.

    It was inlined code ... then maybe someone just had a finger-macro set up they couldn't ignore.

  • ctw (unregistered)

    Okay, sure, it's not super elegant. But it works just as well as a case statement, even if it causes a more severe double-take. This is not Worse Than Failure - it's not even Failure. This is Shoddy Success.

    Yes, there are other ways to do it. Turing-completeness is like that. Deal.

  • pet (unregistered) in reply to Anon

    Yes, everything is different in Russia, err... in embedded. MISRA has guidelines for embedded code which forbid use of goto. So guys work around about it, as accidentally explained today in a blog http://embeddedgurus.net/stack-overflow/2010/02/goto-heresy.html

  • Buddy (unregistered) in reply to joe
    joe:
    subType = (int)(0.125 * mainType * mainType - mainType + 4.875)

    Within integer domain:

    subType = (mainType * mainType - mainType * 8 + 39) / 8;

    And smart compilers will know to use shifts for * 8 and / 8.

Leave a comment on “Else... where?”

Log In or post as a guest

Replying to comment #:

« Return to Article