commit 6c7fa93fd5e0a6de489c8c27b391f70e5fe69892
parent e8468cc4e3751edb40218fbdeaae2fac3ba1d3c9
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 1 Jun 2015 17:54:25 +0200
Pave the way to new generators that can fail in init or set.
This is a new incompatible API version: 0.1.0.
Also rename the uniform_int API call into uniform_uint64 to better reflect what it really does
and add a new API call entropy in the spirit of the C++11 one.
Diffstat:
5 files changed, 72 insertions(+), 30 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -60,7 +60,7 @@ rcmake_append_runtime_dirs(_runtime_dirs RSys)
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 0)
+set(VERSION_MINOR 1)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
diff --git a/src/ssp.h b/src/ssp.h
@@ -63,17 +63,18 @@ struct mem_allocator;
/* Generic Random Number Generator type descriptor */
struct ssp_rng_type {
- void (*init)(struct mem_allocator* allocator, void* state);
+ res_T (*init)(struct mem_allocator* allocator, void* state);
void (*release)(void* state);
- void (*set)(void* state, const uint64_t seed);
+ res_T (*set)(void* state, const uint64_t seed);
uint64_t (*get)(void* state);
- uint64_t (*uniform_int)(void* state, const uint64_t min, const uint64_t max);
+ uint64_t (*uniform_uint64)(void* state, const uint64_t min, const uint64_t max);
double (*uniform_double)(void* state, const double min, const double max);
double (*canonical)(void* state);
res_T (*read)(void* state, FILE* file);
res_T (*write)(const void* state, FILE* file);
-
+ double (*entropy)(const void* state);
+
uint64_t min;
uint64_t max;
size_t sizeof_state;
@@ -118,7 +119,7 @@ ssp_rng_get
/* Uniform random integer distribution in [lower, upper] */
SSP_API uint64_t
-ssp_rng_uniform_int
+ssp_rng_uniform_uint64
(struct ssp_rng* rng,
const uint64_t lower,
const uint64_t upper);
@@ -153,6 +154,10 @@ ssp_rng_read
(struct ssp_rng* rng,
FILE* stream);
+SSP_API double
+ssp_rng_entropy
+(const struct ssp_rng* rng);
+
/*******************************************************************************
* Proxy of Random Number Generators - It manages a list of `nbuckets' RNGs
* whose each have independant `infinite' random sequences
diff --git a/src/ssp_rng.c b/src/ssp_rng.c
@@ -48,13 +48,12 @@
#include <sstream>
-
/*******************************************************************************
* KISS PRNG
******************************************************************************/
struct rng_kiss { uint32_t x, y, z, c; };
-static void
+static res_T
rng_kiss_set(void* data, const size_t seed)
{
struct rng_kiss* kiss = (struct rng_kiss*)data;
@@ -67,6 +66,7 @@ rng_kiss_set(void* data, const size_t seed)
kiss->z = (uint32_t)rng_mt();
/* Offset c by 1 to avoid z=c=0; should be less than 698769069 */
kiss->c = (uint32_t)rng_mt() % 698769068 + 1;
+ return RES_OK;
}
static uint64_t
@@ -87,7 +87,7 @@ rng_kiss_get(void* data)
}
static uint64_t
-rng_kiss_uniform_int(void* data, const uint64_t lower, const uint64_t upper)
+rng_kiss_uniform_uint64(void* data, const uint64_t lower, const uint64_t upper)
{
ASSERT(lower <= upper);
return (uint32_t)
@@ -130,11 +130,12 @@ rng_kiss_write(const void* data, FILE* file)
return res < 0 ? RES_IO_ERR : RES_OK;
}
-static void
+static res_T
rng_kiss_init(struct mem_allocator* allocator, void* data)
{
(void)allocator;
rng_kiss_set(data, 0);
+ return RES_OK;
}
static void
@@ -143,17 +144,25 @@ rng_kiss_release(void* data)
(void)data;
}
+static double
+rng_kiss_entropy(const void* data)
+{
+ (void)data;
+ return 0.;
+}
+
/* Exported type */
const struct ssp_rng_type ssp_rng_kiss = {
rng_kiss_init,
rng_kiss_release,
rng_kiss_set,
rng_kiss_get,
- rng_kiss_uniform_int,
+ rng_kiss_uniform_uint64,
rng_kiss_uniform_double,
rng_kiss_canonical,
rng_kiss_read,
rng_kiss_write,
+ rng_kiss_entropy,
0,
UINT32_MAX,
sizeof(struct rng_kiss)
@@ -163,12 +172,13 @@ const struct ssp_rng_type ssp_rng_kiss = {
* C++11 PRNG
******************************************************************************/
template<typename RNG>
-static void
+static res_T
rng_cxx_set(void* data, const uint64_t seed)
{
RNG* rng = (RNG*)data;
ASSERT(rng);
rng->seed((unsigned long)seed);
+ return RES_OK;
}
template<typename RNG>
@@ -182,7 +192,7 @@ rng_cxx_get(void* data)
template<typename RNG>
static uint64_t
-rng_cxx_uniform_int
+rng_cxx_uniform_uint64
(void* data, const uint64_t lower, const uint64_t upper)
{
RNG* rng = (RNG*)data;
@@ -241,12 +251,13 @@ rng_cxx_read(void* data, FILE* file)
}
template<typename RNG>
-static void
+static res_T
rng_cxx_init(struct mem_allocator* allocator, void* data)
{
(void)allocator;
ASSERT(data);
new (data) RNG;
+ return RES_OK;
}
template<typename RNG>
@@ -259,17 +270,26 @@ rng_cxx_release(void* data)
rng->~RNG();
}
+template<typename RNG>
+static double
+rng_cxx_entropy(const void* data)
+{
+ (void)data;
+ return 0;
+}
+
/* 64-bits Mersenne Twister PRNG */
const struct ssp_rng_type ssp_rng_mt19937_64 = {
rng_cxx_init<RAN_NAMESPACE::mt19937_64>,
rng_cxx_release<RAN_NAMESPACE::mt19937_64>,
rng_cxx_set<RAN_NAMESPACE::mt19937_64>,
rng_cxx_get<RAN_NAMESPACE::mt19937_64>,
- rng_cxx_uniform_int<RAN_NAMESPACE::mt19937_64>,
+ rng_cxx_uniform_uint64<RAN_NAMESPACE::mt19937_64>,
rng_cxx_uniform_double<RAN_NAMESPACE::mt19937_64>,
rng_cxx_canonical<RAN_NAMESPACE::mt19937_64>,
rng_cxx_read<RAN_NAMESPACE::mt19937_64>,
rng_cxx_write<RAN_NAMESPACE::mt19937_64>,
+ rng_cxx_entropy<RAN_NAMESPACE::mt19937_64>,
RAN_NAMESPACE::mt19937_64::min(),
RAN_NAMESPACE::mt19937_64::max(),
sizeof(RAN_NAMESPACE::mt19937_64)
@@ -281,11 +301,12 @@ const struct ssp_rng_type ssp_rng_ranlux48 = {
rng_cxx_release<RAN_NAMESPACE::ranlux48>,
rng_cxx_set<RAN_NAMESPACE::ranlux48>,
rng_cxx_get<RAN_NAMESPACE::ranlux48>,
- rng_cxx_uniform_int<RAN_NAMESPACE::ranlux48>,
+ rng_cxx_uniform_uint64<RAN_NAMESPACE::ranlux48>,
rng_cxx_uniform_double<RAN_NAMESPACE::ranlux48>,
rng_cxx_canonical<RAN_NAMESPACE::ranlux48>,
rng_cxx_read<RAN_NAMESPACE::ranlux48>,
rng_cxx_write<RAN_NAMESPACE::ranlux48>,
+ rng_cxx_entropy<RAN_NAMESPACE::ranlux48>,
RAN_NAMESPACE::ranlux48::min(),
RAN_NAMESPACE::ranlux48::max(),
sizeof(RAN_NAMESPACE::ranlux48)
@@ -302,11 +323,12 @@ check_type(const struct ssp_rng_type* type)
&& NULL != type->release
&& NULL != type->set
&& NULL != type->get
- && NULL != type->uniform_int
+ && NULL != type->uniform_uint64
&& NULL != type->uniform_double
&& NULL != type->canonical
&& NULL != type->read
&& NULL != type->write
+ && NULL != type->entropy
&& type->min <= type->max;
}
@@ -393,11 +415,11 @@ ssp_rng_get(struct ssp_rng* rng)
}
uint64_t
-ssp_rng_uniform_int
+ssp_rng_uniform_uint64
(struct ssp_rng* rng, const uint64_t lower, const uint64_t upper)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.uniform_int(rng->state, lower, upper);
+ return rng->type.uniform_uint64(rng->state, lower, upper);
}
double
@@ -433,8 +455,7 @@ res_T
ssp_rng_set(struct ssp_rng* rng, const uint64_t seed)
{
if(!rng) return RES_BAD_ARG;
- rng->type.set(rng->state, seed);
- return RES_OK;
+ return rng->type.set(rng->state, seed);
}
res_T
@@ -451,6 +472,13 @@ ssp_rng_write(const struct ssp_rng* rng, FILE* stream)
return rng->type.write(rng->state, stream);
}
+double
+ssp_rng_entropy(const struct ssp_rng* rng)
+{
+ if (!rng) FATAL("The Random Number Generator is NULL\n");
+ return rng->type.entropy(rng->state);
+}
+
#ifdef COMPILER_CL
#pragma warning(pop)
#endif
diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c
@@ -171,11 +171,11 @@ rng_bucket_next_ran_pool(struct rng_bucket* rng)
rng->count = BUCKET_SIZE;
}
-static void
+static res_T
rng_bucket_set(void* data, const uint64_t seed)
{
(void)data, (void)seed;
- FATAL("The seed can't be set explicitly on bucket RNGs\n");
+ return RES_BAD_OP;
}
static uint64_t
@@ -189,14 +189,14 @@ rng_bucket_get(void* data)
}
static uint64_t
-rng_bucket_uniform_int
+rng_bucket_uniform_uint64
(void* data, const uint64_t lower, const uint64_t upper)
{
struct rng_bucket* rng = (struct rng_bucket*)data;
ASSERT(data);
if(!rng->count) rng_bucket_next_ran_pool(rng);
--rng->count;
- return ssp_rng_uniform_int(rng->pool, lower, upper);
+ return ssp_rng_uniform_uint64(rng->pool, lower, upper);
}
static double
@@ -223,17 +223,17 @@ static res_T
rng_bucket_read(void* data, FILE* file)
{
(void)data, (void)file;
- FATAL("A bucket RNG can't be de-serialized\n");
+ return RES_BAD_OP;
}
static res_T
rng_bucket_write(const void* data, FILE* file)
{
(void)data, (void)file;
- FATAL("A bucket RNG can't be serialized\n");
+ return RES_BAD_OP;
}
-static void
+static res_T
rng_bucket_init(struct mem_allocator* allocator, void* data)
{
struct rng_bucket* rng = (struct rng_bucket*)data;
@@ -243,6 +243,7 @@ rng_bucket_init(struct mem_allocator* allocator, void* data)
rng->pool = NULL;
rng->name = SIZE_MAX;
rng->count = 0;
+ return RES_OK;
}
static void
@@ -254,16 +255,24 @@ rng_bucket_release(void* data)
SSP(rng_proxy_ref_put(rng->proxy));
}
+static double
+rng_bucket_entropy(const void* data)
+{
+ (void)data;
+ return 0;
+}
+
static const struct ssp_rng_type rng_bucket = {
rng_bucket_init,
rng_bucket_release,
rng_bucket_set,
rng_bucket_get,
- rng_bucket_uniform_int,
+ rng_bucket_uniform_uint64,
rng_bucket_uniform_double,
rng_bucket_canonical,
rng_bucket_read,
rng_bucket_write,
+ rng_bucket_entropy,
0, /* Dummy value */
ULONG_MAX, /* Dummy value */
sizeof(struct rng_bucket)
diff --git a/src/test_ssp_rng.c b/src/test_ssp_rng.c
@@ -92,7 +92,7 @@ test_rng(const struct ssp_rng_type* type)
}
FOR_EACH(i, 0, NRAND) {
- datai0[i] = ssp_rng_uniform_int(rng, 1, 79);
+ datai0[i] = ssp_rng_uniform_uint64(rng, 1, 79);
CHECK(datai0[i] >= 1, 1);
CHECK(datai0[i] <= 79, 1);
}