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