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".
In reply to Re^5: perl inline::c sorting problem
by BrowserUk
in thread perl inline::c sorting problem
by dalittle
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |