star-sp

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

commit d5a0eb6f6f9ee0b1a994e1839056d0cb57f9f9ea
parent c982f45466ece6038a3dea103f07fc40a3aeaad0
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 24 Nov 2015 15:59:34 +0100

Add and test the ssp_rng_proxy_create_from_rng function

Create a proxy RNG from a RNG instance, i.e. use its type as well as its
state to initialise the proxy RNG.

Diffstat:
Msrc/ssp.h | 13+++++++++++--
Msrc/ssp_rng.c | 2+-
Msrc/ssp_rng_proxy.c | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/test_ssp_rng_proxy.c | 52+++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 133 insertions(+), 5 deletions(-)

diff --git a/src/ssp.h b/src/ssp.h @@ -143,7 +143,7 @@ ssp_rng_ref_get SSP_API res_T ssp_rng_get_type - (struct ssp_rng* rng, + (const struct ssp_rng* rng, struct ssp_rng_type* type); SSP_API res_T @@ -214,6 +214,15 @@ ssp_rng_proxy_create const size_t nbuckets, struct ssp_rng_proxy** proxy); +/* Build the proxy RNG from the state of `rng'. Note that `rng' is read only + * argument, i.e. it is not used internally. */ +SSP_API res_T +ssp_rng_proxy_create_from_rng + (struct mem_allocator* allocator, + const struct ssp_rng* rng, + const size_t nbuckets, + struct ssp_rng_proxy** proxy); + SSP_API res_T ssp_rng_proxy_ref_get (struct ssp_rng_proxy* proxy); @@ -232,7 +241,7 @@ ssp_rng_proxy_create_rng SSP_API res_T ssp_rng_proxy_get_type - (struct ssp_rng_proxy* proxy, + (const struct ssp_rng_proxy* proxy, struct ssp_rng_type* type); /******************************************************************************* diff --git a/src/ssp_rng.c b/src/ssp_rng.c @@ -613,7 +613,7 @@ ssp_rng_ref_put(struct ssp_rng* rng) } res_T -ssp_rng_get_type(struct ssp_rng* rng, struct ssp_rng_type* type) +ssp_rng_get_type(const struct ssp_rng* rng, struct ssp_rng_type* type) { if(!rng || !type) return RES_BAD_ARG; *type = rng->type; diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c @@ -439,6 +439,75 @@ error: } res_T +ssp_rng_proxy_create_from_rng + (struct mem_allocator* mem_allocator, + const struct ssp_rng* rng, + const size_t nbuckets, + struct ssp_rng_proxy** out_proxy) +{ + struct mem_allocator* allocator = NULL; + struct ssp_rng_proxy* proxy = NULL; + struct ssp_rng_type type; + FILE* stream = NULL; + res_T res = RES_OK; + + if(!rng || !out_proxy || !nbuckets) { + res = RES_BAD_ARG; + goto error; + } + + allocator = mem_allocator ? mem_allocator : &mem_default_allocator; + proxy = (struct ssp_rng_proxy*) + MEM_CALLOC(allocator, 1, sizeof(struct ssp_rng_proxy)); + if(!proxy) { + res = RES_MEM_ERR; + goto error; + } + proxy->allocator = allocator; + ref_init(&proxy->ref); + + res = ssp_rng_get_type(rng, &type); + if(res != RES_OK) goto error; + + res = ssp_rng_create(allocator, &type, &proxy->rng); + if(res != RES_OK) goto error; + proxy->type = type; + + stream = tmpfile(); + if(!stream) { + res = RES_IO_ERR; + goto error; + } + + res = ssp_rng_write(rng, stream); + if(res != RES_OK) goto error; + + rewind(stream); + res = ssp_rng_read(proxy->rng, stream); + if(res != RES_OK) goto error; + + proxy->mutex = mutex_create(); + if(!proxy->mutex) { + res = RES_MEM_ERR; + goto error; + } + + res = rng_proxy_setup(proxy, nbuckets); + if(res != RES_OK) goto error; + +exit: + if(stream) fclose(stream); + if(out_proxy) *out_proxy = proxy; + return res; +error: + if(proxy) { + SSP(rng_proxy_ref_put(proxy)); + proxy = NULL; + } + goto exit; +} + +res_T ssp_rng_proxy_ref_get(struct ssp_rng_proxy* proxy) { if(!proxy) return RES_BAD_ARG; @@ -498,7 +567,7 @@ error: res_T ssp_rng_proxy_get_type - (struct ssp_rng_proxy* proxy, + (const struct ssp_rng_proxy* proxy, struct ssp_rng_type* type) { if(!proxy || !type) return RES_BAD_ARG; diff --git a/src/test_ssp_rng_proxy.c b/src/test_ssp_rng_proxy.c @@ -67,6 +67,7 @@ main(int argc, char** argv) CHECK(ssp_rng_proxy_ref_get(proxy), RES_OK); CHECK(ssp_rng_proxy_ref_put(NULL), RES_BAD_ARG); CHECK(ssp_rng_proxy_ref_put(proxy), RES_OK); + CHECK(ssp_rng_proxy_ref_put(proxy), RES_OK); CHECK(ssp_rng_proxy_create(&allocator, &ssp_rng_mt19937_64, 4, &proxy), RES_OK); @@ -111,7 +112,7 @@ main(int argc, char** argv) #define COUNT 4605307 ssp_rng_discard(rng1[0], COUNT); ssp_rng_discard(rng3, COUNT+1); - for (i = 0; i < COUNT; i++) ssp_rng_get(rng2[0]); + FOR_EACH(i, 0, COUNT) ssp_rng_get(rng2[0]); CHECK(ssp_rng_get(rng1[0]), ssp_rng_get(rng2[0])); CHECK(ssp_rng_get(rng1[0]), ssp_rng_get(rng3)); @@ -120,7 +121,56 @@ main(int argc, char** argv) CHECK(ssp_rng_ref_put(rng2[0]), RES_OK); CHECK(ssp_rng_ref_put(rng3), RES_OK); + CHECK(ssp_rng_create(NULL, &ssp_rng_threefry, &rng[0]), RES_OK); + CHECK(ssp_rng_discard(rng[0], COUNT), RES_OK); + + CHECK(ssp_rng_proxy_create_from_rng(NULL, NULL, 0, NULL), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, rng[0], 0, NULL), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, NULL, 1, NULL), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, rng[0], 1, NULL), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, NULL, 0, &proxy), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, rng[0], 0, &proxy), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, NULL, 1, &proxy), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_from_rng(NULL, rng[0], 1, &proxy), RES_OK); + CHECK(ssp_rng_proxy_create_rng(proxy, 0, &rng[1]), RES_OK); + CHECK(ssp_rng_proxy_create_rng(proxy, 0, &rng[2]), RES_BAD_ARG); + CHECK(ssp_rng_proxy_create_rng(proxy, 1, &rng[2]), RES_BAD_ARG); + + CHECK(ssp_rng_get(rng[0]), ssp_rng_get(rng[1])); + CHECK(ssp_rng_get(rng[0]), ssp_rng_get(rng[1])); + CHECK(ssp_rng_get(rng[0]), ssp_rng_get(rng[1])); + CHECK(ssp_rng_get(rng[0]), ssp_rng_get(rng[1])); + + CHECK(ssp_rng_ref_put(rng[1]), RES_OK); + CHECK(ssp_rng_proxy_ref_put(proxy), RES_OK); + + CHECK(ssp_rng_proxy_create_from_rng(NULL, rng[0], 4, &proxy), RES_OK); + CHECK(ssp_rng_ref_put(rng[0]), RES_OK); + FOR_EACH(i, 0, 4) + CHECK(ssp_rng_proxy_create_rng(proxy, i, &rng[i]), RES_OK); + CHECK(ssp_rng_proxy_ref_put(proxy), RES_OK); + + CHECK(ssp_rng_get_type(rng[0], &type), RES_OK); + FOR_EACH(i, 1, 4) { + struct ssp_rng_type type2; + CHECK(ssp_rng_get_type(rng[i], &type2), RES_OK); + CHECK(ssp_rng_type_eq(&type, &type2), 1); + } + + FOR_EACH(i, 0, 2000000) { + uint64_t r[4]; + int j; + FOR_EACH(j, 0, 4) { + int k; + r[j] = ssp_rng_get(rng[j]); + FOR_EACH(k, 0, j) + NCHECK(r[k], r[j]); + } + } + FOR_EACH(i, 0, 4) CHECK(ssp_rng_ref_put(rng[i]), RES_OK); + check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); return 0; }