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

The perl api is not very clear here. I have been trying to write my own numberical sort function (for Perl_sv_cmp) and am not sure if I even have the right args. It seems simple enough, but I have not been able to figure it out.
sortsv(AvARRAY(data), arrayLen+1, Perl_sv_cmp); to sortsv(AvARRAY(data), arrayLen+1, numerical_cmp); ??? I32 numerical_cmp(SV* sv1,SV* sv2) { double num1; double num2; num1 = (double)*sv1; num2 = (double)*sv2; if (num1 == num2) { return 0; } else if (num1 > num2) { return 1; } else { return -1; } }

Replies are listed 'Best First'.
Re^5: perl inline::c sorting problem
by BrowserUk (Patriarch) on May 01, 2009 at 01:52 UTC

    I'd just steal the implementation from PP_sort.c. You have to also grab a couple of #defines:

    use warnings; use Inline C => Config => NAME => 'IC_sort', CLEAN_AFTER_BUILD => 0, BUILD_NOISY => 1; use Inline C => <<'END_OF_C_CODE'; #define SvSIOK(sv) ((SvFLAGS(sv) & (SVf_IOK|SVf_IVisUV)) == SVf_IOK) #define SvNSIV(sv) ( SvNOK(sv) ? SvNVX(sv) : ( SvSIOK(sv) ? SvIVX(sv) +: sv_2nv(sv) ) ) static I32 S_sv_ncmp(pTHX_ SV *a, SV *b) { const NV nv1 = SvNSIV(a); const NV nv2 = SvNSIV(b); return nv1 < nv2 ? -1 : nv1 > nv2 ? 1 : 0; } void test(AV* data) { I32 i; I32 arrayLen; SV** pvalue; if( SvTYPE( data ) != SVt_PVAV ) croak( "Requires an array ref ( type %d)\n", SvTYPE( data ) ); arrayLen = av_len(data); sortsv(AvARRAY(data),arrayLen+1, S_sv_ncmp); for (i = 0; i < arrayLen+1; i++) { pvalue = av_fetch(data,i,0); printf("%s \n", SvPV_nolen( *pvalue ) ); } } END_OF_C_CODE my $ref = [ 5.0e-5,4.2e-5,4.3e-5,4.4e-5,4.4e-5,4.2e-5,4.2e-5,4.0e-5]; test($ref);

    That works! However, there is something I do not understand about:

    #define SvNSIV(sv) ( SvNOK(sv) ? SvNVX(sv) : ( SvSIOK(sv) ? SvIVX(sv) +: sv_2nv(sv) ) ) ... const NV nv1 = SvNSIV(a);

    If the value is an NV, it grabs it. But if it is an IV, it grabs the IV and assigns it to the NV without coercion. Seems to work okay for mixed ints and floats and I don't see any warnings, so I guess that's yet another mystery to put down 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.
      Wow, this is exactly what I needed. Really speeds up my code, thanks so much !!!!!!!!!!!!

      As for the float/int question, I believe an int is the lower bits of a float so as long as the variable is declared a float it should not matter.

      Now off to try out my new toy on my heap of data. :)
      "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        

        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.