[9fans] fun and scary evil C code - Plan9

This is a discussion on [9fans] fun and scary evil C code - Plan9 ; I was amused by this: http://www.steike.com/code/useless/evil-c/ I particularly liked the "internalEndianMagic". I see this in some XML libs, as well as GMP and other open sourced code. http://unix.derkeiler.com/Newsgroups.../msg00198.html From: https://svn.r-project.org/R/trunk/sr...trio/trionan.c /* * Endian-agnostic indexing macro. * * The value of ...

+ Reply to Thread
Results 1 to 10 of 10

Thread: [9fans] fun and scary evil C code

  1. [9fans] fun and scary evil C code

    I was amused by this:
    http://www.steike.com/code/useless/evil-c/

    I particularly liked the "internalEndianMagic".

    I see this in some XML libs, as well as GMP and other open sourced code.

    http://unix.derkeiler.com/Newsgroups.../msg00198.html


    From:
    https://svn.r-project.org/R/trunk/sr...trio/trionan.c

    /*
    * Endian-agnostic indexing macro.
    *
    * The value of internalEndianMagic, when converted into a 64-bit
    * integer, becomes 0x0706050403020100 (we could have used a 64-bit
    * integer value instead of a double, but not all platforms supports
    * that type). The value is automatically encoded with the correct
    * endianess by the compiler, which means that we can support any
    * kind of endianess. The individual bytes are then used as an index
    * for the IEEE 754 bit-patterns and masks.
    */
    #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
    static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
    #endif

    pretty weird stuff.


  2. Re: [9fans] fun and scary evil C code

    > #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])

    this is actually done in /sys/src/9/port/devcons.c too:

    static uvlong uvorder = 0x0001020304050607ULL;

    static uchar*
    le2vlong(vlong *to, uchar *f)
    {
    uchar *t, *o;
    int i;

    t = (uchar*)to;
    o = (uchar*)&uvorder;
    for(i = 0; i < sizeof(vlong); i++)
    t[o[i]] = f[i];
    return f+sizeof(vlong);
    }

    static uchar*
    vlong2le(uchar *t, vlong from)
    {
    uchar *f, *o;
    int i;

    f = (uchar*)&from;
    o = (uchar*)&uvorder;
    for(i = 0; i < sizeof(vlong); i++)
    t[i] = f[o[i]];
    return t+sizeof(vlong);
    }

    presotto wrote the code but said he learned the trick from ken.

    there, of course, we have a real compiler and don't have to
    write uvlong constants as floating point numbers
    (wow that seems fragile).

    russ


  3. Re: [9fans] fun and scary evil C code

    Russ Cox wrote:
    >> #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])

    >
    > this is actually done in /sys/src/9/port/devcons.c too:
    >
    > static uvlong uvorder = 0x0001020304050607ULL;
    >
    > static uchar*
    > le2vlong(vlong *to, uchar *f)
    > {
    > uchar *t, *o;
    > int i;
    >
    > t = (uchar*)to;
    > o = (uchar*)&uvorder;
    > for(i = 0; i < sizeof(vlong); i++)
    > t[o[i]] = f[i];
    > return f+sizeof(vlong);
    > }
    >
    > static uchar*
    > vlong2le(uchar *t, vlong from)
    > {
    > uchar *f, *o;
    > int i;
    >
    > f = (uchar*)&from;
    > o = (uchar*)&uvorder;
    > for(i = 0; i < sizeof(vlong); i++)
    > t[i] = f[o[i]];
    > return t+sizeof(vlong);
    > }
    >
    > presotto wrote the code but said he learned the trick from ken.
    >
    > there, of course, we have a real compiler and don't have to
    > write uvlong constants as floating point numbers
    > (wow that seems fragile).
    >
    > russ


    Now THAT's something to be proud of. Especially without comments.


  4. Re: [9fans] fun and scary evil C code

    > > presotto wrote the code but said he learned the trick from ken.
    > >
    > > there, of course, we have a real compiler and don't have to
    > > write uvlong constants as floating point numbers
    > > (wow that seems fragile).
    > >
    > > russ

    >
    > Now THAT's something to be proud of. Especially without comments.


    which. writing the code or learning tricks from ken?



    - erik

  5. Re: [9fans] fun and scary evil C code

    > > #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)
    > ])
    >
    > this is actually done in /sys/src/9/port/devcons.c too:
    >
    > static uvlong uvorder = 0x0001020304050607ULL;
    >
    > static uchar*
    > le2vlong(vlong *to, uchar *f)
    > {
    > uchar *t, *o;
    > int i;
    >
    > t = (uchar*)to;
    > o = (uchar*)&uvorder;
    > for(i = 0; i < sizeof(vlong); i++)
    > t[o[i]] = f[i];
    > return f+sizeof(vlong);
    > }
    >
    > static uchar*
    > vlong2le(uchar *t, vlong from)
    > {
    > uchar *f, *o;
    > int i;
    >
    > f = (uchar*)&from;
    > o = (uchar*)&uvorder;
    > for(i = 0; i < sizeof(vlong); i++)
    > t[i] = f[o[i]];
    > return t+sizeof(vlong);
    > }
    >
    > presotto wrote the code but said he learned the trick from ken.
    >
    > there, of course, we have a real compiler and don't have to
    > write uvlong constants as floating point numbers
    > (wow that seems fragile).


    Most likely the TRIO_DOUBLE_INDEX macro came from some code
    from the pre-long-long days, when you had no other way to
    write down an 8 byte value in host endian order (even in a
    less than portable way).

  6. Re: [9fans] fun and scary evil C code

    > there, of course, we have a real compiler and don't have to
    > write uvlong constants as floating point numbers
    > (wow that seems fragile).


    Scarily: they're not:
    if you read on, that macro is for picking apart a double into bytes
    and vice-versa.
    (i.e. it's insanity is internally consistent).
    It's still ludicrous and fragile.

    As far as I can see,
    they're assuming that double is IEEE 754 and that you can
    rip apart such a representation on an random-endian machine
    and re-assemble it on an any other random-endian machine.

    Does C99 or any other C mandate the actual memory layout
    of floats and doubles or the exact conversion of constant
    representations?
    I'm fairly sure they somehow mandate IEEE 754 properties,
    but do they actually say that floats and doubles have to be stored
    exactly that way in 4 or 8 bytes?

    Even if we assume sizeof(double) == 8,
    what if my implementation is perverse and interleaves the exponent
    bits amongst the mantissa bits?
    Where is this disallowed in the standard(s)?

    DaveL




  7. Re: [9fans] fun and scary evil C code

    > As far as I can see,
    > they're assuming that double is IEEE 754 and that you can
    > rip apart such a representation on an random-endian machine
    > and re-assemble it on an any other random-endian machine.


    I lied.
    They're actually using that stuff to pick apart the (presumed IEEE 754)
    doubles into exponent, mantissa, ...

    My questions still stand ...

    Also, that file is such a tangled nest of ifdefs ...
    is anyone sure whether (and if so, when) that code is invoked?

    DaveL


  8. Re: [9fans] fun and scary evil C code

    > I lied.
    > They're actually using that stuff to pick apart the (presumed IEEE 754)
    > doubles into exponent, mantissa, ...
    >
    > My questions still stand ...
    >
    > Also, that file is such a tangled nest of ifdefs ...
    > is anyone sure whether (and if so, when) that code is invoked?


    interesting conflicts on the web. http://en.wikipedia.org/wiki/IEEE_754
    says c doesn't require ieee, http://home.datacomm.ch/t_wolf/tw/c/c9x_changes.html point #21.
    says it does.

    in any event, if ieee is used, i think the trick is safe.

    - erik

  9. Re: [9fans] fun and scary evil C code

    On Dec 20, 2007 12:51 AM, erik quanstrom wrote:
    > in any event, if ieee is used, i think the trick is safe.


    surely it depends crucially on the consistency of the decimal to float
    conversion?
    is that standard?

  10. Re: [9fans] fun and scary evil C code

    as long as the conversion you're after has an exact ieee representation,
    i can't see how two compliant implementations could come up with
    differing representations. (two different numbers can't have the same
    ieee representation, except -0 and +0.) the conversion process doesn't
    need any floating point itself and the only interpolation comes when
    numbers don't have exact representations.

    it didn't occur to me immediately after russ' post that what he said
    was literally correct:

    #include
    #include

    #define Magici(x) (((uchar*)&magic)[7-(x)])
    static double magic = 7.949928895127363e-275;

    void
    main(void)
    {
    uint sign, exp;
    uvlong sig, *v;

    v = (uvlong*)&magic;
    sign = *v>>63;
    exp = *v>>52;
    sig = *v&~(4096-1LL<<52);
    print("%b*%b*%ullx\n", sign, exp, sig);
    print("%ullx\n", *v);
    }

    - erik

+ Reply to Thread