commit 69921a28f54332b506b651a1c39f8fec5dcdf763
parent 3a77feae140e281aeccfc67cf0e1f87b4da59f96
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 12 Apr 2016 11:27:08 +0200
Add and test the uniform_float and canonical_float distributions
Remove the uniform distributions from the ssp_type data structure. They
are defined generically through the "get, get_min, get_max" ssp_type
functors.
Diffstat:
4 files changed, 76 insertions(+), 137 deletions(-)
diff --git a/src/ssp.h b/src/ssp.h
@@ -70,9 +70,6 @@ struct ssp_rng_type {
uint64_t (*get)(void* state);
res_T(*discard)(void* state, uint64_t n);
- 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);
@@ -91,9 +88,6 @@ ssp_rng_type_eq(const struct ssp_rng_type* t0, const struct ssp_rng_type* t1)
&& t0->set == t1->set
&& t0->get == t1->get
&& t0->discard == t1->discard
- && t0->uniform_uint64 == t1->uniform_uint64
- && t0->uniform_double == t1->uniform_double
- && t0->canonical == t1->canonical
&& t0->read == t1->read
&& t0->write == t1->write
&& t0->entropy == t1->entropy
@@ -177,11 +171,22 @@ ssp_rng_uniform_double
const double lower,
const double upper);
+SSP_API float
+ssp_rng_uniform_float
+ (struct ssp_rng* rng,
+ const float lower,
+ const float upper);
+
/* Uniform random floating point distribution in [0, 1) */
SSP_API double
ssp_rng_canonical
(struct ssp_rng* rng);
+/* Uniform random single precision floating point distribution in [0, 1) */
+SSP_API float
+ssp_rng_canonical_float
+ (struct ssp_rng* rng);
+
SSP_API uint64_t
ssp_rng_min
(struct ssp_rng* rng);
diff --git a/src/ssp_rng.c b/src/ssp_rng.c
@@ -83,6 +83,20 @@
#define SQRT_2_PI 2.50662827463100050240
+class rng_cxx /* Wrap a SSP random generator into a CXX object */
+{
+public:
+ FINLINE rng_cxx(struct ssp_rng& rng) : rng(&rng) {}
+ FINLINE uint64_t operator()() { return ssp_rng_get(rng); }
+ FINLINE uint64_t min() const { return ssp_rng_min(rng); }
+ FINLINE uint64_t max() const { return ssp_rng_max(rng); }
+
+ typedef uint64_t result_type;
+
+private:
+ ssp_rng* rng;
+};
+
/*******************************************************************************
* KISS PRNG
******************************************************************************/
@@ -122,30 +136,6 @@ rng_kiss_get(void* data)
return (uint32_t)(kiss->x + kiss->y + kiss->z);
}
-static uint64_t
-rng_kiss_uniform_uint64(void* data, const uint64_t lower, const uint64_t upper)
-{
- ASSERT(lower <= upper);
- return (uint64_t)
- ( (double)rng_kiss_get(data)/(double)UINT32_MAX
- * (double)(upper - lower) + (double)lower);
-}
-
-static double
-rng_kiss_uniform_double(void* data, const double lower, const double upper)
-{
- ASSERT(lower <= upper);
- ASSERT(lower <= upper);
- return (double)rng_kiss_get(data)/(double)UINT32_MAX * (upper-lower) + lower;
-}
-
-
-static double
-rng_kiss_canonical(void* data)
-{
- return (double)rng_kiss_get(data) / ((double)UINT32_MAX + 1);
-}
-
static res_T
rng_kiss_read(void* data, FILE* file)
{
@@ -224,9 +214,6 @@ const struct ssp_rng_type ssp_rng_kiss = {
rng_kiss_set,
rng_kiss_get,
rng_kiss_discard,
- rng_kiss_uniform_uint64,
- rng_kiss_uniform_double,
- rng_kiss_canonical,
rng_kiss_read,
rng_kiss_write,
rng_kiss_entropy,
@@ -266,35 +253,6 @@ rng_cxx_get(void* data)
}
template<typename RNG>
-static uint64_t
-rng_cxx_uniform_uint64
- (void* data, const uint64_t lower, const uint64_t upper)
-{
- RNG* rng = (RNG*)data;
- ASSERT(rng && lower <= upper);
- return RAN_NAMESPACE::uniform_int_distribution<uint64_t>(lower, upper)(*rng);
-}
-
-template<typename RNG>
-static double
-rng_cxx_uniform_double
- (void* data, const double lower, const double upper)
-{
- RNG* rng = (RNG*)data;
- ASSERT(rng && lower <= upper);
- return RAN_NAMESPACE::uniform_real_distribution<>(lower, upper)(*rng);
-}
-
-template<typename RNG>
-static double
-rng_cxx_canonical(void* data)
-{
- RNG* rng = (RNG*)data;
- ASSERT(rng);
- return RAN_NAMESPACE::generate_canonical<double, 48>(*rng);
-}
-
-template<typename RNG>
static res_T
rng_cxx_write(const void* data, FILE* file)
{
@@ -403,9 +361,6 @@ const struct ssp_rng_type ssp_rng_mt19937_64 = {
rng_cxx_set<RAN_NAMESPACE::mt19937_64>,
rng_cxx_get<RAN_NAMESPACE::mt19937_64>,
rng_cxx_discard<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>,
@@ -421,9 +376,6 @@ const struct ssp_rng_type ssp_rng_ranlux48 = {
rng_cxx_set<RAN_NAMESPACE::ranlux48>,
rng_cxx_get<RAN_NAMESPACE::ranlux48>,
rng_cxx_discard<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>,
@@ -439,9 +391,6 @@ const struct ssp_rng_type ssp_rng_random_device = {
rng_cxx_set<RAN_NAMESPACE::random_device>,
rng_cxx_get<RAN_NAMESPACE::random_device>,
rng_cxx_discard<RAN_NAMESPACE::random_device>,
- rng_cxx_uniform_uint64<RAN_NAMESPACE::random_device>,
- rng_cxx_uniform_double<RAN_NAMESPACE::random_device>,
- rng_cxx_canonical<RAN_NAMESPACE::random_device>,
rng_cxx_read<RAN_NAMESPACE::random_device>,
rng_cxx_write<RAN_NAMESPACE::random_device>,
rng_cxx_entropy<RAN_NAMESPACE::random_device>,
@@ -480,9 +429,6 @@ const struct ssp_rng_type ssp_rng_threefry = {
rng_cxx_set<threefry_T>,
rng_cxx_get<threefry_T>,
rng_cxx_discard<threefry_T>,
- rng_cxx_uniform_uint64<threefry_T>,
- rng_cxx_uniform_double<threefry_T>,
- rng_cxx_canonical<threefry_T>,
rng_cxx_read<threefry_T>,
rng_cxx_write<threefry_T>,
rng_cxx_entropy<threefry_T>,
@@ -499,9 +445,6 @@ const struct ssp_rng_type ssp_rng_aes = {
rng_cxx_set<aes_T>,
rng_cxx_get<aes_T>,
rng_cxx_discard<aes_T>,
- rng_cxx_uniform_uint64<aes_T>,
- rng_cxx_uniform_double<aes_T>,
- rng_cxx_canonical<aes_T>,
rng_cxx_read<aes_T>,
rng_cxx_write<aes_T>,
rng_cxx_entropy<aes_T>,
@@ -522,9 +465,6 @@ check_type(const struct ssp_rng_type* type)
&& NULL != type->release
&& NULL != type->set
&& NULL != type->get
- && NULL != type->uniform_uint64
- && NULL != type->uniform_double
- && NULL != type->canonical
&& NULL != type->read
&& NULL != type->write
&& NULL != type->entropy
@@ -632,22 +572,44 @@ 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_uint64(rng->state, lower, upper);
+ rng_cxx rng_cxx(*rng);
+ return RAN_NAMESPACE::uniform_int_distribution<uint64_t>(lower, upper)(rng_cxx);
}
double
ssp_rng_uniform_double
- (struct ssp_rng* rng, double lower, double upper)
+ (struct ssp_rng* rng, const double lower, const double upper)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.uniform_double(rng->state, lower, upper);
+ rng_cxx rng_cxx(*rng);
+ return RAN_NAMESPACE::uniform_real_distribution<double>(lower, upper)(rng_cxx);
+}
+
+float
+ssp_rng_uniform_float
+ (struct ssp_rng* rng, const float lower, const float upper)
+{
+ if(!rng) FATAL("The Random Number Generator is NULL\n");
+ rng_cxx rng_cxx(*rng);
+ return RAN_NAMESPACE::uniform_real_distribution<float>(lower, upper)(rng_cxx);
}
double
ssp_rng_canonical(struct ssp_rng* rng)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.canonical(rng->state);
+ rng_cxx rng_cxx(*rng);
+ return RAN_NAMESPACE::generate_canonical
+ <double, std::numeric_limits<double>::digits>(rng_cxx);
+}
+
+float
+ssp_rng_canonical_float(struct ssp_rng* rng)
+{
+ if(!rng) FATAL("The Random Number Generator is NULL\n");
+ rng_cxx rng_cxx(*rng);
+ return RAN_NAMESPACE::generate_canonical
+ <float, std::numeric_limits<float>::digits>(rng_cxx);
}
uint64_t
@@ -702,20 +664,6 @@ ssp_rng_discard(struct ssp_rng* rng, uint64_t n)
/*******************************************************************************
* Exported distributions
******************************************************************************/
-class rng_cxx /* Wrap a SSP random generator into a CXX object */
-{
-public:
- FINLINE rng_cxx(struct ssp_rng& rng) : rng(&rng) {}
- FINLINE uint64_t operator()() { return ssp_rng_get(rng); }
- FINLINE uint64_t min() const { return ssp_rng_min(rng); }
- FINLINE uint64_t max() const { return ssp_rng_max(rng); }
-
- typedef uint64_t result_type;
-
-private:
- ssp_rng* rng;
-};
-
double
ssp_ran_exp(struct ssp_rng* rng, const double mu)
{
diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c
@@ -188,37 +188,6 @@ rng_bucket_get(void* data)
return ssp_rng_get(rng->pool);
}
-static uint64_t
-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_uint64(rng->pool, lower, upper);
-}
-
-static double
-rng_bucket_uniform_double(void* data, const double lower, const double 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_double(rng->pool, lower, upper);
-}
-
-static double
-rng_bucket_canonical(void* data)
-{
- struct rng_bucket* rng = (struct rng_bucket*)data;
- ASSERT(data);
- if(!rng->count) rng_bucket_next_ran_pool(rng);
- --rng->count;
- return ssp_rng_canonical(rng->pool);
-}
-
static res_T
rng_bucket_read(void* data, FILE* file)
{
@@ -281,9 +250,6 @@ static const struct ssp_rng_type RNG_BUCKET_NULL = {
rng_bucket_set,
rng_bucket_get,
rng_bucket_discard,
- rng_bucket_uniform_uint64,
- rng_bucket_uniform_double,
- rng_bucket_canonical,
rng_bucket_read,
rng_bucket_write,
rng_bucket_entropy,
diff --git a/src/test_ssp_rng.c b/src/test_ssp_rng.c
@@ -49,7 +49,8 @@ test_rng(const struct ssp_rng_type* type)
struct time t0, t1;
uint64_t datai0[NRAND];
uint64_t datai1[NRAND];
- double dataf[NRAND];
+ double datad[NRAND];
+ float dataf[NRAND];
char buf[512];
int i, j;
res_T r;
@@ -133,9 +134,19 @@ test_rng(const struct ssp_rng_type* type)
}
FOR_EACH(i, 0, NRAND) {
- dataf[i] = ssp_rng_uniform_double(rng, -5.0, 11.3);
- CHECK(dataf[i] >= -5.0, 1);
- CHECK(dataf[i] <= 11.3, 1);
+ datad[i] = ssp_rng_uniform_double(rng, -5.0, 11.3);
+ CHECK(datad[i] >= -5.0, 1);
+ CHECK(datad[i] <= 11.3, 1);
+ }
+ FOR_EACH(i, 0, NRAND) {
+ FOR_EACH(j, 0, NRAND) if(datad[i] != datad[j]) break;
+ NCHECK(j, NRAND);
+ }
+
+ FOR_EACH(i, 0, NRAND) {
+ dataf[i] = ssp_rng_uniform_float(rng, -1.0, 12.5);
+ CHECK(dataf[i] >= -1.0, 1);
+ CHECK(dataf[i] <= 12.5, 1);
}
FOR_EACH(i, 0, NRAND) {
FOR_EACH(j, 0, NRAND) if(dataf[i] != dataf[j]) break;
@@ -143,7 +154,16 @@ test_rng(const struct ssp_rng_type* type)
}
FOR_EACH(i, 0, NRAND) {
- dataf[i] = ssp_rng_canonical(rng);
+ datad[i] = ssp_rng_canonical(rng);
+ CHECK(datad[i] >= 0.0, 1);
+ CHECK(datad[i] < 1.0, 1);
+ FOR_EACH(j, 0, i) {
+ NCHECK(datad[i], datad[j]);
+ }
+ }
+
+ FOR_EACH(i, 0, NRAND) {
+ dataf[i] = ssp_rng_canonical_float(rng);
CHECK(dataf[i] >= 0.0, 1);
CHECK(dataf[i] < 1.0, 1);
FOR_EACH(j, 0, i) {