in reply to Re^5: perl inline::c sorting problem
in thread perl inline::c sorting problem

"the magic of XS"

No, just the magic of the C standard. Very much like how double n = 1; doesn't generate a warning. Some compilers might give you a warning if assigning a long long value into a non-long double, at least if the long long value is "big" enough, but that is beyond my level of knowledge of such things at this point. The typical case of a 4-byte IV and an 8-byte NV means there is never even a single bit lost by such an assignment and I clearly recall that the C standard specifies that such is allowed without complaint.

- tye        

Replies are listed 'Best First'.
Re^7: perl inline::c sorting problem (implicit coercion)
by BrowserUk (Patriarch) on May 02, 2009 at 05:32 UTC

    I'm running a 64-bit build of Perl, making IVs & UVs 64-bit. As you pointed out to me a long time ago, a 64-bit double can hold at most a 53-bit integer. Therefore there is a potential that assigning either of the former to the latter, could result in loss of data. I expected a warning.

    And indeed, if I try this with straight C, I get those warnings:

    void test2 ( SV *sv ) { double d = SvIV( sv ); double d2 = SvUV( sv ); return; } IC_sort.c IC_sort.xs(42) : warning C4244: 'initializing' : conversion from 'IV' +to 'double', possible loss of data IC_sort.xs(43) : warning C4244: 'initializing' : conversion from 'UV' +to 'double', possible loss of data
    <

    Hence, I attribute their absence to "the magic of XS".


    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".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Hence, I attribute their absence to "the magic of XS".

      With the test2() sub, the compiler sees it is *inevitable* that the conversion from IV/UV to double will occur - and warns accordingly.

      With the test() sub, that inevitability does not exist (as there's the possibility that SvNSIV() defines an NV), and the compiler recognises this. Therefore the warning cannot be given.

      For example, with this modification, the warning disappears:
      #define IIII(sv) (SvIOK(sv) ? SvIV(sv) : SvNV(sv)) #define UUUU(sv) (SvUOK(sv) ? SvUV(sv) : SvNV(sv)) void test2 ( SV *sv ) { double d = IIII( sv ); double d2 = UUUU( sv ); return; }
      Cheers,
      Rob

        That does explain it. I was still leery of what goings on inside the SvIOK/SvUOK macros might be influencing it, so I substituted a volatile variable as the conditional:

        volatile int n; void test2 ( SV *sv ) { double d1 = n ? SvNV( sv ) : SvIV( sv ); double d2 = n ? SvNV( sv ) : SvUV( sv ); return; }

        And sure enough that silenced the warnings.

        Whilst that definitively takes XS off the hook, moving it to either the C/C++ standard or the compiler, it still leaves a bad taste in the mouth. Given this is a warning rather than an error; and that even the wording "possible loss of data" hedges its bets; I'd personally prefer the warning to be issued if there is the 'possibility of data loss', rather than not issued if there is the 'possibility that no data will be lost'.

        That said, given my enmity for things like const correctness and PerlCritic, I wonder if I'm in danger of asking for a similar level of cry-wolfism?


        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".
        In the absence of evidence, opinion is indistinguishable from prejudice.