Bit-Grep

 view release on metacpan or  search on metacpan

Grep.xs  view on Meta::CPAN

typedef void (*iterate_cb)(pTHX_ UV ix, SV *ele, void *ptr);

static void
iterate(pTHX_ SV *vec, SV **eles, UV size, iterate_cb cb, void *ptr) {
    STRLEN bits_len;
    const char *bits = SvPV_const(vec, bits_len);
    UV bits_size = bits_len * 8;
    UV i = 0;
    if (size > bits_size) size = bits_size;
    while (i < size) {
        char byte = *(bits++);
        int j;
        for (j = 0; j < 8; j++) {
            if (i == size) return;
            if ((byte >> j) & 1) (*cb)(aTHX_ i, eles[i], ptr);
            i++;
        }
    }
}

static void
bg_sum_cb(pTHX_ UV ix, SV *ele, void *nv) {
    *(NV*)nv += SvNV(ele);
}

struct bg_stats_state {
    UV count;
    NV sum;
    NV sum2;
};

static void
bg_count_and_sum_cb(pTHX_ UV ix, SV *ele, void *state) {
    ((struct bg_stats_state*)state)->count++;
    ((struct bg_stats_state*)state)->sum += SvNV(ele);
}

static void
bg_count_sum_and_sum2_cb(pTHX_ UV ix, SV *ele, void *state) {
    NV nv = SvNV(ele);
    ((struct bg_stats_state*)state)->count++;
    ((struct bg_stats_state*)state)->sum += nv;
    ((struct bg_stats_state*)state)->sum2 += nv * nv;
}

static void
bg_grep_cb(pTHX_ UV ix, SV *ele, void *state) {
    SV **to = (*(SV***)state)++;
    *to = ele;
}


MODULE = Bit::Grep		PACKAGE = Bit::Grep		
PROTOTYPES: DISABLE

void
bg_grep(vec, ...)
    SV *vec;
PREINIT:
    SV **to;
PPCODE:
    to = &(ST(0));
    iterate(aTHX_ vec, &(ST(1)), items - 1, &bg_grep_cb, &to);
    XSRETURN(to - &(ST(0)));
  
NV
bg_sum(vec, ...)
    SV *vec;
CODE:
    RETVAL = 0;
    iterate(aTHX_ vec, &(ST(1)), items - 1, &bg_sum_cb, &RETVAL);
OUTPUT:
    RETVAL

void
bg_count_and_sum(vec, ...)
    SV *vec;
PREINIT:
    struct bg_stats_state state;
PPCODE:
    state.count = 0;
    state.sum   = 0;
    iterate(aTHX_ vec, &(ST(1)), items - 1, &bg_count_and_sum_cb, &state);
    mXPUSHi(state.count);
    mXPUSHn(state.sum);
    XSRETURN(2);

void
bg_count_sum_and_sum2(vec, ...)
    SV *vec;
PREINIT:
    struct bg_stats_state state;
PPCODE:
    state.count = 0;
    state.sum   = 0;
    state.sum2  = 0;
    iterate(aTHX_ vec, &(ST(1)), items - 1, &bg_count_sum_and_sum2_cb, &state);
    mXPUSHi(state.count);
    mXPUSHn(state.sum);
    mXPUSHn(state.sum2);
    XSRETURN(3);

SV *
bg_avg(vec, ...)
    SV *vec;
PREINIT:
    struct bg_stats_state state;
CODE:
    state.count = 0;
    state.sum = 0;
    iterate(aTHX_ vec, &(ST(1)), items -1, &bg_count_and_sum_cb, &state);
    RETVAL = (state.count ? newSVnv(state.sum/state.count) : &PL_sv_undef);
OUTPUT:
    RETVAL



( run in 1.680 second using v1.01-cache-2.11-cpan-71847e10f99 )