star-sp

Random number generators and distributions
git clone git://git.meso-star.fr/star-sp.git
Log | Files | Refs | README | LICENSE

commit 0e55da9835f1afc59fa342544e00d94f1c15c158
parent b7e07af739449f04789ade3a82adf8acc83f73a4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  4 Dec 2015 15:33:25 +0100

Update the discrete random variate API

Diffstat:
Msrc/ssp.h | 8++++++--
Msrc/ssp_ran_discrete.c | 45+++++++++++++++++++++++++++++++++------------
Msrc/test_ssp_ran_discrete.c | 24+++++++++++++-----------
3 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/src/ssp.h b/src/ssp.h @@ -254,11 +254,15 @@ ssp_rng_proxy_get_type SSP_API res_T ssp_ran_discrete_create (struct mem_allocator* allocator, /* May be NULL <=> Use default allocator */ - const double* weights, - const size_t nweights, struct ssp_ran_discrete** ran); SSP_API res_T +ssp_ran_discrete_setup + (struct ssp_ran_discrete* discrete, + const double* weights, + const size_t nweights); + +SSP_API res_T ssp_ran_discrete_ref_get (struct ssp_ran_discrete* ran); diff --git a/src/ssp_ran_discrete.c b/src/ssp_ran_discrete.c @@ -72,18 +72,13 @@ ran_discrete_release(ref_T* ref) res_T ssp_ran_discrete_create (struct mem_allocator* mem_allocator, - const double* weights, - const size_t nweights, - struct ssp_ran_discrete** out_ran) + struct ssp_ran_discrete** out_ran) { struct mem_allocator* allocator = NULL; struct ssp_ran_discrete* ran = NULL; - double* cdf; - double* pdf; - size_t i; res_T res = RES_OK; - if(!weights || !nweights || !out_ran) { + if(!out_ran) { res = RES_BAD_ARG; goto error; } @@ -99,6 +94,33 @@ ssp_ran_discrete_create darray_double_init(allocator, &ran->cdf); darray_double_init(allocator, &ran->pdf); +exit: + if(out_ran) *out_ran = ran; + return res; +error: + if(ran) { + SSP(ran_discrete_ref_put(ran)); + ran = NULL; + } + goto exit; +} + +res_T +ssp_ran_discrete_setup + (struct ssp_ran_discrete* ran, + const double* weights, + const size_t nweights) +{ + double* cdf; + double* pdf; + size_t i; + res_T res = RES_OK; + + if(!ran || !weights || !nweights) { + res = RES_BAD_ARG; + goto error; + } + res = darray_double_resize(&ran->cdf, nweights); if(res != RES_OK) goto error; res = darray_double_resize(&ran->pdf, nweights); @@ -131,16 +153,15 @@ ssp_ran_discrete_create } exit: - if(out_ran) *out_ran = ran; return res; error: if(ran) { - SSP(ran_discrete_ref_put(ran)); - ran = NULL; + darray_double_clear(&ran->cdf); + darray_double_clear(&ran->pdf); } goto exit; } - + res_T ssp_ran_discrete_ref_get(struct ssp_ran_discrete* ran) { @@ -162,7 +183,7 @@ ssp_ran_discrete(struct ssp_rng* rng, struct ssp_ran_discrete* ran) { const double* found; double r; - ASSERT(rng && ran); + ASSERT(rng && ran && darray_double_size_get(&ran->cdf) != 0); r = ssp_rng_canonical(rng); found = (const double*)search_lower_bound(&r, diff --git a/src/test_ssp_ran_discrete.c b/src/test_ssp_ran_discrete.c @@ -52,14 +52,8 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); - CHECK(ssp_ran_discrete_create(NULL, NULL, 0, NULL), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, weights, 0, NULL), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, NULL, nweights, NULL), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, weights, nweights, NULL), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, NULL, 0, &ran), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, weights, 0, &ran), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, NULL, nweights, &ran), RES_BAD_ARG); - CHECK(ssp_ran_discrete_create(NULL, weights, nweights, &ran), RES_OK); + CHECK(ssp_ran_discrete_create(NULL, NULL), RES_BAD_ARG); + CHECK(ssp_ran_discrete_create(NULL, &ran), RES_OK); CHECK(ssp_ran_discrete_ref_get(NULL), RES_BAD_ARG); CHECK(ssp_ran_discrete_ref_get(ran), RES_OK); @@ -67,7 +61,16 @@ main(int argc, char** argv) CHECK(ssp_ran_discrete_ref_put(ran), RES_OK); CHECK(ssp_ran_discrete_ref_put(ran), RES_OK); - CHECK(ssp_ran_discrete_create(&allocator, weights, nweights, &ran), RES_OK); + CHECK(ssp_ran_discrete_create(&allocator, &ran), RES_OK); + + CHECK(ssp_ran_discrete_setup(NULL, NULL, 0), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(ran, NULL, 0), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(NULL, weights, 0), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(ran, weights, 0), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(NULL, NULL, nweights), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(ran, NULL, nweights), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(NULL, weights, nweights), RES_BAD_ARG); + CHECK(ssp_ran_discrete_setup(ran, weights, nweights), RES_OK); memset(tmp, 0, sizeof(tmp)); FOR_EACH(i, 0, NSAMPS) { @@ -83,9 +86,8 @@ main(int argc, char** argv) FOR_EACH(i, 0, nweights) { NCHECK(tmp[i], 0); } - CHECK(ssp_ran_discrete_ref_put(ran), RES_OK); - CHECK(ssp_ran_discrete_create(&allocator, weights, nweights-1, &ran), RES_OK); + CHECK(ssp_ran_discrete_setup(ran, weights, nweights-1), RES_OK); FOR_EACH(i, 0, NSAMPS) { const size_t k = ssp_ran_discrete(rng, ran); double pdf;