Vector from hell



  • I was amused by the alternate universe check:

    assert(value == value);

    But I died a little when I saw the insert into this so-called map (its a vector):

    object->GetMap()->push_back(std::make_pair(std::make_pair(std::make_pair(conflictObject, subConflictID),std::make_pair(object, subObjectID)),To_dB(value)));



  • In some languages there actually are values that doesn't compare equal to themself.

    For example, NaN is not equal to anything.



  • This is C++. Operator== can be overloaded, meaning that value == value may very well NOT return true. It would be a wtf if it didn't, though...

    Nice replacement of a structure though. Heck, who needs a structure anyways?



  •  Yup, that looks very much like someone who was too lazy to make a struct. Though, I admit, the way he did it is pretty unique.



  •  @Evo said:

    This is C++. Operator== can be overloaded, meaning that value == value may very well NOT return true.

    Good point. I should have mentioned that "value" is of type float. 



  • @noitcif said:

    I should have mentioned that "value" is of type float. 

    So the assert may return true if the actual values are being compared to each other and are the same, or it's comparing references; or it might return false if the floating-point values are of sufficiently large precision to not actually be equivalent. In other words, it's about as useful and reliable as a Windows service that shows a modal dialog box.

    Also, make_pair > structs apparently.



  • @PSWorx said:

     Yup, that looks very much like someone who was too lazy to make a struct. Though, I admit, the way he did it is pretty unique.

    It is pretty ingenious in a twisted way, like the programmer was trying to prove a theorem in comp. sci. stating that you can represent any conceivable data structure using only scalars and std::pairs.




  • @noitcif said:

    assert(value == value);

    If the computer's overclocked, it could fail on that. YOU NEVER KNOW!



  •  Or if value is volatile.  Nothing guarantees that two successive reads will return the same value.



  • @blakeyrat said:

    @noitcif said:
    assert(value == value);

    If the computer's overclocked, it could fail on that. YOU NEVER KNOW!

     

    @Cat said:

     Or if value is volatile.  Nothing guarantees that two successive reads will return the same value.

     

    Don't forget about solar flares

     



  • x == x can be false for floats if x is Nan.


  • BINNED

    I'm not too sure but if I remember correctly depending on compiler settings x == x could theoretically be false even if x is not a NaN. That's because values stored in the x87 registers have higher precision than values stored in memory.

    Though this seems to be quite unlikely and would be a compiler fuckup IMO.



  •  henke37 is right, the assert is not a WTF; it is asserting that value is not NaN.  It would be clearer to use isnan(3), but inequality-with-self is a well-defined test that is widely understood among competent programmers.

     The pair thing is a bit silly though.  It's 2011, long past time to upgrade to a modern compiler that provides std::tuple.



  • @Iago said:

     henke37 is right, the assert is not a WTF; it is asserting that value is not NaN.  It would be clearer to use isnan(3), but inequality-with-self is a well-defined test that is widely understood among competent programmers.

    I have this in one of my libraries:

    // w is always non-negative
    if(!(w+w>w) && w!=0)
    {
      // Do some common stuff for NaN and inf
      if(!(w>=0))
        // It's a NaN
      else
        // It's an inf
    }

  • Discourse touched me in a no-no place

    @tdb said:

    if(!(w+w>w) && w!=0)
    What happens for (INT_MAX/2) <= w <=INT_MAX



  • @PJH said:

    @tdb said:
    if(!(w+w>w) && w!=0)
    What happens for (INT_MAX/2) <= w <=INT_MAX

    I could've clarified that w has a floating-point type, even though we were talking about NaNs (which, to my knowledge, do not exist for integers on any modern architecture). Thus, the overflow-into-negative problem does not exist.



  • Any code that does something else than it appears to do at first sight, should be taken out of the country, and put on a flight to Guantanamo Bay, where it is to be treated as the treacherous son-of-a-b*tch terrorist that it is. If we allow this code, the terrorists have already won!

    But, seriously, I think that code that cannot be understood by less competent programmers (where competent seems to mean: knowing all the dirty tricks to make code unreadable) is not good code, especially when replacing it with readable code has no performance penalty at all.

    The other stuff is just the effect of using too much STL for too much time. Try something saner, such as Boost.



  • @noitcif said:

    object->GetMap()->push_back(std::make_pair(std::make_pair(std::make_pair(conflictObject, subConflictID),std::make_pair(object, subObjectID)),To_dB(value)));

     

    Can't you see the hidden binary tree? It's obviously optimized for speed!

    Filed under: cons car cdr



  • @DaveK said:

    @PSWorx said:

     Yup, that looks very much like someone who was too lazy to make a struct. Though, I admit, the way he did it is pretty unique.

    It is pretty ingenious in a twisted way, like the programmer was trying to prove a theorem in comp. sci. stating that you can represent any conceivable data structure using only scalars and std::pairs.

     

    It would be almost trival to show that std::pairs + scalars can be used to build a binary tree. Anything more complicated, however, like a graph (n.b. a binary tree is a special case of a graph) might not be possible.



  • @TGV said:

    But, seriously, I think that code that cannot be understood by less competent programmers (where competent seems to mean: knowing all the dirty tricks to make code unreadable) is not good code, especially when replacing it with readable code has no performance penalty at all.

     

    Agreed. Plus it is a debug assert so performance shouldn't be a factor.  The author spent the last several years developing this code base, and it gets much worse than these two examples.  I can think of two reasons. 1. He intentionally did this for job security. If this is the case he failed, because he was recently reassigned and I inherited it.  2. He is a bad programmer.



  • This famously lead to a security hole (reverse denial of service) in PHP recently; it tried to perform a deterministic operation twice and compare the results, and went into an infinite loop because the (non-NaN) results didn't compare equal.

    I would be more sympathetic to them, except that the code in question was copied from somewhere else and specifically had a comment above it saying that it didn't work correctly on x87.

    (Incidentally, although C89 allows this sort of shenanigans, C99 specifically says compilers have to make sure that doesn't happen. gcc will happily let x87 screw around with your floating-point calculations in C89 mode but not C99 mode for that reason. I imagine most languages other than C likewise enforce that floating point numbers lose excess precision before being compared.)



  • @esoterik said:

    @DaveK said:

    @PSWorx said:

     Yup, that looks very much like someone who was too lazy to make a struct. Though, I admit, the way he did it is pretty unique.

    It is pretty ingenious in a twisted way, like the programmer was trying to prove a theorem in comp. sci. stating that you can represent any conceivable data structure using only scalars and std::pairs.

     

    It would be almost trival to show that std::pairs + scalars can be used to build a binary tree. Anything more complicated, however, like a graph (n.b. a binary tree is a special case of a graph) might not be possible.

    No, seriously, you can represent anything this way.  It's basically just a singly-linked list of data-struct members.  It doesn't have to model a tree or graph directly, just the data structs that you'd use to represent your tree or graph or whatever; I was assuming you're allowed more than one of these nested-pair monstrosities in existence.  And even if not.. I mean, you can always find a flattened representation of anything, after all when it's stored in memory it's just a linear sequence of bytes, no matter what; in extremis, you could represent any such struct by using nested-pairs with a single byte stored as the data item in each one and explicitly represent the memory layout of whatever struct you wanted to model yourself.




  • @The_Assimilator said:

    it might return false if the floating-point values are of sufficiently large precision to not actually be equivalent

    The value is so precise, it is not even equal to itself...



  • No, seriously, you can represent anything this way. ...
     

    Correct - this has been proved nearly 50 years ago, when any data structure would have been done with Lisp's CONS cells... lists, double-linked lists, trees, even graphs ...



  • @topspin said:

    I'm not too sure but if I remember correctly depending on compiler settings x == x could theoretically be false even if x is not a NaN. That's because values stored in the x87 registers have higher precision than values stored in memory.

    Though this seems to be quite unlikely and would be a compiler fuckup IMO.

    Stupid tricks like this is why I hate C and C++; programming should be intuitive, and almost every snippet of C code I see breaks that rule. If you really want to write shit like that, at least put it in a macro called ISNAN or something similar, so people actually understand what the code's intended to do.

    @DaveK said:

    No, seriously, you can represent anything this way.  It's basically just a singly-linked list of data-struct members.  It doesn't have to model a tree or graph directly, just the data structs that you'd use to represent your tree or graph or whatever; I was assuming you're allowed more than one of these nested-pair monstrosities in existence.  And even if not.. I mean, you can always find a flattened representation of anything, after all when it's stored in memory it's just a linear sequence of bytes, no matter what; in extremis, you could represent any such struct by using nested-pairs with a single byte stored as the data item in each one and explicitly represent the memory layout of whatever struct you wanted to model yourself.

    assert(can != should);



  • @The_Assimilator said:

    Stupid tricks like this is why I hate C and C++; programming should be intuitive, and almost every snippet of C code I see breaks that rule. If you really want to write shit like that, at least put it in a macro called ISNAN or something similar, so people actually understand what the code's intended to do.

    C99 has a standard isnan macro, but alas, C99 adoption isn't universal yet.



  • I'm currently working on a cross-platform C++ application, and I've had plenty of trouble with consistency of isnan(), what header it's defined in and whether it's in the std:: namespace or the global level. So I can understand doing things this way, which should behave consistently across all compilers even if it isn't very well-explaned.

    That said, I'm a big fan of verbose asserts, eg.

      assert(value == value && "value must not be NaN");

    This has the same effect as the original but conveys the intent of the assert, both in the source code and if the assert happens to get triggered.

    Dan.


Log in to reply