Hi,

This demo script requires a compiler (eg gcc) that provides the _Decimal64 type:
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; d64 *= -1.DD; if(d64 != 0.DD) printf("!= 0\n"); else printf("== 0\n"); if(d64 != -0.DD) printf("!= -0\n"); else printf("== -0\n"); return 0; } EOC foo();
That outputs:
!= 0 == -0
which tells me that -0 != 0 (and that is contrary to IEEE standards).

However, if I copy'n'past that C code across to a separate file and run it as a C program (using the very same compiler) I get correct output:
#include <stdio.h> int main(void) { _Decimal64 d64 = 0.DD; d64 *= -1.DD; if(d64 != 0.DD) printf("!= 0\n"); else printf("== 0\n"); if(d64 != -0.DD) printf("!= -0\n"); else printf("== -0\n"); return 0; }
AFAICS, all that has changed is that "foo" has been renamed to "main".
Yet, this now correctly outputs:
== 0 == -0
I'm seeing this behaviour on both Windows and Linux for a variety of perl versions and a variety of gcc compilers from 4.7.0 to 7.1.0 - so I'm hopeful that anyone else who has a gcc-4.x.x compiler (or later) will have no trouble reproducing the behaviour. Only other thing needed is Inline::C.

I've gazed upon the C code that Inline::C generates, and I've run the script through the C pre-processor, but I haven't managed to spot anything that helps me understand how this anomaly exists.
I've also spent some time trying various things that I hoped might trick Inline::C into behaving properly and I did find that this works:
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) { if(d64 != 0.DD) printf("!= 0\n"); else printf("== 0\n"); if(d64 != -0.DD) printf("!= -0\n"); else printf("== -0\n"); } int foo(void) { _Decimal64 d64 = 0.DD; d64 *= -1.DD; _is_zero(d64); return 0; } EOC foo();
All I've done there is to move the test that foo() was previously doing, into a separate sub. That produces correct output of:
== 0 == -0
Unfortunately the same approach doesn't work for the _Decimal128 type, where the same issue also arises.

There's nothing of much immediate importance with this ... but I can't stop scratching at it ;-)

Your insights are most welcome

Cheers,
Rob

In reply to Inline::C producing an absurd result by syphilis

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.