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:
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;