Math-Prime-Util-GMP

 view release on metacpan or  search on metacpan

XS.xs  view on Meta::CPAN


PROTOTYPES: ENABLE

void _GMP_init()

void _GMP_destroy()

void _GMP_memfree()

void _GMP_set_verbose(IN int v)
  PPCODE:
     set_verbose_level(v);

void seed_csprng(IN UV bytes, IN unsigned char* seed)
  PPCODE:
    isaac_init(bytes, seed);

UV irand()
  ALIAS:
    irand64 = 1
    is_csprng_well_seeded = 2
  CODE:
    switch (ix) {
#if BITS_PER_WORD >= 64
      case 0:  RETVAL = isaac_rand32(); break;

XS.xs  view on Meta::CPAN

    RETVAL = is_miller_prime(n, assumegrh);
    mpz_clear(n);
  OUTPUT:
    RETVAL

void
_is_provable_prime(IN char* strn, IN int wantproof = 0)
  PREINIT:
    int result;
    mpz_t n;
  PPCODE:
    PRIMALITY_START("is_provable_prime", 2, 1);
    if (wantproof == 0) {
      result = _GMP_is_provable_prime(n, 0);
      XPUSH_INT(result);
    } else {
      char* prooftext = 0;
      result = _GMP_is_provable_prime(n, &prooftext);
      XPUSH_INT(result);
      if (prooftext) {
        XPUSHs(sv_2mortal(newSVpv(prooftext, 0)));

XS.xs  view on Meta::CPAN

  OUTPUT:
    RETVAL

void
next_prime(IN char* strn)
  ALIAS:
    prev_prime = 1
    next_twin_prime = 2
  PREINIT:
    mpz_t n;
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    if (ix == 1 && mpz_cmp_ui(n,3) < 0) { mpz_clear(n); XSRETURN_UNDEF; }
    if      (ix == 0) _GMP_next_prime(n);
    else if (ix == 1) _GMP_prev_prime(n);
    else              next_twin_prime(n, n);
    XPUSH_MPZ(n);
    mpz_clear(n);


void
random_prime(IN char* strlo, IN char* strhi = 0)
  ALIAS:
    urandomr = 1
  PREINIT:
    mpz_t lo, hi, res;
    int retundef;
  PPCODE:
    if (strhi == 0) {
      mpz_init_set_ui(lo, 0);
      VALIDATE_AND_SET(hi, strlo);
    } else {
      if (*strlo == '+')  strlo++;
      if (*strhi == '+')  strhi++;
      validate_string_number(cv, "lo", strlo);
      validate_string_number(cv, "hi", strhi);
      mpz_init_set_str(lo, strlo, 10);
      mpz_init_set_str(hi, strhi, 10);

XS.xs  view on Meta::CPAN

    mpz_clear(hi);
    mpz_clear(lo);
    if (retundef) XSRETURN_UNDEF;

void prime_count(IN char* strlo, IN char* strhi = 0)
  ALIAS:
    prime_power_count = 1
    perfect_power_count = 2
  PREINIT:
    mpz_t n, lo, hi, res;
  PPCODE:
    mpz_init(res);
    if (strhi == 0) {
      VALIDATE_AND_SET(n, strlo);
      switch (ix) {
        case  0: prime_count(res, n); break;
        case  1: prime_power_count(res, n); break;
        case  2: perfect_power_count(res, n); break;
        default: break;
      }
      mpz_clear(n);

XS.xs  view on Meta::CPAN

      mpz_clear(lo);
      mpz_clear(hi);
    }
    XPUSH_MPZ(res);

void nth_perfect_power(IN char* strn)
  ALIAS:
    nth_perfect_power_approx = 1
  PREINIT:
    mpz_t n, res;
  PPCODE:
    mpz_init(res);
    VALIDATE_AND_SET(n, strn);
    if (ix == 0) nth_perfect_power(res, n);
    else         nth_perfect_power_approx(res, n);
    mpz_clear(n);
    XPUSH_MPZ(res);

void next_perfect_power(IN char* strn)
  ALIAS:
    prev_perfect_power = 1
  PREINIT:
    mpz_t n, res;
  PPCODE:
    mpz_init(res);
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    if (ix == 0) next_perfect_power(res, n);
    else         prev_perfect_power(res, n);
    mpz_clear(n);
    XPUSH_MPZ(res);

void
totient(IN char* strn)
  ALIAS:

XS.xs  view on Meta::CPAN

    ramanujan_tau = 6
    sqrtint = 7
    is_prime_power = 8
    prime_count_lower = 9
    prime_count_upper = 10
    urandomm = 13
    add1int = 14
    sub1int = 15
  PREINIT:
    mpz_t res, n;
  PPCODE:
    if (strn != 0 && strn[0] == '-') { /* If input is negative... */
      if (ix == 2)  XSRETURN_IV(1);    /* exp_mangoldt return 1 */
      if (ix == 5)  strn++;            /* znprimroot flip sign */
      if (ix == 8)  XSRETURN_IV(0);    /* is_prime_power return 0 */
    }
    validate_and_set_signed(cv, n, "n", strn,
                            (ix==14 || ix==15) ? VSETNEG_OK : VSETNEG_ERR);
    mpz_init(res);
    switch (ix) {
      case 0:  totient(res, n);  break;

XS.xs  view on Meta::CPAN

    }
    XPUSH_MPZ(res);
    mpz_clear(n);
    mpz_clear(res);

void absint(IN char* strn)
  ALIAS:
    negint = 1
  PREINIT:
    mpz_t res;
  PPCODE:
    if (strn != 0 && strn[0] == '-') {
      VALIDATE_AND_SET(res, strn+1);
    } else {
      VALIDATE_AND_SET(res, strn);
      if (ix == 1) mpz_neg(res, res);
    }
    XPUSH_MPZ(res);
    mpz_clear(res);

void signint(IN char* strn)
  PREINIT:
    mpz_t n;
    int res;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    res = mpz_sgn(n);
    mpz_clear(n);
    XSRETURN_IV(res);

void cmpint(IN char* stra, IN char* strb)
  ALIAS:
    cmpabsint = 1
  PREINIT:
    mpz_t a, b;
    int res;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, b, "b", strb, VSETNEG_OK);
    res = (ix == 0) ? mpz_cmp(a, b) : mpz_cmpabs(a, b);
    /* GMP 6.2 changed to only return -1,0,1 */
    /* Enforce -1, 0, 1 as our only return values. */
    if (res < 0) res = -1;
    if (res > 0) res = 1;
    mpz_clear(a);
    mpz_clear(b);
    XSRETURN_IV(res);

void setbit(IN char* strn, IN UV k)
  ALIAS:
    clrbit = 1
    notbit = 2
    tstbit = 3
  PREINIT:
    mpz_t n;
    int res;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    switch (ix) {
      case 0:  mpz_setbit(n, k); break;
      case 1:  mpz_clrbit(n, k); break;
      case 2:  mpz_combit(n, k); break;
      case 3:  res = mpz_tstbit(n, k); break;
      default: break;
    }
    if (ix != 3) XPUSH_MPZ(n);
    mpz_clear(n);
    if (ix == 3) XSRETURN_IV(res);

void bitand(IN char* stra, IN char* strb)
  ALIAS:
    bitor = 1
    bitxor = 2
  PREINIT:
    mpz_t a, b;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, b, "b", strb, VSETNEG_OK);
    switch (ix) {
      case 0:  mpz_and(a, a, b); break;
      case 1:  mpz_ior(a, a, b); break;
      case 2:  mpz_xor(a, a, b); break;
      default: break;
    }
    XPUSH_MPZ(a);
    mpz_clear(a);
    mpz_clear(b);

void bitnot(IN char* strn)
  PREINIT:
    mpz_t n;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    mpz_com(n, n);
    XPUSH_MPZ(n);
    mpz_clear(n);

void harmreal(IN char* strn, IN UV prec = 40)
  ALIAS:
    bernreal = 1
    logreal = 2
    expreal = 3
    zeta = 4
    li = 5
    ei = 6
    riemannr = 7
    lambertw = 8
    surround_primes = 9
  PREINIT:
    mpz_t n;
    mpf_t f;
    char* res;
  PPCODE:
    if (ix == 9) {  /* surround_primes */
      UV prev, next;
      VALIDATE_AND_SET(n, strn);
      next = 1 + (mpz_sgn(n)==0);
      if (mpz_cmp_ui(n,2) > 0) {
        surround_primes(n, &prev, &next, (items == 1) ? 0 : prec);
        XPUSH_UINT(prev);
      } else {
        XPUSHs(sv_2mortal(newSV(0)));
      }

XS.xs  view on Meta::CPAN

    rootreal = 1
    agmreal = 2
    addreal = 3
    subreal = 4
    mulreal = 5
    divreal = 6
  PREINIT:
    mpf_t n, x;
    char* res;
    unsigned long bits, bits2, bits3;
  PPCODE:
    bits  = 64 + (unsigned long)(3.32193 * prec);
    bits2 = 64 + (unsigned long)(3.32193 * strlen(strn));
    bits3 = 64 + (unsigned long)(3.32193 * strlen(strx));
    if (bits2 > bits) bits = bits2;
    if (bits3 > bits) bits = bits3;
    mpf_init2(n, bits);
    if (mpf_set_str(n, strn, 10) != 0)
      croak("Not valid base-10 floating point input: %s", strn);
    mpf_init2(x, bits);
    if (mpf_set_str(x, strx, 10) != 0)

XS.xs  view on Meta::CPAN

    mpf_clear(x);
    if (res == 0)
      XSRETURN_UNDEF;
    XPUSHs(sv_2mortal(newSVpv(res, 0)));
    Safefree(res);

void bernvec(IN UV n)
  PREINIT:
    const mpz_t *N, *D;
    UV i;
  PPCODE:
    bernvec(&N, &D, n);  /* Cached array, do not destroy */
    if (GIMME_V != G_VOID) {
      EXTEND(SP, (long)(n+1));
      for (i = 0; i <= n; i++) {
        AV* av = newAV();
        av_push(av, sv_return_for_mpz(aTHX_ N[i]));
        av_push(av, sv_return_for_mpz(aTHX_ D[i]));
        PUSHs( sv_2mortal(newRV_noinc( (SV*) av )) );
      }
    }

XS.xs  view on Meta::CPAN

void
gcd(...)
  PROTOTYPE: @
  ALIAS:
    lcm = 1
    vecsum = 2
    vecprod = 3
  PREINIT:
    int i, negflag;
    mpz_t ret, n;
  PPCODE:
    if (items == 0) XSRETURN_IV( (ix == 1 || ix == 3) ? 1 : 0);
    negflag = (ix <= 1) ? VSETNEG_ABS : VSETNEG_OK;
    if (ix == 1 || ix == 3) {
      mpz_t* list;
      New(0, list, items, mpz_t);
      for (i = 0; i < items; i++) {
        char* strn = SvPV_nolen(ST(i));
        validate_and_set_signed(cv, list[i], "arg", strn, negflag);
      }
      if (ix == 1) mpz_veclcm(list, 0, items-1);

XS.xs  view on Meta::CPAN

    }
    mpz_clear(b);
    mpz_clear(a);
  OUTPUT:
    RETVAL

void
moebius(IN char* strn, IN char* stro = 0)
  PREINIT:
    mpz_t n;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    if (stro == 0) {
      int result = moebius(n);
      mpz_clear(n);
      XSRETURN_IV(result);
    } else {   /* Ranged result */
      mpz_t nhi;
      validate_and_set_signed(cv, nhi, "nhi", stro, VSETNEG_OK);
      while (mpz_cmp(n, nhi) <= 0) {
        XPUSH_INT( moebius(n) );

XS.xs  view on Meta::CPAN

      mpz_clear(n);
      mpz_clear(nhi);
    }

void lucasu(IN char* strp, IN char* strq, IN char* strk)
  ALIAS:
    lucasv = 1
    lucasuv = 2
  PREINIT:
    mpz_t u, v, p, q, k;
  PPCODE:
    validate_and_set_signed(cv, p, "P", strp, VSETNEG_OK);
    validate_and_set_signed(cv, q, "Q", strq, VSETNEG_OK);
    VALIDATE_AND_SET(k, strk);
    mpz_init(u);  mpz_init(v);
    lucasuv(u, v, p, q, k);
    switch (ix) {
      case 0:  XPUSH_MPZ(u);  break;
      case 1:  XPUSH_MPZ(v);  break;
      case 2:
      default: XPUSH_MPZ(u);  XPUSH_MPZ(v); break;
    }
    mpz_clear(v); mpz_clear(u);
    mpz_clear(k); mpz_clear(q); mpz_clear(p);

void lucasumod(IN char* strp, IN char* strq, IN char* strk, IN char* strn)
  ALIAS:
    lucasvmod = 1
    lucasuvmod = 2
  PREINIT:
    mpz_t u, v, t, p, q, k, n;
  PPCODE:
    validate_and_set_signed(cv, p, "P", strp, VSETNEG_OK);
    validate_and_set_signed(cv, q, "Q", strq, VSETNEG_OK);
    VALIDATE_AND_SET(k, strk);
    validate_and_set_signed(cv, n, "N", strn, VSETNEG_ABS);
    if (mpz_cmpabs_ui(n,1) <= 0) {
      int retundef = (mpz_sgn(n) == 0);
      mpz_clear(n); mpz_clear(k); mpz_clear(q); mpz_clear(p);
      if (retundef)     XSRETURN_UNDEF;
      else if (ix != 2) XSRETURN_IV(0);
      else              { XPUSH_UINT(0); XPUSH_UINT(0); XSRETURN(2); }

XS.xs  view on Meta::CPAN

    RETVAL

void
next_powerfree(IN char* strn, IN UV k = 2)
  ALIAS:
    prev_powerfree = 1
    nth_powerfree = 2
  PREINIT:
    mpz_t n;
    int retundef;
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    switch (ix) {
      case 0:  next_powerfree(n,n,k);  break;
      case 1:  prev_powerfree(n,n,k);  break;
      case 2:  nth_powerfree(n,n,k);  break;
      default: break;
    }
    retundef = (mpz_sgn(n) <= 0);
    if (!retundef) XPUSH_MPZ(n);
    mpz_clear(n);

XS.xs  view on Meta::CPAN

    cdivint = 17
    tdivrem = 18
    fdivrem = 19
    cdivrem = 20
    divrem = 21
    factorialmod = 22
    multifactorial = 23
  PREINIT:
    mpz_t a, b, t;
    int retundef;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, b, "b", strb, VSETNEG_OK);
    retundef = 0;
    switch (ix) {
               /* 0 if b is 1, else undef if a|b = 0, else mpz_invert */
      case 0:{
               if      (!mpz_cmpabs_ui(b,1))         mpz_set_ui(a,0);
               else if (!mpz_sgn(b) || !mpz_sgn(a))  retundef = 1;
               else                              retundef = !mpz_invert(a,a,b);
             } break;

XS.xs  view on Meta::CPAN

    }
    if (!retundef) XPUSH_MPZ(a);
    mpz_clear(b); mpz_clear(a);
    if (retundef) XSRETURN_UNDEF;

void
binomialmod(IN char* strn, IN char* strk, IN char* strm)
  PREINIT:
    mpz_t n, k, m, r;
    unsigned long nu, ku;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    validate_and_set_signed(cv, k, "k", strk, VSETNEG_OK);
    validate_and_set_signed(cv, m, "m", strm, VSETNEG_ABS);
    if (mpz_sgn(m) == 0) {
      mpz_clear(n); mpz_clear(k); mpz_clear(m);
      XSRETURN_UNDEF;
    }
    if ( mpz_cmp_ui(m,1) <= 0 ||
         (mpz_sgn(n) >= 0 && (mpz_sgn(k) < 0 || mpz_cmp(k,n) > 0)) ||
         (mpz_sgn(n) <  0 && (mpz_sgn(k) < 0 && mpz_cmp(k,n) > 0)) ) {

XS.xs  view on Meta::CPAN

    mpz_clear(m);
    XPUSH_MPZ(r);
    mpz_clear(r);

void
falling_factorial(IN char* strx, IN char* strn)
  ALIAS:
    rising_factorial = 1
  PREINIT:
    mpz_t x, n, r;
  PPCODE:
    validate_and_set_signed(cv, x, "x", strx, VSETNEG_OK);
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_ABS);
    mpz_init(r);
    if (ix == 0)  falling_factorial(r, x, n);
    else          rising_factorial(r, x, n);
    mpz_clear(x);
    mpz_clear(n);
    XPUSH_MPZ(r);
    mpz_clear(r);

XS.xs  view on Meta::CPAN

    if (RETVAL == -1)
      XSRETURN_UNDEF;
  OUTPUT:
    RETVAL

void powersum(IN char* stra, IN char* strb)
  ALIAS:
    faulhaber_sum = 1
  PREINIT:
    mpz_t a, b;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, b, "b", strb, VSETNEG_OK);
    if (mpz_sgn(a) < 0 || mpz_sgn(b) < 0) croak("powersum: negative argument");
    if (ix == 0 || ix == 1)
      faulhaber_sum(a, a, mpz_get_ui(b));
    XPUSH_MPZ(a);
    mpz_clear(b); mpz_clear(a);

void
lshiftint(IN char* strn, IN long k = 1)
  ALIAS:
    rshiftint = 1
    rashiftint = 2
  PREINIT:
    mpz_t n;
    int nix;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    nix = ix;
    if (k < 0) {
      k = -k;
      nix = !nix;  /* left => right, right or arith_right => left */
    }
    switch (nix) {
      case 0:  mpz_mul_2exp(n, n, k);      break;
      case 1:  mpz_tdiv_q_2exp(n, n, k);   break;
      case 2:

XS.xs  view on Meta::CPAN

    }
    XPUSH_MPZ(n);
    mpz_clear(n);

void
powerful_count(IN char* strn, IN int k = 2)
  ALIAS:
    powerfree_count = 1
  PREINIT:
    mpz_t n, r;
  PPCODE:
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    mpz_init(r);
    switch (ix) {
      case 0:  powerful_count(r, n, (unsigned long) k);  break;
      case 1:  powerfree_count(r, n, (uint32_t) k);  break;
      default: break;
    }
    XPUSH_MPZ(r);
    mpz_clear(r);
    mpz_clear(n);

void negmod(IN char* stra, IN char* strn)
  PREINIT:
    mpz_t a, n;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_OK);
    if (mpz_sgn(n) == 0) {
      mpz_clear(n); mpz_clear(a);
      XSRETURN_UNDEF;
    }
    mpz_abs(n, n);
    mpz_neg(a, a);
    mpz_mod(a, a, n);
    XPUSH_MPZ(a);

XS.xs  view on Meta::CPAN

void
addmod(IN char* stra, IN char* strb, IN char* strn)
  ALIAS:
    submod = 1
    mulmod = 2
    powmod = 3
    divmod = 4
  PREINIT:
    mpz_t a, b, n;
    int retundef;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, b, "b", strb, VSETNEG_OK);
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_ABS);
    retundef = (mpz_sgn(n) <= 0);
    if (!retundef && ix == 4) {
      if (mpz_cmp_ui(n,1) > 0) {  /* if n is 1, let the mod turn it into zero */
        mpz_mod(b, b, n);         /* Get b between 0 and n-1. */
        if (mpz_sgn(b) == 0)           retundef = 1;
        else if (mpz_cmp_ui(b,1) > 0)  retundef = !mpz_invert(b,b,n);
      }

XS.xs  view on Meta::CPAN

      mpz_powm(a, a, b, n);
    }
    XPUSH_MPZ(a);
    mpz_clear(n); mpz_clear(b); mpz_clear(a);

void muladdmod(IN char* stra, IN char* strb, IN char* strc, IN char* strn)
  ALIAS:
    mulsubmod = 1
  PREINIT:
    mpz_t a, b, c, n;
  PPCODE:
    validate_and_set_signed(cv, a, "a", stra, VSETNEG_OK);
    validate_and_set_signed(cv, b, "b", strb, VSETNEG_OK);
    validate_and_set_signed(cv, c, "c", strc, VSETNEG_OK);
    validate_and_set_signed(cv, n, "n", strn, VSETNEG_ABS);
    if (mpz_sgn(n) <= 0) {
      mpz_clear(n); mpz_clear(c); mpz_clear(b); mpz_clear(a);
      XSRETURN_UNDEF;
    }
    mpz_mul(a,a,b);
    if (ix == 0)  mpz_add(a, a, c);

XS.xs  view on Meta::CPAN

    RETVAL = lucas_lehmer(n);
  OUTPUT:
    RETVAL

void Pi(IN UV n)
  ALIAS:
    Euler = 1
    random_bytes = 2
  PREINIT:
    UV prec;
  PPCODE:
    if (ix == 2) {  /* random_bytes */
      char* sptr;
      SV* sv = newSV(n == 0 ? 1 : n);
      SvPOK_only(sv);
      SvCUR_set(sv, n);
      sptr = SvPVX(sv);
      isaac_rand_bytes(n, (unsigned char*)sptr);
      sptr[n] = '\0';
      PUSHs(sv_2mortal(sv));
      XSRETURN(1);

XS.xs  view on Meta::CPAN

    factorial = 9
    factorial_sum = 10
    subfactorial = 11
    partitions = 12
    primorial = 13
    pn_primorial = 14
    consecutive_integer_lcm = 15
  PREINIT:
    mpz_t p;
    char* proof;
  PPCODE:
    if (ix == 8 && n <= BITS_PER_WORD) {
      UV v = irand64(n);
      ST(0) = sv_2mortal(newSVuv(v));
      XSRETURN(1);
    }
    mpz_init(p);
    proof = 0;
    switch (ix) {
      case 0:  mpz_random_nbit_prime(p, n); break;
      case 1:  mpz_random_safe_prime(p, n); break;

XS.xs  view on Meta::CPAN

    mpz_clear(p);
    if (proof) {
      XPUSHs(sv_2mortal(newSVpv(proof, 0)));
      Safefree(proof);
    }

void
stirling(IN UV n, IN UV m, IN UV type = 1)
  PREINIT:
    mpz_t r;
  PPCODE:
    mpz_init(r);
    stirling(r, n, m, type);
    XPUSH_MPZ( r );
    mpz_clear(r);

void chinese(...)
  ALIAS:
    chinese2 = 1
  PROTOTYPE: @
  PREINIT:
    int i, doretval;
    mpz_t* an;
    mpz_t ret, lcm;
  PPCODE:
    if (items == 0) {
      if (ix == 0)  XSRETURN_IV(0);
      XPUSH_UINT(0);
      XPUSH_UINT(0);
      XSRETURN(2);
    }
    mpz_init_set_ui(ret, 0);
    New(0, an, 2*items, mpz_t);
    for (i = 0; i < items; i++) {
      AV* av;

XS.xs  view on Meta::CPAN

    }

void
permtonum(SV* svp)
  PREINIT:
    AV *av;
    char* seen;
    UV val, *V;
    int plen, n, i, j, k;
    mpz_t f, t, num;
  PPCODE:
    if ((!SvROK(svp)) || (SvTYPE(SvRV(svp)) != SVt_PVAV))
      croak("permtonum argument must be an array reference");
    av = (AV*) SvRV(svp);
    plen = av_len(av);
    if (plen < 0) XSRETURN_IV(0);
    Newz(0, seen, plen+1, char);
    New(0, V, plen+1, UV);
    for (i = 0; i <= plen; i++) {
      SV **iv = av_fetch(av, i, 0);
      if (iv == 0) break;

XS.xs  view on Meta::CPAN

      mpz_divexact_ui(f, f, n-i-1);
    }
    Safefree(V);
    XPUSH_MPZ(num);
    mpz_clear(num);  mpz_clear(t);  mpz_clear(f);

void numtoperm(IN UV n, IN char* strk)
  PREINIT:
    mpz_t k, f, p;
    UV i, j, tv, *perm;
  PPCODE:
    if (n == 0)
      XSRETURN_EMPTY;
    validate_and_set_signed(cv, k, "k", strk, VSETNEG_OK);
    mpz_init(f);  mpz_init(p);
    New(0, perm, n, UV);
    for (i = 0; i < n; i++)
      perm[i] = i;
    mpz_fac_ui(f, n);
    mpz_mod(k,k,f);
    for (i = 0; i < n-1; i++) {

XS.xs  view on Meta::CPAN

    mpz_clear(p);  mpz_clear(f); mpz_clear(k);

void
sieve_prime_cluster(IN char* strlow, IN char* strhigh, ...)
  ALIAS:
    sieve_primes = 1
    sieve_twin_primes = 2
  PREINIT:
    mpz_t low, seghigh, high, t;
    UV i, nc, nprimes, maxseg, *list;
  PPCODE:
    VALIDATE_AND_SET(low, strlow);
    VALIDATE_AND_SET(high, strhigh);
    mpz_init(seghigh);
    mpz_init(t);

    nc = items-1;
    maxseg = ((UV_MAX > ULONG_MAX) ? ULONG_MAX : UV_MAX);

    /* Loop as needed */
    while (mpz_cmp(low, high) <= 0) {

XS.xs  view on Meta::CPAN

    mpz_clear(t);
    mpz_clear(seghigh);
    mpz_clear(high);
    mpz_clear(low);

void
sieve_range(IN char* strn, IN UV width, IN UV depth)
  PREINIT:
    mpz_t low, seghigh, high, t;
    UV i, nprimes, maxseg, offset, *list;
  PPCODE:
    if (width == 0) XSRETURN(0);
    if (depth == 0) depth = 1;

    VALIDATE_AND_SET(low, strn);
    mpz_init(high);
    mpz_add_ui(high, low, width-1);
    mpz_init(seghigh);
    mpz_init(t);
    maxseg = ((UV_MAX > ULONG_MAX) ? ULONG_MAX : UV_MAX);
    offset = 0;

XS.xs  view on Meta::CPAN

    }
    mpz_clear(t);
    mpz_clear(seghigh);
    mpz_clear(high);
    mpz_clear(low);

void
lucas_sequence(IN char* strn, IN IV P, IN IV Q, IN char* strk)
  PREINIT:
    mpz_t U, V, Qk, n, k, t;
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    VALIDATE_AND_SET(k, strk);
    mpz_init(U);  mpz_init(V);  mpz_init(Qk);  mpz_init(t);
    lucas_seq(U, V, n, P, Q, k, Qk, t);
    XPUSH_MPZ(U);
    XPUSH_MPZ(V);
    XPUSH_MPZ(Qk);

    mpz_clear(n);  mpz_clear(k);
    mpz_clear(U);  mpz_clear(V);  mpz_clear(Qk);  mpz_clear(t);

XS.xs  view on Meta::CPAN

    holf_factor = 6
    squfof_factor = 7
    ecm_factor = 8
    qs_factor = 9
  PREINIT:
    mpz_t n;
    UV arg1, arg2, uf;
    static const UV default_arg1[] =
      {0,   64000000,64000000,5000000,5000000,0,256000000,100000000,0,  0  };
    /*Trial,Rho,     Brent,   P-1,    P+1,    Cheb, HOLF, SQUFOF,   ECM,QS */
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    {
      int cmpr = mpz_cmp_ui(n,1);
      if (cmpr <= 0) {
        mpz_clear(n);
        if (cmpr < 0) XSRETURN_IV(0);
        XSRETURN_EMPTY;
      }
    }
    arg1 = default_arg1[ix];

XS.xs  view on Meta::CPAN

      XPUSH_MPZ(n);
    mpz_clear(n);

void
factor(IN char* strn)
  PREINIT:
    mpz_t n;
    mpz_t* factors;
    int* exponents;
    int nfactors, i, j;
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    if (GIMME_V != G_VOID) {
      nfactors = factor(n, &factors, &exponents);
      if (GIMME_V == G_SCALAR) {
        for (i = 0, j = 0; i < nfactors; i++)
          j += exponents[i];
        PUSHs(sv_2mortal(newSVuv(j)));
      } else {
        for (i = 0; i < nfactors; i++) {
          for (j = 0; j < exponents[i]; j++) {

XS.xs  view on Meta::CPAN

      }
      clear_factors(nfactors, &factors, &exponents);
    }
    mpz_clear(n);

void divisors(IN char* strn, IN char* strk = 0)
  PREINIT:
    mpz_t n, k;
    mpz_t* divs;
    int ndivisors, i;
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    if (strk == 0) {
      mpz_init_set(k, n);
    } else {
      VALIDATE_AND_SET(k, strk);
    }
    if (GIMME_V == G_VOID) {
      /* Nothing */
    } else if (GIMME_V == G_SCALAR && mpz_cmp(k, n) >= 0) {
      sigma(n, n, 0);

XS.xs  view on Meta::CPAN

        mpz_clear(divs[i]);
      Safefree(divs);
    }
    mpz_clear(k);
    mpz_clear(n);

void
sigma(IN char* strn, IN UV k = 1)
  PREINIT:
    mpz_t n;
  PPCODE:
    VALIDATE_AND_SET(n, strn);
    sigma(n, n, k);
    XPUSH_MPZ(n);
    mpz_clear(n);

void
todigits(IN char* strn, unsigned int base=10, int length=-1)
  PREINIT:
    mpz_t n;
    uint32_t d, *digits;
  PPCODE:
    if (base < 2 || base > 0xFFFFFFFFU) croak("invalid base: %u\n", base);
    if (strn[0] == '-' || strn[0] == '+')  strn++;
    validate_string_number(cv, "n", strn);
    if (base == 10) {
      uint32_t l = strlen(strn);
      New(0, digits, l, uint32_t);
      for (d = 0; d < l; d++)
        digits[d] = strn[d]-'0';
    } else {
      mpz_init_set_str(n, strn, 10);

XS.xs  view on Meta::CPAN

    }
    Safefree(digits);

void
fromdigits(IN SV* svp, unsigned int base=10)
  PREINIT:
    AV *av;
    int i, plen;
    uint32_t *digits;
    mpz_t n;
  PPCODE:
    if (base < 2 || base > 0xFFFFFFFFU) croak("invalid base: %u\n", base);
    mpz_init(n);
    if (!SvROK(svp)) { /* string */
      fromdigits_str(n, SvPV_nolen(svp), base);
    } else {
      if (SvTYPE(SvRV(svp)) != SVt_PVAV)
        croak("fromdigits argument must be a string or array reference");
      av = (AV*) SvRV(svp);
      plen = av_len(av);
      if (plen < 0) XSRETURN_IV(0);



( run in 0.523 second using v1.01-cache-2.11-cpan-5511b514fd6 )