Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: Inline::C producing an absurd result

by BrowserUk (Patriarch)
on May 08, 2017 at 10:55 UTC ( [id://1189793]=note: print w/replies, xml ) Need Help??


in reply to Inline::C producing an absurd result

My only suggestion is that you dump the values as bits and see where they differ. It might be easier to pass the values back to perl so that you can use unpack.

Of course, that would probably mean assigning your D64 constants to variables, and that might change things.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
  • Comment on Re: Inline::C producing an absurd result

Replies are listed 'Best First'.
Re^2: Inline::C producing an absurd result
by pryrt (Abbot) on May 08, 2017 at 13:49 UTC

    syphilis, I see the same problem with strawberry perl 5.24.1 for MSWin32-x64 with gcc 4.9.2, so I added a function in the c to dump the bytes (I didn't want the bytes leaving the c-environment, just in case trying to follow BrowserUK's unpack advice introduced a translation error (as he said, "might change things"):

    ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// // https://perlmonks.org/?node_id=1189780 ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <string.h> void _dump64(char* varname, _Decimal64 d64) { int i; void* ptr = (void*)(&d64); printf("%s = 0x", varname); for(i=0; i < sizeof(d64); i++) { printf("%02X ", 0xFF & *(char*)(ptr+i)); } printf("\n"); } #define dump64(v) _dump64(#v, v) int foo(void) { _Decimal64 pz64 = 0.DD, nz64 = 0.DD, no64 = -1.DD; nz64 = pz64 * no64; dump64(pz64); dump64(nz64); dump64(no64); if(nz64 != 0.DD) printf("!= +0\n"); else printf("== +0\n"); if(nz64 != -0.DD) printf("!= -0\n"); else printf("== -0\n"); return 0; } int main(int argc, char* argv) { foo(); } ----------------------------------------- pz64 = 0x00 00 00 00 00 00 C0 31 nz64 = 0x00 00 00 00 00 00 C0 B1 no64 = 0x01 00 00 00 00 00 C0 B1 == +0 == -0

    When I converted that to perl, and run using Inline::C 0.76, I get

    pz64 = 0x00 00 00 00 00 00 C0 31 nz64 = 0x00 00 00 00 00 00 C0 B1 no64 = 0x01 00 00 00 00 00 C0 B1 != +0 == -0

    That's definitely a strange one: inside C, the bits are the same, but the comparison-behavior is different.

    I see a lot of compiler options during the make- and make-install stages, and I'm wondering if one of them is messing up (intentionally modifying?) gcc behavior. What I would probably do next (if it were a problem I had to solve -- or if I had more time to spend on it today for my own education, but unfortunately, $work beckons for now): start making your pure-c compile look more like the Inline::C compile, adding more of the options, until such time as the pure-c failed...

    Let us know if you find anything more...

      I see a lot of compiler options during the make- and make-install stages, and I'm wondering if one of them is messing up (intentionally modifying?) gcc behaviour

      Yes, as Anonymous Monk has subsequently confirmed, that's precisely what's happening (in the form of the optimization option).

      Cheers,
      Rob
Re^2: Inline::C producing an absurd result
by syphilis (Archbishop) on May 08, 2017 at 13:19 UTC
    My only suggestion is that you dump the values as bits and see where they differ

    Definitely worth a try, but it appears not to have helped much.
    So .... I changed the original Inline::C script to:
    use strict; use warnings; use Inline C => Config => BUILD_NOISY => 1, USING => 'ParseRegExp', #CLEAN_AFTER_BUILD => 0, ; use Inline C => <<'EOC'; #include <stdio.h> int foo(void) { _Decimal64 d64 = 0.DD, neg_zero, pos_zero = 0.DD; void *pd64 = &d64, *pneg_zero = &neg_zero, *ppos_zero = &pos_zero; int i; neg_zero = pos_zero * -1.DD; d64 *= -1.DD; if(d64 != pos_zero) printf("!= 0\n"); else printf("== 0\n"); if(d64 != neg_zero) printf("!= -0\n"); else printf("== -0\n"); for(i = 7; i >= 0; i--) printf("%02X", ((unsigned char*)pd64)[i]); printf("\n"); for(i = 7; i >= 0; i--) printf("%02X", ((unsigned char*)pneg_zero)[i]); printf("\n"); for(i = 7; i >= 0; i--) printf("%02X", ((unsigned char*)ppos_zero)[i]); printf("\n"); return 0; } EOC foo();
    It now outputs:
    != 0 == -0 B1C0000000000000 B1C0000000000000 31C0000000000000
    "B1C000..." is a _Decimal64 -0, and "31C000..." a _Decimal64 0.
    The first bit is the sign bit, the next 10 bits encode the exponent, and the 54-bit significand is an implicit 0 bit followed by the remaining 53 bits (all 0).
    When I run that revised C code as a C program it outputs (correctly):
    == 0 == -0 B1C0000000000000 B1C0000000000000 31C0000000000000
    I also modified the Inline::C rendition that was getting it right to:
    use strict; use warnings; use Inline C => Config => BUILD_NOISY => 1, USING => 'ParseRegExp', #CLEAN_AFTER_BUILD => 0, ; use Inline C => <<'EOC'; #include <stdio.h> void _is_zero(_Decimal64 d64) { _Decimal64 neg_zero, pos_zero = 0.DD; void *pd64 = &d64, *pneg_zero = &neg_zero, *ppos_zero = &pos_zero; int i; neg_zero = pos_zero * -1.DD; if(d64 != pos_zero) printf("!= 0\n"); else printf("== 0\n"); if(d64 != neg_zero) printf("!= -0\n"); else printf("== -0\n"); for(i = 7; i >= 0; i--) printf("%02X", ((unsigned char*)pd64)[i]); printf("\n"); for(i = 7; i >= 0; i--) printf("%02X", ((unsigned char*)pneg_zero)[i]); printf("\n"); for(i = 7; i >= 0; i--) printf("%02X", ((unsigned char*)ppos_zero)[i]); printf("\n"); } int foo(void) { _Decimal64 d64 = 0.DD; d64 *= -1.DD; _is_zero(d64); return 0; } EOC foo();
    It still outputs (correctly):
    == 0 == -0 B1C0000000000000 B1C0000000000000 31C0000000000000
    It's as though the != operation (in the problem script) believes that the values it's comparing are unsigned.

    Cheers,
    Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1189793]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2024-04-19 21:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found