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