#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" enum { false, true }; MODULE = Math::Factor::XS PACKAGE = Math::Factor::XS void xs_factors (number) unsigned long number PROTOTYPE: $ INIT: unsigned long i; PPCODE: AV *factors = newAV (); unsigned long square_root = sqrt (number); for (i = 2; i <= number; i++) { if (i > square_root) break; if (number % i == 0) { EXTEND (SP, 1); PUSHs (sv_2mortal(newSVuv(i))); if ((number / i) > i) av_push (factors, newSVuv(number / i)); } } while (av_len (factors) >= 0) { EXTEND (SP, 1); PUSHs (sv_2mortal(av_pop(factors))); } SvREFCNT_dec (factors); void xs_matches (number, factors_aref, ...) unsigned long number SV *factors_aref PROTOTYPE: $\@ INIT: AV *factors; unsigned long *prev_base = NULL; unsigned int b, c, p = 0; unsigned int top = items - 1; bool Skip_multiples = false; bool skip = false; PPCODE: factors = (AV*)SvRV (factors_aref); if (av_len (factors) == -1) XSRETURN_EMPTY; if (SvROK (ST(top)) && SvTYPE (SvRV(ST(top))) == SVt_PVHV) { const char *opt = "skip_multiples"; unsigned int len = strlen (opt); HV *opts = (HV*)SvRV (ST(top)); if (hv_exists (opts, opt, len)) { SV **val = hv_fetch (opts, opt, len, 0); if (val) Skip_multiples = SvTRUE (*val); } } for (b = 0; b <= av_len (factors); b++) { unsigned long base = SvUV (*av_fetch(factors, b, 0)); for (c = 0; c <= av_len (factors); c++) { unsigned long cmp = SvUV (*av_fetch(factors, c, 0)); if ((cmp >= base) && (base * cmp == number)) { if (Skip_multiples) { unsigned int i; skip = false; for (i = 0; i < p; i++) if (base % prev_base[i] == 0) skip = true; } if (!skip) { AV *match = newAV (); av_push (match, newSVuv(base)); av_push (match, newSVuv(cmp)); EXTEND (SP, 1); PUSHs (sv_2mortal(newRV_noinc((SV*)match))); if (Skip_multiples) { if (!prev_base) Newx (prev_base, 1, unsigned long); else Renew (prev_base, p + 1, unsigned long); prev_base[p++] = base; } } } } } Safefree (prev_base);