Math-Random-MTwist

 view release on metacpan or  search on metacpan

MTwist.xs  view on Meta::CPAN

  return RETVAL;
}

static int loadstate(mt_state* state, SV* file_sv) {
  PerlIO* pio = NULL;
  FILE* fh = NULL;
  int RETVAL = 0;

  dTHX;

  fh = open_file_from_sv(file_sv, "r", &pio);

  if (fh) {
    RETVAL = state ? mts_loadstate(fh, state) : mt_loadstate(fh);
    if (pio)
      PerlIO_releaseFILE(pio, fh);
    else
      fclose(fh);
  }

  return RETVAL;
}

static void set_state_from_sv(SV* sv_state, mt_state* state) {
  STRLEN len;

  dTHX;

  if (!SvPOK(sv_state))
    croak("State must be a string");

  len = SvCUR(sv_state);
  if (len != sizeof(mt_state))
    croak("Need exactly %d state bytes, not %d", sizeof(mt_state), len);

  *state = *(mt_state*)SvPV_nolen(sv_state);

  if (state->stateptr < 0 || state->stateptr > MT_STATE_SIZE) {
    warn("stateptr value %d outside valid range [0, %d], using 0 instead",
         state->stateptr, MT_STATE_SIZE);
    state->stateptr = 0;
  }
}


MODULE = Math::Random::MTwist		PACKAGE = Math::Random::MTwist

PROTOTYPES: ENABLE

mt_state*
new_state(char* CLASS)
  CODE:
    Newxz(RETVAL, 1, mt_state);
    if (RETVAL == NULL)
      croak("Could not allocate state memory");
  OUTPUT:
    RETVAL

void
DESTROY(mt_state* state)
  PPCODE:
    Safefree(state);

UV
seed32(mt_state* state, uint32_t seed)
  CODE:
    mts_seed32new(state, seed);
    RETVAL = seed;
  OUTPUT:
    RETVAL

UV
_seed32(uint32_t seed)
  CODE:
    mt_seed32new(seed);
    RETVAL = seed;
  OUTPUT:
    RETVAL

UV
srand(mt_state* state, uint32_t seed = 0)
  CODE:
    RETVAL = srand50c(state, items == 1 ? NULL : &seed);
  OUTPUT:
    RETVAL

UV
_srand(uint32_t seed = 0)
  CODE:
    RETVAL = srand50c(NULL, items == 0 ? NULL : &seed);
  OUTPUT:
    RETVAL

UV
timeseed(mt_state* state)

UV
_timeseed()
  CODE:
    RETVAL = timeseed(NULL);
  OUTPUT:
    RETVAL

UV
fastseed(mt_state* state)

UV
_fastseed()
  CODE:
    RETVAL = fastseed(NULL);
  OUTPUT:
    RETVAL

UV
goodseed(mt_state* state)

UV
_goodseed()
  CODE:
    RETVAL = goodseed(NULL);
  OUTPUT:
    RETVAL

void
bestseed(mt_state* state)

void
_bestseed()
  PPCODE:
    bestseed(NULL);

void
seedfull(mt_state* state, AV* seeds)
  PPCODE:
    seedfull(state, seeds);

void
_seedfull(AV* seeds)
  PPCODE:
    seedfull(NULL, seeds);

SV*
irand32(mt_state* state);
  ALIAS:
    irand64 = 1
    irand = 2
  CODE:
#if IVSIZE >= 8
    if (ix)
      RETVAL = newSVuv(mts_llrand(state));
#elif defined(UINT64_MAX)
    if (ix)
      RETVAL = svpv_uint64(mts_llrand(state));
#else
    if (ix == 1)
      XSRETURN_UNDEF;
#endif
    else
      RETVAL = newSVuv(state ? mts_lrand(state) : mt_lrand());
  OUTPUT:
    RETVAL

SV*
_irand32();
  ALIAS:
    _irand64 = 1
    _irand = 2
  CODE:
#if IVSIZE >= 8
    if (ix)
      RETVAL = newSVuv(mt_llrand());
#elif defined(UINT64_MAX)
    if (ix)
      RETVAL = svpv_uint64(mt_llrand());
#else
    if (ix == 1)
      XSRETURN_UNDEF;
#endif
    else
      RETVAL = newSVuv(mt_lrand());
  OUTPUT:
    RETVAL

SV*
irand128(mt_state* state);
  CODE:
#if IVSIZE >= 16
    RETVAL = newSVuv(mts_u128rand(state));
#elif MT_HAS_INT128
    RETVAL = svpv_uint128(mts_u128rand(state));
#else
    XSRETURN_UNDEF;
#endif
  OUTPUT:
    RETVAL

SV*
_irand128();
  CODE:

MTwist.xs  view on Meta::CPAN

      RETVAL = mt_drand();
    else
#if NVMANTBITS <= 64
      RETVAL = mt_ldrand();
#else
      RETVAL = mt_lldrand();
#endif
    if (bound)
      RETVAL *= bound;
  OUTPUT:
    RETVAL

### Interestingly, randstr() is faster than rd_double(2).
SV*
randstr(mt_state* state, STRLEN length = I2D_SIZE)
  CODE:
    RETVAL = randstr(state, length);
  OUTPUT:
    RETVAL

SV*
_randstr(STRLEN length = I2D_SIZE)
  CODE:
    RETVAL = randstr(NULL, length);
  OUTPUT:
    RETVAL

#define RETURN_I2D(have_index) { \
  if (have_index) {              \
    switch(index) {              \
    case 0:                      \
      XSRETURN_NV(i2d.dbl);      \
    case 1:                      \
      if (IVSIZE >= 8)           \
        XSRETURN_UV(i2d.i64);    \
      else                       \
        XSRETURN_UNDEF;          \
    case 2:                      \
      XSRETURN_PVN(i2d.str, 8);  \
    default:                     \
      XSRETURN_UNDEF;            \
    }                            \
  }                              \
  else {                         \
    mPUSHn(i2d.dbl);             \
    if (GIMME_V == G_ARRAY) {    \
      EXTEND(SP, 2);             \
      if (IVSIZE >= 8)           \
        mPUSHu(i2d.i64);         \
      else                       \
        PUSHs(&PL_sv_undef);     \
      mPUSHp(i2d.str, 8);        \
    }                            \
  }                              \
}                                \

void
rd_double(mt_state* state, int index = 0)
  PREINIT:
    int2dbl i2d;
  PPCODE:
    i2d = rd_double(state);
    RETURN_I2D(items > 1);

void
_rd_double(int index = 0)
  PREINIT:
    int2dbl i2d;
  PPCODE:
    i2d = rd_double(NULL);
    RETURN_I2D(items != 0);

IV
rd_iuniform32(mt_state* state, IV lower, IV upper);
  ALIAS:
    rd_iuniform64 = 1
    rd_iuniform   = 2
  CODE:
#if IVSIZE >= 8
    if (ix)
      RETVAL = rds_liuniform(state, lower, upper);
#else
    if (ix == 1)
      XSRETURN_UNDEF;
#endif
    else
      RETVAL = rds_iuniform(state, (int32_t)lower, (int32_t)upper);
  OUTPUT:
    RETVAL

IV
_rd_iuniform32(IV lower, IV upper);
  ALIAS:
    _rd_iuniform64 = 1
    _rd_iuniform   = 2
  CODE:
#if IVSIZE >= 8
    if (ix)
      RETVAL = rd_liuniform(lower, upper);
#else
    if (ix == 1)
      XSRETURN_UNDEF;
#endif
    else
      RETVAL = rd_iuniform((int32_t)lower, (int32_t)upper);
  OUTPUT:
    RETVAL

NV
rd_uniform(mt_state* state, NV lower, NV upper);
  ALIAS:
    rd_luniform = 1
  CODE:
    RETVAL = (ix == 0) ? rds_uniform(state, lower, upper)
                       : rds_luniform(state, lower, upper);
  OUTPUT:
    RETVAL

NV
_rd_uniform(NV lower, NV upper);
  ALIAS:
    _rd_luniform = 1
  CODE:
    RETVAL = (ix == 0) ? rd_uniform(lower, upper)
                       : rd_luniform(lower, upper);
  OUTPUT:
    RETVAL

NV

MTwist.xs  view on Meta::CPAN

                       : rd_lnormal(mean, sigma);
  OUTPUT:
    RETVAL

NV
rd_triangular(mt_state* state, NV lower, NV upper, NV mode)
  ALIAS:
    rd_ltriangular = 1
  CODE:
    RETVAL = (ix == 0) ? rds_triangular(state, lower, upper, mode)
                       : rds_ltriangular(state, lower, upper, mode);
  OUTPUT:
    RETVAL

NV
_rd_triangular(NV lower, NV upper, NV mode)
  ALIAS:
    _rd_ltriangular = 1
  CODE:
    RETVAL = (ix == 0) ? rd_triangular(lower, upper, mode)
                       : rd_ltriangular(lower, upper, mode);
  OUTPUT:
    RETVAL

int
savestate(mt_state* state, SV* file_sv)

int
_savestate(SV* file_sv)
  CODE:
    RETVAL = savestate(NULL, file_sv);
  OUTPUT:
    RETVAL

int
loadstate(mt_state* state, SV* file_sv)

int
_loadstate(SV* file_sv)
  CODE:
    RETVAL = loadstate(NULL, file_sv);
  OUTPUT:
    RETVAL

SV*
getstate(mt_state* state)
  CODE:
    RETVAL = newSVpvn((char*)state, sizeof(mt_state));
  OUTPUT:
    RETVAL

SV*
_getstate()
  CODE:
    RETVAL = newSVpvn((char*)&mt_default_state, sizeof(mt_state));
  OUTPUT:
    RETVAL

void
setstate(mt_state* state, SV* sv_state)
  PPCODE:
    set_state_from_sv(sv_state, state);

void
_setstate(SV* sv_state)
  PPCODE:
    set_state_from_sv(sv_state, &mt_default_state);

BOOT:
{
  HV *stash;

  stash = gv_stashpv("Math::Random::MTwist", TRUE);
  newCONSTSUB(stash, "HAS_UINT64_T", newSViv(HAS_UINT64_T));
  newCONSTSUB(stash, "NVMANTBITS",   newSViv(NVMANTBITS));
}

# vim: set ts=2 sw=2 sts=2 expandtab:



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