star-sp

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

commit ef00cd1a511c6c3836ab2e9141c37babbca0aec2
parent 0effa0cb821429b844c5f6a43d07035c05007c4a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  2 Dec 2020 10:02:53 +0100

Upd the ssp_rng_proxy_create2 function

Submit the list of input arguments through a variable of type struct
ssp_rng_proxy_create2_args. Add the possibility to initialise the proxy
RNG state.

Diffstat:
Msrc/ssp.h | 24++++++++++++++++++------
Msrc/ssp_rng_proxy.c | 149++++++++++++++++++++++++++++++++-----------------------------------------------
Msrc/test_ssp_rng_proxy.c | 107++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
3 files changed, 138 insertions(+), 142 deletions(-)

diff --git a/src/ssp.h b/src/ssp.h @@ -97,13 +97,29 @@ ssp_rng_type_eq(const struct ssp_rng_type* t0, const struct ssp_rng_type* t1) && t0->get == t1->get && t0->discard == t1->discard && t0->read == t1->read + && t0->read_cstr == t1->read_cstr && t0->write == t1->write + && t0->write_cstr == t1->write_cstr && t0->entropy == t1->entropy && t0->min == t1->min && t0->max == t1->max - && t0->sizeof_state == t1->sizeof_state; + && t0->sizeof_state == t1->sizeof_state + && t0->alignof_state == t1->alignof_state; } +/* Arguments of the ssp_rng_proxy_create2 function */ +struct ssp_rng_proxy_create2_args { + const struct ssp_rng* rng; /* Original RNG state. May be NULL*/ + const struct ssp_rng_type* type; /* Type of the RN if 'rng' is NULL */ + size_t sequence_offset; /* #RNs before the 1st valid sequence */ + size_t sequence_size; /* #RNs in a sequence */ + size_t sequence_pitch; /* #RNs between sequences. Must be >= sequence_size */ + size_t nbuckets; /* #buckets of continuous RNs in a sequence */ +}; +#define SSP_RNG_PROXY_CREATE2_ARGS_NULL__ {NULL, NULL, 0, 0, 0, 0} +static const struct ssp_rng_proxy_create2_args SSP_RNG_PROXY_CREATE2_ARGS_NULL = + SSP_RNG_PROXY_CREATE2_ARGS_NULL__; + BEGIN_DECLS /* David Jones's Keep It Simple Stupid builtin PRNG type. Suitable for fast @@ -252,11 +268,7 @@ ssp_rng_proxy_create_from_rng SSP_API res_T ssp_rng_proxy_create2 (struct mem_allocator* mem_allocator, - const struct ssp_rng_type* type, - const size_t sequence_offset, /* #RNs before the 1st valid sequence */ - const size_t sequence_size, /* #RNs in a sequence */ - const size_t sequence_pitch, /* #RNs between 2 consecutive sequence */ - const size_t nbuckets, /* #buckets in sequence */ + const struct ssp_rng_proxy_create2_args* args, struct ssp_rng_proxy** out_proxy); SSP_API res_T diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c @@ -545,126 +545,99 @@ ssp_rng_proxy_create const size_t nbuckets, struct ssp_rng_proxy** out_proxy) { + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; const size_t sz = BUCKET_SIZE_DEFAULT * nbuckets; - return ssp_rng_proxy_create2 - (mem_allocator, type, 0, sz, sz, nbuckets, out_proxy); + args.type = type; + args.sequence_offset = 0; + args.sequence_size = sz; + args.sequence_pitch = sz; + args.nbuckets = nbuckets; + return ssp_rng_proxy_create2(mem_allocator, &args, out_proxy); } res_T -ssp_rng_proxy_create2 +ssp_rng_proxy_create_from_rng (struct mem_allocator* mem_allocator, - const struct ssp_rng_type* type, - const size_t sequence_offset, /* #RNs before the 1st valid sequence */ - const size_t sequence_size, /* #RNs in a sequence */ - const size_t sequence_pitch, /* #RNs between 2 consecutive sequences */ - const size_t nbuckets, /* #buckets in a sequence */ + 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; - size_t i; - res_T res = RES_OK; - - if(!type || !out_proxy || !sequence_size || sequence_pitch < sequence_size - || !nbuckets || sequence_size < 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); - proxy->bucket_size = sequence_size / nbuckets; - proxy->sequence_bias = sequence_pitch - (proxy->bucket_size * nbuckets); - - res = ssp_rng_create(allocator, type, &proxy->rng); - if(res != RES_OK) goto error; - proxy->type = *type; - - res = ssp_rng_discard(proxy->rng, sequence_offset); - if(res != RES_OK) goto error; - - proxy->mutex = mutex_create(); - if(!proxy->mutex) { - res = RES_MEM_ERR; - goto error; - } - - FOR_EACH(i, 0, RNG_PROXY_SIGS_COUNT__) { - SIG_INIT(proxy->signals + i); - } - - res = rng_proxy_setup(proxy, sequence_pitch, nbuckets); - if(res != RES_OK) goto error; - -exit: - if(out_proxy) *out_proxy = proxy; - return res; -error: - if(proxy) { - SSP(rng_proxy_ref_put(proxy)); - proxy = NULL; - } - goto exit; + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; + const size_t sz = BUCKET_SIZE_DEFAULT * nbuckets; + args.rng = rng; + args.sequence_offset = 0; + args.sequence_size = sz; + args.sequence_pitch = sz; + args.nbuckets = nbuckets; + return ssp_rng_proxy_create2(mem_allocator, &args, out_proxy); } res_T -ssp_rng_proxy_create_from_rng +ssp_rng_proxy_create2 (struct mem_allocator* mem_allocator, - const struct ssp_rng* rng, - const size_t nbuckets, + const struct ssp_rng_proxy_create2_args* args, struct ssp_rng_proxy** out_proxy) { + struct darray_char buf; struct mem_allocator* allocator = NULL; struct ssp_rng_proxy* proxy = NULL; - struct ssp_rng_type type; - FILE* stream = NULL; - size_t sequence_pitch; size_t i; res_T res = RES_OK; - if(!rng || !out_proxy || !nbuckets) { + darray_char_init(mem_allocator, &buf); + + if(!args + || !out_proxy + || !args->sequence_size + || !args->nbuckets + || (!args->type && !args->rng) + || args->sequence_pitch < args->sequence_size + || args->sequence_size < args->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)); + proxy = (struct ssp_rng_proxy*)MEM_CALLOC(allocator, 1, sizeof(*proxy)); if(!proxy) { res = RES_MEM_ERR; goto error; } proxy->allocator = allocator; ref_init(&proxy->ref); - proxy->bucket_size = BUCKET_SIZE_DEFAULT; - proxy->sequence_bias = 0; - sequence_pitch = proxy->bucket_size * nbuckets; + proxy->bucket_size = args->sequence_size / args->nbuckets; + proxy->sequence_bias = + args->sequence_pitch - (proxy->bucket_size * args->nbuckets); - res = ssp_rng_get_type(rng, &type); - if(res != RES_OK) goto error; + /* Create the proxy RNG in its default state */ + if(!args->rng) { + res = ssp_rng_create(allocator, args->type, &proxy->rng); + if(res != RES_OK) goto error; + proxy->type = *args->type; - res = ssp_rng_create(allocator, &type, &proxy->rng); - if(res != RES_OK) goto error; - proxy->type = type; + /* Create the proxy RNG from a submitted RNG state */ + } else { + size_t len; - stream = tmpfile(); - if(!stream) { - res = RES_IO_ERR; - goto error; - } + /* Create the RNG proxy of the type of the submitted RNG. Simply Ignore the + * submitted RNG type if any */ + res = ssp_rng_get_type(args->rng, &proxy->type); + if(res != RES_OK) goto error; + res = ssp_rng_create(allocator, &proxy->type, &proxy->rng); + if(res != RES_OK) goto error; - res = ssp_rng_write(rng, stream); - if(res != RES_OK) goto error; + /* Initialise the RNG proxy state from the state of the submitted RNG */ + res = ssp_rng_write_cstr(args->rng, NULL, 0, &len); + if(res != RES_OK) goto error; + res = darray_char_resize(&buf, len+1/*Null char*/); + if(res != RES_OK) goto error; + res = ssp_rng_write_cstr(args->rng, darray_char_data_get(&buf), len+1, &len); + if(res != RES_OK) goto error; + res = ssp_rng_read_cstr(proxy->rng, darray_char_cdata_get(&buf)); + if(res != RES_OK) goto error; + } - rewind(stream); - res = ssp_rng_read(proxy->rng, stream); + res = ssp_rng_discard(proxy->rng, args->sequence_offset); if(res != RES_OK) goto error; proxy->mutex = mutex_create(); @@ -677,11 +650,11 @@ ssp_rng_proxy_create_from_rng SIG_INIT(proxy->signals + i); } - res = rng_proxy_setup(proxy, sequence_pitch, nbuckets); + res = rng_proxy_setup(proxy, args->sequence_pitch, args->nbuckets); if(res != RES_OK) goto error; exit: - if(stream) fclose(stream); + darray_char_release(&buf); if(out_proxy) *out_proxy = proxy; return res; error: diff --git a/src/test_ssp_rng_proxy.c b/src/test_ssp_rng_proxy.c @@ -73,52 +73,50 @@ test_creation(void) static void test_creation2(void) { - const struct ssp_rng_type* type = &ssp_rng_mt19937_64; + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; struct ssp_rng_proxy* proxy; - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 0, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 0, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 0, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 0, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 32, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 32, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 32, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 0, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 0, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 0, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 0, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 0, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 32, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 32, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 32, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 1, NULL) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 0, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 0, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 0, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 0, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 32, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 32, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 32, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 0, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 0, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 0, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 0, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 0, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 0, 32, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 0, 32, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, NULL, 0, 32, 32, 1, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 1, &proxy) == RES_OK); + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG); + + args.type = &ssp_rng_mt19937_64; + args.sequence_offset = 0; + args.sequence_size = 32; + args.sequence_pitch = 32; + args.nbuckets = 1; + CHK(ssp_rng_proxy_create2(NULL, &args, NULL) == RES_BAD_ARG); + + args.type = NULL; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG); + args.type = &ssp_rng_mt19937_64; + args.sequence_size= 0; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG); + args.sequence_size = 32; + args.sequence_pitch = 0; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG); + args.sequence_pitch = 32; + args.nbuckets = 0; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG); + args.nbuckets = 33; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG); + args.nbuckets = 1; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); + CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); + + args.nbuckets = 4; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 4, &proxy) == RES_OK); + args.nbuckets = 5; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 32, &proxy) == RES_OK); + args.nbuckets = 32; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); - CHK(ssp_rng_proxy_create2(NULL, type, 0, 32, 32, 33, &proxy) == RES_BAD_ARG); - CHK(ssp_rng_proxy_create2 - (&mem_default_allocator, type, 1024, 32, 32, 4, &proxy) == RES_OK); + args.sequence_offset = 1024; + args.nbuckets = 4; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK); } @@ -165,6 +163,7 @@ test_rng_from_proxy(void) static void test_rng_from_proxy2(void) { + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; struct ssp_rng_proxy* proxy[2]; struct ssp_rng* rng[4]; const size_t block_sz = 99; @@ -177,8 +176,11 @@ test_rng_from_proxy2(void) CHK((r[2] = mem_alloc(sizeof(uint64_t)*nrands)) != NULL); CHK((r[3] = mem_alloc(sizeof(uint64_t)*nrands)) != NULL); - CHK(ssp_rng_proxy_create2 - (NULL, &ssp_rng_mt19937_64, 0, block_sz, block_sz, 4, &proxy[0]) == RES_OK); + args.type = &ssp_rng_mt19937_64; + args.sequence_size = block_sz; + args.sequence_pitch = block_sz; + args.nbuckets = 4; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy[0]) == RES_OK); CHK(ssp_rng_proxy_create_rng(proxy[0], 0, &rng[0]) == RES_OK); CHK(ssp_rng_proxy_create_rng(proxy[0], 1, &rng[1]) == RES_OK); @@ -211,10 +213,15 @@ test_rng_from_proxy2(void) CHK(ssp_rng_ref_put(rng[2]) == RES_OK); CHK(ssp_rng_ref_put(rng[3]) == RES_OK); - CHK(ssp_rng_proxy_create2(NULL, &ssp_rng_mt19937_64, - 0, block_sz, 2*block_sz, 2, &proxy[0]) == RES_OK); - CHK(ssp_rng_proxy_create2(NULL, &ssp_rng_mt19937_64, - block_sz, block_sz, 2*block_sz, 2, &proxy[1]) == RES_OK); + args.type = &ssp_rng_mt19937_64; + args.sequence_size = block_sz; + args.sequence_pitch = 2*block_sz; + args.nbuckets = 2; + + args.sequence_offset = 0; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy[0]) == RES_OK); + args.sequence_offset = block_sz; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy[1]) == RES_OK); CHK(ssp_rng_proxy_create_rng(proxy[0], 0, &rng[0]) == RES_OK); CHK(ssp_rng_proxy_create_rng(proxy[0], 1, &rng[1]) == RES_OK); @@ -420,17 +427,21 @@ test_write(void) static void test_cache(void) { + struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL; struct ssp_rng_proxy* proxy; struct ssp_rng* rng0; struct ssp_rng* rng1; struct ssp_rng* rng; - const size_t nbuckets = 2; - const size_t sequence_pitch = 2/*#RNs per bucket*/ * nbuckets; const size_t nrands = 20000; size_t i; - CHK(ssp_rng_proxy_create2(NULL, &ssp_rng_mt19937_64, 0, sequence_pitch, - sequence_pitch, nbuckets, &proxy) == RES_OK); + /* Create a proxy with a very small sequence size of 2 RNs per bucket in + * order to maximize the number of cached states. */ + args.type = &ssp_rng_mt19937_64; + args.sequence_size = 4; + args.sequence_pitch = 4; + args.nbuckets = 2; + CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_OK); CHK(ssp_rng_proxy_create_rng(proxy, 0, &rng0) == RES_OK); CHK(ssp_rng_proxy_create_rng(proxy, 1, &rng1) == RES_OK);