commit d54a904d6e0c37bad83371ff434aefa1484f6c89
parent a19b7723ac366fa0a1a5084e6493dce6420aa063
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 14 Oct 2021 14:21:46 +0200
Merge branch 'release_0.12'
Diffstat:
24 files changed, 371 insertions(+), 294 deletions(-)
diff --git a/README.md b/README.md
@@ -34,6 +34,24 @@ variable to the directory that contains the `boost` include directory.
## Release notes
+### Version 0.12
+
+Ensures C++11 compliance to correct gcc 11 compilation errors. On the other
+hand, this introduces API breaks.
+
+According to the C++11 standard, the min/max values of a
+UniformRandomBitGenerator must be static constant expressions. But until now,
+gcc has been flexible enough to allow the use of UniformRandomBitGenerators
+with regular min/max values. At run time, the caller could thus define its own
+RNG type as provided by the struct `ssp_rng_type` data structure.
+Unfortunately, since its version 11, gcc is more severe and refuses to compile
+this code.
+
+This version updates the API to respect this C++11 constraint. The
+`ssp_rng_type` is no longer a structure; it becomes an enumeration which is
+then instantiated internally in a specific UniformRandomBitGenerator with
+min/max values resolved at compilation time.
+
### Version 0.11.1
Sets the CMake minimum version to 3.1 in the Random123Config.cmake file: since
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -70,12 +70,17 @@ endif()
rcmake_append_runtime_dirs(_runtime_dirs RSys ${Boost_LIBRARY_DIRS})
+if(CMAKE_COMPILER_IS_GNUCXX)
+ # Random123 warning that cannot be disabled by a GCC pragma
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-expansion-to-defined")
+endif()
+
################################################################################
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 11)
-set(VERSION_PATCH 1)
+set(VERSION_MINOR 12)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SSP_FILES_SRC
diff --git a/src/ssp.h b/src/ssp.h
@@ -67,89 +67,53 @@ struct ssp_ranst_piecewise_linear_float;
/* Forward declaration of external types */
struct mem_allocator;
-/* Generic Random Number Generator type descriptor */
-struct ssp_rng_type {
- res_T (*init)(struct mem_allocator* allocator, void* state);
- void (*release)(void* state);
- res_T (*set)(void* state, const uint64_t seed);
-
- uint64_t (*get)(void* state);
- res_T (*discard)(void* state, uint64_t n);
- res_T (*read)(void* state, FILE* file);
- res_T (*read_cstr)(void* state, const char* cstr);
- res_T (*write)(const void* state, FILE* file);
- res_T (*write_cstr)(const void* state, char* buf, const size_t sz, size_t* len);
- double (*entropy)(const void* state);
-
- uint64_t min;
- uint64_t max;
- size_t sizeof_state;
- size_t alignof_state;
+enum ssp_rng_type {
+ /* David Jones's Keep It Simple Stupid builtin PRNG type. Suitable for fast
+ * basic randomness */
+ SSP_RNG_KISS,
+ /* 64-bits Mersenne Twister builtin PRNG type of Matsumoto and Nishimura */
+ SSP_RNG_MT19937_64,
+ /* 48-bits RANLUX builtin PRNG type of Lusher and James, 1994 */
+ SSP_RNG_RANLUX48,
+ /* A random_device RNG is a uniformly-distributed integer random number
+ * generator that produces non-deterministic random numbers. It may be
+ * implemented in terms of an implementation-defined pseudo-random number
+ * engine if a non-deterministic source (e.g. a hardware device) is not
+ * available to the implementation. In this case each random_device object
+ * may generate the same number sequence. */
+ SSP_RNG_RANDOM_DEVICE,
+ /* Counter Based RNG threefry of Salmon, Moraes, Dror & Shaw */
+ SSP_RNG_THREEFRY,
+#ifdef WITH_R123_AES
+ /* Counter Based RNG aes of Salmon, Moraes, Dror & Shaw */
+ SSP_RNG_AES,
+#endif
+ SSP_RNG_TYPES_COUNT__,
+ SSP_RNG_TYPE_NULL = SSP_RNG_TYPES_COUNT__
};
-static FINLINE char
-ssp_rng_type_eq(const struct ssp_rng_type* t0, const struct ssp_rng_type* t1)
-{
- ASSERT(t0 && t1);
- return t0->init == t1->init
- && t0->release == t1->release
- && t0->set == t1->set
- && 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->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 */
+ enum 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}
+#define SSP_RNG_PROXY_CREATE2_ARGS_NULL__ {NULL, SSP_RNG_TYPE_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
- * basic randomness */
-SSP_API const struct ssp_rng_type ssp_rng_kiss;
-/* 64-bits Mersenne Twister builtin PRNG type of Matsumoto and Nishimura, 2000 */
-SSP_API const struct ssp_rng_type ssp_rng_mt19937_64;
-/* 48-bits RANLUX builtin PRNG type of Lusher and James, 1994 */
-SSP_API const struct ssp_rng_type ssp_rng_ranlux48;
-/* A random_device RNG is a uniformly-distributed integer random number generator
- * that produces non-deterministic random numbers. It may be implemented in
- * terms of an implementation-defined pseudo-random number engine if a
- * non-deterministic source (e.g. a hardware device) is not available to the
- * implementation. In this case each random_device object may generate the same
- * number sequence. */
-SSP_API const struct ssp_rng_type ssp_rng_random_device;
-/* Counter Based RNG threefry of Salmon, Moraes, Dror & Shaw */
-SSP_API const struct ssp_rng_type ssp_rng_threefry;
-#ifdef WITH_R123_AES
-/* Counter Based RNG aes of Salmon, Moraes, Dror & Shaw */
-SSP_API const struct ssp_rng_type ssp_rng_aes;
-#endif
-
/*******************************************************************************
* Random Number Generator API
******************************************************************************/
SSP_API res_T
ssp_rng_create
(struct mem_allocator* allocator, /* May be NULL <=> Use default allocator */
- const struct ssp_rng_type* type,
+ const enum ssp_rng_type type,
struct ssp_rng** rng);
SSP_API res_T
@@ -163,7 +127,7 @@ ssp_rng_ref_get
SSP_API res_T
ssp_rng_get_type
(const struct ssp_rng* rng,
- struct ssp_rng_type* type);
+ enum ssp_rng_type* type);
SSP_API res_T
ssp_rng_set
@@ -252,7 +216,7 @@ ssp_rng_entropy
SSP_API res_T
ssp_rng_proxy_create
(struct mem_allocator* allocator, /* May be NULL <=> Use default allocator */
- const struct ssp_rng_type* type,
+ const enum ssp_rng_type type,
const size_t nbuckets,
struct ssp_rng_proxy** proxy);
@@ -300,7 +264,7 @@ ssp_rng_proxy_create_rng
SSP_API res_T
ssp_rng_proxy_get_type
(const struct ssp_rng_proxy* proxy,
- struct ssp_rng_type* type);
+ enum ssp_rng_type* type);
/*******************************************************************************
* Miscellaneous distributions
diff --git a/src/ssp_ran.c b/src/ssp_ran.c
@@ -49,19 +49,17 @@ cosf2sinf(const float d)
double
ssp_ran_exp(struct ssp_rng* rng, const double mu)
{
- ASSERT(rng && mu > 0);
- rng_cxx rng_cxx(*rng);
+ ASSERT(rng && mu >= 0);
RAN_NAMESPACE::exponential_distribution<double> distribution(mu);
- return distribution(rng_cxx);
+ return wrap_ran(*rng, distribution);
}
float
ssp_ran_exp_float(struct ssp_rng* rng, const float mu)
{
- ASSERT(rng && mu > 0);
- rng_cxx rng_cxx(*rng);
+ ASSERT(rng && mu >= 0);
RAN_NAMESPACE::exponential_distribution<float> distribution(mu);
- return distribution(rng_cxx);
+ return wrap_ran(*rng, distribution);
}
double
@@ -129,9 +127,8 @@ ssp_ran_gaussian
const double sigma)
{
ASSERT(rng);
- rng_cxx rng_cxx(*rng);
RAN_NAMESPACE::normal_distribution<double> distribution(mu, sigma);
- return distribution(rng_cxx);
+ return wrap_ran(*rng, distribution);
}
float
@@ -141,9 +138,8 @@ ssp_ran_gaussian_float
const float sigma)
{
ASSERT(rng);
- rng_cxx rng_cxx(*rng);
RAN_NAMESPACE::normal_distribution<float> distribution(mu, sigma);
- return distribution(rng_cxx);
+ return wrap_ran(*rng, distribution);
}
double
@@ -173,9 +169,8 @@ ssp_ran_lognormal
const double sigma)
{
ASSERT(rng);
- rng_cxx rng_cxx(*rng);
RAN_NAMESPACE::lognormal_distribution<double> distribution(zeta, sigma);
- return distribution(rng_cxx);
+ return wrap_ran(*rng, distribution);
}
float
@@ -185,9 +180,8 @@ ssp_ran_lognormal_float
const float sigma)
{
ASSERT(rng);
- rng_cxx rng_cxx(*rng);
RAN_NAMESPACE::lognormal_distribution<float> distribution(zeta, sigma);
- return distribution(rng_cxx);
+ return wrap_ran(*rng, distribution);;
}
double
diff --git a/src/ssp_ranst_discrete.c b/src/ssp_ranst_discrete.c
@@ -179,8 +179,7 @@ ssp_ranst_discrete_ref_put(struct ssp_ranst_discrete* ran)
size_t
ssp_ranst_discrete_get(struct ssp_rng* rng, const struct ssp_ranst_discrete* ran)
{
- class rng_cxx r(*rng);
- return ran->distrib->operator()(r);
+ return wrap_ran(*rng, *ran->distrib);
}
double
diff --git a/src/ssp_ranst_gaussian.c b/src/ssp_ranst_gaussian.c
@@ -248,18 +248,16 @@ double
ssp_ranst_gaussian_get
(const struct ssp_ranst_gaussian* ran, struct ssp_rng* rng)
{
- class rng_cxx r(*rng);
ASSERT(ran->K1 > 0);
- return ran->distrib->operator()(r);
+ return wrap_ran(*rng, *ran->distrib);
}
float
ssp_ranst_gaussian_float_get
(const struct ssp_ranst_gaussian_float* ran, struct ssp_rng* rng)
{
- class rng_cxx r(*rng);
ASSERT(ran->K1 > 0);
- return ran->distrib->operator()(r);
+ return wrap_ran(*rng, *ran->distrib);
}
double
diff --git a/src/ssp_ranst_piecewise_linear.c b/src/ssp_ranst_piecewise_linear.c
@@ -256,8 +256,7 @@ ssp_ranst_piecewise_linear_get
(const struct ssp_ranst_piecewise_linear* ran,
struct ssp_rng* rng)
{
- class rng_cxx r(*rng);
- return ran->distrib->operator()(r);
+ return wrap_ran(*rng, *ran->distrib);
}
float
@@ -265,8 +264,7 @@ ssp_ranst_piecewise_linear_float_get
(const struct ssp_ranst_piecewise_linear_float* ran,
struct ssp_rng* rng)
{
- class rng_cxx r(*rng);
- return ran->distrib->operator()(r);
+ return wrap_ran(*rng, *ran->distrib);
}
double
@@ -275,7 +273,7 @@ ssp_ranst_piecewise_linear_pdf
double x)
{
ASSERT(ran);
- if (x<ran->distrib->min() || x>ran->distrib->max())
+ if(x<ran->distrib->min() || x>ran->distrib->max())
return 0;
const auto& inter = ran->distrib->intervals();
@@ -311,4 +309,4 @@ ssp_ranst_piecewise_linear_float_pdf
return
((float)dens[idx+1] * (x-inter[idx]) + (float)dens[idx] * (inter[idx+1]-x))
/ (inter[idx+1] - inter[idx]);
-}
-\ No newline at end of file
+}
diff --git a/src/ssp_rng.c b/src/ssp_rng.c
@@ -34,32 +34,6 @@
#include <rsys/dynamic_array_char.h>
#include <rsys/mem_allocator.h>
-/* disable some warnings in Random123 includes */
-#ifdef COMPILER_GCC
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wconversion" /* unsafe conversion */
- #pragma GCC diagnostic ignored "-Wshadow"
- #pragma GCC diagnostic ignored "-Wunused-parameter" /* in Random123/aes.h */
-#elif defined(COMPILER_CL)
- #pragma warning(push)
- #pragma warning(disable:4100) /* unreferenced formal parameter */
- #pragma warning(disable:4127) /* conditional expression is constant */
- #pragma warning(disable:4512) /* assignment operator could not be generated */
- #pragma warning(disable:4521) /* multiple copy constructors specified */
-#endif
-
-#include <Random123/conventional/Engine.hpp>
-#include <Random123/threefry.h>
-#ifdef WITH_R123_AES
- #include <Random123/aes.h>
-#endif
-
-#ifdef COMPILER_GCC
- #pragma GCC diagnostic pop
-#elif defined(COMPILER_CL)
- #pragma warning(pop)
-#endif
-
#include <sstream>
#include <cstring>
#include <limits>
@@ -204,7 +178,7 @@ rng_kiss_discard(void* data, uint64_t n)
}
/* Exported type */
-const struct ssp_rng_type ssp_rng_kiss = {
+static const struct rng_desc rng_kiss = {
rng_kiss_init,
rng_kiss_release,
rng_kiss_set,
@@ -405,7 +379,7 @@ rng_cxx_entropy<RAN_NAMESPACE::random_device>(const void* data)
}
/* 64-bits Mersenne Twister PRNG */
-const struct ssp_rng_type ssp_rng_mt19937_64 = {
+static const struct rng_desc rng_mt19937_64 = {
rng_cxx_init<RAN_NAMESPACE::mt19937_64>,
rng_cxx_release<RAN_NAMESPACE::mt19937_64>,
rng_cxx_set<RAN_NAMESPACE::mt19937_64>,
@@ -423,7 +397,7 @@ const struct ssp_rng_type ssp_rng_mt19937_64 = {
};
/* 48-bits RANLUX PRNG */
-const struct ssp_rng_type ssp_rng_ranlux48 = {
+static const struct rng_desc rng_ranlux48 = {
rng_cxx_init<RAN_NAMESPACE::ranlux48>,
rng_cxx_release<RAN_NAMESPACE::ranlux48>,
rng_cxx_set<RAN_NAMESPACE::ranlux48>,
@@ -441,7 +415,7 @@ const struct ssp_rng_type ssp_rng_ranlux48 = {
};
/* random_device generator */
-const struct ssp_rng_type ssp_rng_random_device = {
+static const struct rng_desc rng_random_device = {
rng_cxx_init<RAN_NAMESPACE::random_device>,
rng_cxx_release<RAN_NAMESPACE::random_device>,
rng_cxx_set<RAN_NAMESPACE::random_device>,
@@ -483,7 +457,7 @@ rng_cxx_init<aes_T>(struct mem_allocator* allocator, void* data)
#endif
/* threefry generator */
-const struct ssp_rng_type ssp_rng_threefry = {
+static const struct rng_desc rng_threefry = {
rng_cxx_init<threefry_T>,
rng_cxx_release<threefry_T>,
rng_cxx_set<threefry_T>,
@@ -502,7 +476,7 @@ const struct ssp_rng_type ssp_rng_threefry = {
#ifdef WITH_R123_AES
/* aes generator */
-const struct ssp_rng_type ssp_rng_aes = {
+static const struct rng_desc rng_aes = {
rng_cxx_init<aes_T>,
rng_cxx_release<aes_T>,
rng_cxx_set<aes_T>,
@@ -523,20 +497,6 @@ const struct ssp_rng_type ssp_rng_aes = {
/*******************************************************************************
* Helper functions
******************************************************************************/
-static char
-check_type(const struct ssp_rng_type* type)
-{
- ASSERT(type);
- return NULL != type->init
- && NULL != type->release
- && NULL != type->set
- && NULL != type->get
- && NULL != type->read
- && NULL != type->write
- && NULL != type->entropy
- && type->min <= type->max;
-}
-
static void
rng_release(ref_T* ref)
{
@@ -544,8 +504,8 @@ rng_release(ref_T* ref)
ASSERT(ref);
rng = CONTAINER_OF(ref, struct ssp_rng, ref);
if(rng->state) {
- if(rng->type.release) {
- rng->type.release(rng->state);
+ if(rng->desc.release) {
+ rng->desc.release(rng->state);
}
MEM_RM(rng->allocator, rng->state);
}
@@ -558,56 +518,40 @@ rng_release(ref_T* ref)
res_T
ssp_rng_create
(struct mem_allocator* mem_allocator,
- const struct ssp_rng_type* type,
+ const enum ssp_rng_type type,
struct ssp_rng** out_rng)
{
- struct mem_allocator* allocator;
- struct ssp_rng* rng = NULL;
- size_t log2r;
res_T res = RES_OK;
- if(!type || !out_rng || !check_type(type)) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- allocator = mem_allocator ? mem_allocator : &mem_default_allocator;
-
- /* Align the rng on 16 bytes since its 'r' attrib is a long double that on
- * Linux 64-bits systems must be aligned on 16 bytes. */
- rng = (struct ssp_rng*)MEM_ALLOC_ALIGNED(allocator, sizeof(*rng), 16);
- if(!rng) {
- res = RES_MEM_ERR;
- goto error;
- }
- memset(rng, 0, sizeof(struct ssp_rng));
- rng->allocator = allocator;
- ref_init(&rng->ref);
-
- rng->state =
- MEM_ALLOC_ALIGNED(rng->allocator, type->sizeof_state, type->alignof_state);
- if(!rng->state) {
- res = RES_MEM_ERR;
- goto error;
+ switch(type) {
+ case SSP_RNG_KISS:
+ res = rng_create(mem_allocator, &rng_kiss, out_rng);
+ break;
+ case SSP_RNG_MT19937_64:
+ res = rng_create(mem_allocator, &rng_mt19937_64, out_rng);
+ break;
+ case SSP_RNG_RANLUX48:
+ res = rng_create(mem_allocator, &rng_ranlux48, out_rng);
+ break;
+ case SSP_RNG_RANDOM_DEVICE:
+ res = rng_create(mem_allocator, &rng_random_device, out_rng);
+ break;
+ case SSP_RNG_THREEFRY:
+ res = rng_create(mem_allocator, &rng_threefry, out_rng);
+#ifdef WITH_R123_AES
+ break;
+ case SSP_RNG_AES:
+ res = rng_create(mem_allocator, &rng_aes, out_rng);
+ break;
+#endif
+ default: res = RES_BAD_ARG; break;
}
- res = type->init(allocator, rng->state);
if(res != RES_OK) goto error;
- rng->type = *type;
-
- /* Precompute some values for the canonical distribution */
- rng->r = (long double)rng->type.max - (long double)rng->type.min + 1.0L;
- log2r = (size_t)(std::log(rng->r) / std::log(2.0L));
- rng->dbl_k = std::max<size_t>(1UL, (53 + log2r - 1UL) / log2r);
- rng->flt_k = std::max<size_t>(1UL, (24 + log2r - 1UL) / log2r);
+ (*out_rng)->type = type;
exit:
- if(out_rng) *out_rng = rng;
return res;
error:
- if(rng) {
- SSP(rng_ref_put(rng));
- rng = NULL;
- }
goto exit;
}
@@ -628,7 +572,7 @@ ssp_rng_ref_put(struct ssp_rng* rng)
}
res_T
-ssp_rng_get_type(const struct ssp_rng* rng, struct ssp_rng_type* type)
+ssp_rng_get_type(const struct ssp_rng* rng, enum ssp_rng_type* type)
{
if(!rng || !type) return RES_BAD_ARG;
*type = rng->type;
@@ -639,7 +583,7 @@ uint64_t
ssp_rng_get(struct ssp_rng* rng)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.get(rng->state);
+ return rng->desc.get(rng->state);
}
uint64_t
@@ -647,8 +591,8 @@ 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");
- rng_cxx rng_cxx(*rng);
- return RAN_NAMESPACE::uniform_int_distribution<uint64_t>(lower, upper)(rng_cxx);
+ RAN_NAMESPACE::uniform_int_distribution<uint64_t> distrib(lower, upper);
+ return wrap_ran(*rng, distrib);
}
double
@@ -656,8 +600,8 @@ ssp_rng_uniform_double
(struct ssp_rng* rng, const double lower, const double upper)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- rng_cxx rng_cxx(*rng);
- return RAN_NAMESPACE::uniform_real_distribution<double>(lower, upper)(rng_cxx);
+ RAN_NAMESPACE::uniform_real_distribution<double> distrib(lower, upper);
+ return wrap_ran(*rng, distrib);
}
float
@@ -665,8 +609,8 @@ 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);
+ RAN_NAMESPACE::uniform_real_distribution<float> distrib(lower, upper);
+ return wrap_ran(*rng, distrib);
}
double
@@ -683,7 +627,7 @@ ssp_rng_canonical(struct ssp_rng* rng)
double sum = 0;
double tmp = 1;
for(; k !=0; --k) {
- sum += (double)(rng->type.get(rng->state) - rng->type.min) * tmp;
+ sum += (double)(rng->desc.get(rng->state) - rng->desc.min) * tmp;
tmp = (double)(tmp*rng->r);
}
return sum/tmp;
@@ -709,7 +653,7 @@ ssp_rng_canonical_float(struct ssp_rng* rng)
float sum = 0;
float tmp = 1;
for(; k !=0; --k) {
- sum += (float)(rng->type.get(rng->state) - rng->type.min) * tmp;
+ sum += (float)(rng->desc.get(rng->state) - rng->desc.min) * tmp;
tmp = (float)(tmp*rng->r);
}
r = sum/tmp;
@@ -722,42 +666,42 @@ uint64_t
ssp_rng_min(struct ssp_rng* rng)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.min;
+ return rng->desc.min;
}
uint64_t
ssp_rng_max(struct ssp_rng* rng)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.max;
+ return rng->desc.max;
}
res_T
ssp_rng_set(struct ssp_rng* rng, const uint64_t seed)
{
if(!rng) return RES_BAD_ARG;
- return rng->type.set(rng->state, seed);
+ return rng->desc.set(rng->state, seed);
}
res_T
ssp_rng_read(struct ssp_rng* rng, FILE* stream)
{
if(!rng || !stream) return RES_BAD_ARG;
- return rng->type.read(rng->state, stream);
+ return rng->desc.read(rng->state, stream);
}
res_T
ssp_rng_read_cstr(struct ssp_rng* rng, const char* cstr)
{
if(!rng || !cstr) return RES_BAD_ARG;
- return rng->type.read_cstr(rng->state, cstr);
+ return rng->desc.read_cstr(rng->state, cstr);
}
res_T
ssp_rng_write(const struct ssp_rng* rng, FILE* stream)
{
if(!rng || !stream) return RES_BAD_ARG;
- return rng->type.write(rng->state, stream);
+ return rng->desc.write(rng->state, stream);
}
res_T
@@ -768,19 +712,78 @@ ssp_rng_write_cstr
size_t* len)
{
if(!rng) return RES_BAD_ARG;
- return rng->type.write_cstr(rng->state, buf, bufsz, len);
+ return rng->desc.write_cstr(rng->state, buf, bufsz, len);
}
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);
+ if (!rng) FATAL("The Random Number Generator is NULL\n");
+ return rng->desc.entropy(rng->state);
}
res_T
ssp_rng_discard(struct ssp_rng* rng, uint64_t n)
{
- if(!rng) FATAL("The Random Number Generator is NULL\n");
- return rng->type.discard(rng->state, n);
+ if (!rng) FATAL("The Random Number Generator is NULL\n");
+ return rng->desc.discard(rng->state, n);
+}
+
+/*******************************************************************************
+ * Local function
+ ******************************************************************************/
+res_T
+rng_create
+ (struct mem_allocator* mem_allocator,
+ const struct rng_desc* desc,
+ struct ssp_rng** out_rng)
+{
+ struct mem_allocator* allocator;
+ struct ssp_rng* rng = NULL;
+ size_t log2r;
+ res_T res = RES_OK;
+
+ if(!desc || !out_rng) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ allocator = mem_allocator ? mem_allocator : &mem_default_allocator;
+
+ /* Align the rng on 16 bytes since its 'r' attrib is a long double that on
+ * Linux 64-bits systems must be aligned on 16 bytes. */
+ rng = (struct ssp_rng*)MEM_ALLOC_ALIGNED(allocator, sizeof(*rng), 16);
+ if(!rng) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ memset(rng, 0, sizeof(struct ssp_rng));
+ rng->allocator = allocator;
+ ref_init(&rng->ref);
+ rng->desc = *desc;
+
+ rng->state = MEM_ALLOC_ALIGNED
+ (rng->allocator, rng->desc.sizeof_state, rng->desc.alignof_state);
+ if(!rng->state) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ res = rng->desc.init(allocator, rng->state);
+ if(res != RES_OK) goto error;
+
+ /* Precompute some values for the canonical distribution */
+ rng->r = (long double)rng->desc.max - (long double)rng->desc.min + 1.0L;
+ log2r = (size_t)(std::log(rng->r) / std::log(2.0L));
+ rng->dbl_k = std::max<size_t>(1UL, (53 + log2r - 1UL) / log2r);
+ rng->flt_k = std::max<size_t>(1UL, (24 + log2r - 1UL) / log2r);
+
+exit:
+ if(out_rng) *out_rng = rng;
+ return res;
+error:
+ if(rng) {
+ SSP(rng_ref_put(rng));
+ rng = NULL;
+ }
+ goto exit;
}
diff --git a/src/ssp_rng_c.h b/src/ssp_rng_c.h
@@ -32,6 +32,34 @@
#ifndef SSP_RNG_C_H
#define SSP_RNG_C_H
+#include <rsys/rsys.h>
+
+/* disable some warnings in Random123 includes */
+#ifdef COMPILER_GCC
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wconversion" /* unsafe conversion */
+ #pragma GCC diagnostic ignored "-Wshadow"
+ #pragma GCC diagnostic ignored "-Wunused-parameter" /* in Random123/aes.h */
+#elif defined(COMPILER_CL)
+ #pragma warning(push)
+ #pragma warning(disable:4100) /* unreferenced formal parameter */
+ #pragma warning(disable:4127) /* conditional expression is constant */
+ #pragma warning(disable:4512) /* assignment operator could not be generated */
+ #pragma warning(disable:4521) /* multiple copy constructors specified */
+#endif
+
+#include <Random123/conventional/Engine.hpp>
+#include <Random123/threefry.h>
+#ifdef WITH_R123_AES
+ #include <Random123/aes.h>
+#endif
+
+#ifdef COMPILER_GCC
+ #pragma GCC diagnostic pop
+#elif defined(COMPILER_CL)
+ #pragma warning(pop)
+#endif
+
#include "ssp.h"
#include <rsys/ref_count.h>
@@ -56,8 +84,30 @@
#define RAN_NAMESPACE std
#endif
+/* Generic Random Number Generator type descriptor */
+struct rng_desc {
+ res_T (*init)(struct mem_allocator* allocator, void* state);
+ void (*release)(void* state);
+ res_T (*set)(void* state, const uint64_t seed);
+
+ uint64_t (*get)(void* state);
+ res_T (*discard)(void* state, uint64_t n);
+ res_T (*read)(void* state, FILE* file);
+ res_T (*read_cstr)(void* state, const char* cstr);
+ res_T (*write)(const void* state, FILE* file);
+ res_T (*write_cstr)(const void* state, char* buf, const size_t sz, size_t* out_sz);
+ double (*entropy)(const void* state);
+
+ uint64_t min;
+ uint64_t max;
+
+ size_t sizeof_state;
+ size_t alignof_state;
+};
+
struct ssp_rng {
- struct ssp_rng_type type;
+ struct rng_desc desc;
+ enum ssp_rng_type type;
void* state;
struct mem_allocator* allocator;
@@ -69,19 +119,68 @@ struct ssp_rng {
ref_T ref;
};
+/*******************************************************************************
+ * Local API
+ ******************************************************************************/
+extern LOCAL_SYM res_T
+rng_create
+ (struct mem_allocator* allocator,
+ const struct rng_desc* desc,
+ struct ssp_rng** out_rng);
+
+/*******************************************************************************
+ * C++ Wrappers
+ ******************************************************************************/
+template<typename ResultType, uint64_t Min, uint64_t Max>
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 rng.type.get(rng.state); }
- FINLINE uint64_t min() const { return rng.type.min; }
- FINLINE uint64_t max() const { return rng.type.max; }
+ FINLINE uint64_t operator()() { return rng.desc.get(rng.state); }
+ static constexpr uint64_t min() { return Min; }
+ static constexpr uint64_t max() { return Max; }
- typedef uint64_t result_type;
+ typedef ResultType result_type;
private:
struct ssp_rng& rng;
};
+template<typename Ran> typename Ran::result_type
+wrap_ran(struct ssp_rng& rng, Ran& ran)
+{
+ #define RNG_CXX(Type) rng_cxx<Type::result_type, Type::min(), Type::max()>
+ switch(rng.type) {
+ case SSP_RNG_KISS: {
+ class rng_cxx<uint64_t, 0, UINT32_MAX> rng_cxx(rng);
+ return ran(rng_cxx);
+ }
+ case SSP_RNG_MT19937_64: {
+ class RNG_CXX(RAN_NAMESPACE::mt19937_64) rng_cxx(rng);
+ return ran(rng_cxx);
+ }
+ case SSP_RNG_RANLUX48: {
+ class RNG_CXX(RAN_NAMESPACE::ranlux48) rng_cxx(rng);
+ return ran(rng_cxx);
+ }
+ case SSP_RNG_RANDOM_DEVICE: {
+ class RNG_CXX(RAN_NAMESPACE::random_device) rng_cxx(rng);
+ return ran(rng_cxx);
+ }
+ case SSP_RNG_THREEFRY: {
+ class RNG_CXX(r123::Engine<r123::Threefry4x64>) rng_cxx(rng);
+ return ran(rng_cxx);
+ }
+#ifdef WITH_R123_AES
+ case SSP_RNG_AES: {
+ class RNG_CXX(r123::Engine<r123::AESNI4x32>) rng_cxx(rng);
+ return ran(rng_cxx);
+ }
+#endif
+ default: FATAL("Unreachable code\n");
+ }
+ #undef RNG_CXX
+}
+
#endif /* SSP_RNG_C_H */
diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c
@@ -77,7 +77,7 @@ enum rng_proxy_sig {
* +---------+---------+- -+---------+---------+---------+-
* Unique random sequence */
struct ssp_rng_proxy {
- struct ssp_rng_type type; /* Type of the RNGs managed by the proxy */
+ enum ssp_rng_type type; /* Type of the RNGs managed by the proxy */
struct ssp_rng* rng; /* Main `type' RNG */
@@ -419,7 +419,7 @@ rng_bucket_discard(void* data, uint64_t n)
return ssp_rng_discard(rng->pool, n);
}
-static const struct ssp_rng_type RNG_BUCKET_NULL = {
+static const struct rng_desc RNG_BUCKET_NULL = {
rng_bucket_init,
rng_bucket_release,
rng_bucket_set,
@@ -508,7 +508,7 @@ rng_proxy_setup
res = rng_state_cache_init
(proxy->allocator, sequence_pitch, proxy->states+ibucket);
if(res != RES_OK) goto error;
- res = ssp_rng_create(proxy->allocator, &proxy->type, proxy->pools+ibucket);
+ res = ssp_rng_create(proxy->allocator, proxy->type, proxy->pools+ibucket);
if(res != RES_OK) goto error;
proxy->buckets[ibucket] = 0;
}
@@ -541,7 +541,7 @@ rng_proxy_release(ref_T* ref)
res_T
ssp_rng_proxy_create
(struct mem_allocator* mem_allocator,
- const struct ssp_rng_type* type,
+ const enum ssp_rng_type type,
const size_t nbuckets,
struct ssp_rng_proxy** out_proxy)
{
@@ -613,7 +613,7 @@ ssp_rng_proxy_create2
if(!args->rng) {
res = ssp_rng_create(allocator, args->type, &proxy->rng);
if(res != RES_OK) goto error;
- proxy->type = *args->type;
+ proxy->type = args->type;
/* Create the proxy RNG from a submitted RNG state */
} else {
@@ -625,12 +625,12 @@ ssp_rng_proxy_create2
if(res != RES_OK) goto error;
/* Bucket RNG is not allowed to be a proxy RNG */
- if(proxy->type.init == rng_bucket_init) {
+ if(args->rng->desc.init == rng_bucket_init) {
res = RES_BAD_ARG;
goto error;
}
- res = ssp_rng_create(allocator, &proxy->type, &proxy->rng);
+ res = ssp_rng_create(allocator, proxy->type, &proxy->rng);
if(res != RES_OK) goto error;
/* Initialise the RNG proxy state from the state of the submitted RNG */
@@ -723,7 +723,7 @@ ssp_rng_proxy_create_rng
struct ssp_rng** out_rng)
{
struct ssp_rng* rng = NULL;
- struct ssp_rng_type type = RNG_BUCKET_NULL;
+ struct rng_desc desc = RNG_BUCKET_NULL;
struct rng_bucket* bucket = NULL;
res_T res = RES_OK;
@@ -738,12 +738,13 @@ ssp_rng_proxy_create_rng
}
/* Update the dummy rng bucket min/max value with the min/max values of the
- * RNG type on which the proxy relies */
- type.min = proxy->type.min;
- type.max = proxy->type.max;
+ * RNG desc on which the proxy relies */
+ desc.min = proxy->rng->desc.min;
+ desc.max = proxy->rng->desc.max;
- res = ssp_rng_create(proxy->allocator, &type, &rng);
+ res = rng_create(proxy->allocator, &desc, &rng);
if(res != RES_OK) goto error;
+ rng->type = proxy->type;
bucket = (struct rng_bucket*)rng->state;
bucket->name = ibucket;
bucket->proxy = proxy;
@@ -769,7 +770,7 @@ error:
res_T
ssp_rng_proxy_get_type
(const struct ssp_rng_proxy* proxy,
- struct ssp_rng_type* type)
+ enum ssp_rng_type* type)
{
if(!proxy || !type) return RES_BAD_ARG;
*type = proxy->type;
diff --git a/src/test_ssp_ran_circle.h b/src/test_ssp_ran_circle.h
@@ -70,7 +70,7 @@ TEST(void)
int i = 0, j = 9;
CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
CHK(EQ_EPS(RAN_CIRCLE_UNIFORM_PDF(), 1/(2*(REAL)PI), (REAL)1.e-6));
FOR_EACH(i, 0, NSAMPS) {
diff --git a/src/test_ssp_ran_discrete.c b/src/test_ssp_ran_discrete.c
@@ -50,7 +50,7 @@ main(int argc, char** argv)
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng) == RES_OK);
CHK(ssp_ranst_discrete_create(NULL, NULL) == RES_BAD_ARG);
CHK(ssp_ranst_discrete_create(NULL, &ran) == RES_OK);
diff --git a/src/test_ssp_ran_gaussian.h b/src/test_ssp_ran_gaussian.h
@@ -85,7 +85,7 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
CHK(RANST_GAUSSIAN_CREATE(NULL, NULL) == RES_BAD_ARG);
CHK(RANST_GAUSSIAN_CREATE(NULL, &gaussian) == RES_OK);
diff --git a/src/test_ssp_ran_hemisphere.h b/src/test_ssp_ran_hemisphere.h
@@ -101,8 +101,8 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng0) == RES_OK);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng1) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng0) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng1) == RES_OK);
samps0[0][0] = 0; samps0[0][1] = 0; samps0[0][2] = 1;
f = RAN_HEMISPHERE_UNIFORM(rng1, samps0[0], samps1[0], NULL);
diff --git a/src/test_ssp_ran_hg.h b/src/test_ssp_ran_hg.h
@@ -69,7 +69,7 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng) == RES_OK);
FOR_EACH(i, 0, NG) {
/* for any value of g... */
diff --git a/src/test_ssp_ran_piecewise_linear.h b/src/test_ssp_ran_piecewise_linear.h
@@ -84,7 +84,7 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
CHK(RANST_PIECEWISE_LINEAR_CREATE(NULL, NULL) == RES_BAD_ARG);
CHK(RANST_PIECEWISE_LINEAR_CREATE(NULL, &pwl) == RES_OK);
diff --git a/src/test_ssp_ran_sphere.h b/src/test_ssp_ran_sphere.h
@@ -69,7 +69,7 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
FOR_EACH(i, 0, NSAMPS) {
f = RAN_SPHERE_UNIFORM(rng, samps[i], &samps[i][3]);
diff --git a/src/test_ssp_ran_sphere_cap.h b/src/test_ssp_ran_sphere_cap.h
@@ -75,7 +75,7 @@ TEST(void)
int i, j;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
CHK(RAN_SPHERE_CAP_UNIFORM_LOCAL(rng, 1, samps[0], &pdf) == samps[0]);
CHK(samps[0][0] == 0);
diff --git a/src/test_ssp_ran_spherical_zone.h b/src/test_ssp_ran_spherical_zone.h
@@ -76,7 +76,7 @@ TEST(void)
int i, j;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
heights[0] = heights[1] = 1;
CHK(RAN_SPHERICAL_ZONE_UNIFORM_LOCAL(rng, heights, samps[0], &pdf) == samps[0]);
diff --git a/src/test_ssp_ran_tetrahedron.h b/src/test_ssp_ran_tetrahedron.h
@@ -86,7 +86,7 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
FOR_EACH(j, 0, 100) {
FOR_EACH(i, 0, 3) {
diff --git a/src/test_ssp_ran_triangle.h b/src/test_ssp_ran_triangle.h
@@ -86,7 +86,7 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_MT19937_64, &rng) == RES_OK);
FOR_EACH(i, 0, 3) {
A[i] = RNG_UNIFORM_R(rng, 0, 1);
diff --git a/src/test_ssp_ran_uniform_disk.h b/src/test_ssp_ran_uniform_disk.h
@@ -85,8 +85,8 @@ TEST()
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng0) == RES_OK);
- CHK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng1) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng0) == RES_OK);
+ CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng1) == RES_OK);
up[0] = RNG_UNIFORM_R(rng1, -1, 1);
up[1] = RNG_UNIFORM_R(rng1, -1, 1);
diff --git a/src/test_ssp_rng.c b/src/test_ssp_rng.c
@@ -38,10 +38,10 @@
#define NRAND 1024
static void /* Really basic test */
-test_rng(const struct ssp_rng_type* type)
+test_rng(const enum ssp_rng_type type)
{
FILE* stream;
- struct ssp_rng_type type2;
+ enum ssp_rng_type type2;
struct ssp_rng* rng = NULL;
struct ssp_rng* rng1 = NULL;
struct ssp_rng* rng2 = NULL;
@@ -56,23 +56,22 @@ test_rng(const struct ssp_rng_type* type)
char* cstr = NULL;
int i, j;
res_T r;
- const char can_set = (type != &ssp_rng_random_device);
- const char can_rw = (type != &ssp_rng_random_device);
- const char can_have_entropy = (type == &ssp_rng_random_device);
- const char can_discard = (type != &ssp_rng_random_device);
+ const char can_set = (type != SSP_RNG_RANDOM_DEVICE);
+ const char can_rw = (type != SSP_RNG_RANDOM_DEVICE);
+ const char can_have_entropy = (type == SSP_RNG_RANDOM_DEVICE);
+ const char can_discard = (type != SSP_RNG_RANDOM_DEVICE);
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(type != NULL);
- CHK(ssp_rng_create(NULL, NULL, NULL) == RES_BAD_ARG);
- CHK(ssp_rng_create(&allocator, NULL, NULL) == RES_BAD_ARG);
+ CHK(ssp_rng_create(NULL, -1, NULL) == RES_BAD_ARG);
+ CHK(ssp_rng_create(&allocator, -1, NULL) == RES_BAD_ARG);
CHK(ssp_rng_create(NULL, type, NULL) == RES_BAD_ARG);
CHK(ssp_rng_create(&allocator, type, NULL) == RES_BAD_ARG);
- CHK(ssp_rng_create(NULL, NULL, &rng) == RES_BAD_ARG);
- CHK(ssp_rng_create(&allocator, NULL, &rng) == RES_BAD_ARG);
+ CHK(ssp_rng_create(NULL, -1, &rng) == RES_BAD_ARG);
+ CHK(ssp_rng_create(&allocator, -1, &rng) == RES_BAD_ARG);
r = ssp_rng_create(NULL, type, &rng);
#ifdef WITH_R123_AES
- if (r == RES_BAD_OP && type == &ssp_rng_aes) {
+ if(r == RES_BAD_OP && type == SSP_RNG_AES) {
printf("AES-NI instructions not available on this CPU and system.\n");
mem_shutdown_proxy_allocator(&allocator);
check_memory_allocator(&allocator);
@@ -85,7 +84,7 @@ test_rng(const struct ssp_rng_type* type)
CHK(ssp_rng_get_type(rng, NULL) == RES_BAD_ARG);
CHK(ssp_rng_get_type(NULL, &type2) == RES_BAD_ARG);
CHK(ssp_rng_get_type(rng, &type2) == RES_OK);
- CHK(ssp_rng_type_eq(type, &type2) == 1);
+ CHK(type == type2);
CHK(ssp_rng_ref_get(NULL) == RES_BAD_ARG);
CHK(ssp_rng_ref_get(rng) == RES_OK);
@@ -100,8 +99,8 @@ test_rng(const struct ssp_rng_type* type)
CHK(ssp_rng_create(NULL, type, &rng1) == RES_OK);
CHK(ssp_rng_create(NULL, type, &rng2) == RES_OK);
CHK(ssp_rng_discard(rng1, 10) == (can_discard ? RES_OK : RES_BAD_OP));
- if(type != &ssp_rng_random_device) {
- for (i = 0; i < 10; i++) ssp_rng_get(rng2);
+ if(type != SSP_RNG_RANDOM_DEVICE) {
+ FOR_EACH(i, 0, 10) ssp_rng_get(rng2);
CHK(ssp_rng_get(rng1) == ssp_rng_get(rng2));
}
@@ -267,18 +266,18 @@ main(int argc, char** argv)
exit(0);
}
if(!strcmp(argv[1], "kiss")) {
- test_rng(&ssp_rng_kiss);
+ test_rng(SSP_RNG_KISS);
} else if(!strcmp(argv[1], "mt19937_64")) {
- test_rng(&ssp_rng_mt19937_64);
+ test_rng(SSP_RNG_MT19937_64);
} else if(!strcmp(argv[1], "ranlux48")) {
- test_rng(&ssp_rng_ranlux48);
+ test_rng(SSP_RNG_RANLUX48);
} else if(!strcmp(argv[1], "random_device")) {
- test_rng(&ssp_rng_random_device);
+ test_rng(SSP_RNG_RANDOM_DEVICE);
} else if(!strcmp(argv[1], "threefry")) {
- test_rng(&ssp_rng_threefry);
+ test_rng(SSP_RNG_THREEFRY);
#ifdef WITH_R123_AES
} else if(!strcmp(argv[1], "aes")) {
- test_rng(&ssp_rng_aes);
+ test_rng(SSP_RNG_AES);
#endif
} else {
fprintf(stderr, "Unknown RNG `%s'\n", argv[1]);
diff --git a/src/test_ssp_rng_proxy.c b/src/test_ssp_rng_proxy.c
@@ -38,24 +38,24 @@ static void
test_creation(void)
{
struct ssp_rng_proxy* proxy;
- struct ssp_rng_type type;
+ enum ssp_rng_type type;
- CHK(ssp_rng_proxy_create(NULL, NULL, 0, NULL) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_mt19937_64, 0, NULL) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, NULL, 4, NULL) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_mt19937_64, 4, NULL) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, NULL, 0, &proxy) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_mt19937_64, 0, &proxy) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, NULL, 4, &proxy) == RES_BAD_ARG);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_mt19937_64, 4, &proxy) == RES_OK);
+ CHK(ssp_rng_proxy_create(NULL, -1, 0, NULL) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 0, NULL) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, -1, 4, NULL) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 4, NULL) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, -1, 0, &proxy) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 0, &proxy) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, -1, 4, &proxy) == RES_BAD_ARG);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 4, &proxy) == RES_OK);
CHK(ssp_rng_proxy_get_type(NULL, NULL) == RES_BAD_ARG);
CHK(ssp_rng_proxy_get_type(proxy, NULL) == RES_BAD_ARG);
CHK(ssp_rng_proxy_get_type(NULL, &type) == RES_BAD_ARG);
CHK(ssp_rng_proxy_get_type(proxy, &type) == RES_OK);
- CHK(ssp_rng_type_eq(&type, &ssp_rng_kiss) == 0);
- CHK(ssp_rng_type_eq(&type, &ssp_rng_mt19937_64) == 1);
+ CHK(type != SSP_RNG_KISS);
+ CHK(type == SSP_RNG_MT19937_64);
CHK(ssp_rng_proxy_ref_get(NULL) == RES_BAD_ARG);
CHK(ssp_rng_proxy_ref_get(proxy) == RES_OK);
@@ -64,9 +64,9 @@ test_creation(void)
CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK);
CHK(ssp_rng_proxy_create
- (&mem_default_allocator, &ssp_rng_threefry, 1, &proxy) == RES_OK);
+ (&mem_default_allocator, SSP_RNG_THREEFRY, 1, &proxy) == RES_OK);
CHK(ssp_rng_proxy_get_type(proxy, &type) == RES_OK);
- CHK(ssp_rng_type_eq(&type, &ssp_rng_threefry) == 1);
+ CHK(type == SSP_RNG_THREEFRY);
CHK(ssp_rng_proxy_ref_put(proxy) == RES_OK);
}
@@ -78,16 +78,16 @@ test_creation2(void)
CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG);
- args.type = &ssp_rng_mt19937_64;
+ 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;
+ args.type = SSP_RNG_TYPE_NULL;
CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG);
- args.type = &ssp_rng_mt19937_64;
+ 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;
@@ -125,13 +125,13 @@ test_creation2(void)
static void
test_rng_from_proxy(void)
{
- struct ssp_rng_type type;
+ enum ssp_rng_type type;
struct ssp_rng_proxy* proxy;
struct ssp_rng* rng[4];
uint64_t r[4];
size_t i, j, k;
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_mt19937_64, 4, &proxy) == RES_OK);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 4, &proxy) == RES_OK);
CHK(ssp_rng_proxy_create_rng(NULL, 0, NULL) == RES_BAD_ARG);
CHK(ssp_rng_proxy_create_rng(proxy, 0, NULL) == RES_BAD_ARG);
@@ -147,9 +147,9 @@ test_rng_from_proxy(void)
CHK(ssp_rng_get_type(rng[0], &type) == RES_OK);
FOR_EACH(i, 1, 4) {
- struct ssp_rng_type type2;
+ enum ssp_rng_type type2;
CHK(ssp_rng_get_type(rng[i], &type2) == RES_OK);
- CHK(ssp_rng_type_eq(&type, &type2) == 1);
+ CHK(type == type2);
}
FOR_EACH(i, 0, NRANDS) {
@@ -178,7 +178,7 @@ 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);
- args.type = &ssp_rng_mt19937_64;
+ args.type = SSP_RNG_MT19937_64;
args.sequence_size = block_sz;
args.sequence_pitch = block_sz;
args.nbuckets = 4;
@@ -215,7 +215,7 @@ test_rng_from_proxy2(void)
CHK(ssp_rng_ref_put(rng[2]) == RES_OK);
CHK(ssp_rng_ref_put(rng[3]) == RES_OK);
- args.type = &ssp_rng_mt19937_64;
+ args.type = SSP_RNG_MT19937_64;
args.sequence_size = block_sz;
args.sequence_pitch = 2*block_sz;
args.nbuckets = 2;
@@ -273,12 +273,12 @@ test_multi_proxies(void)
struct ssp_rng* rng3;
size_t i;
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_threefry, 1, &proxy1) == RES_OK);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_threefry, 1, &proxy2) == RES_OK);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_THREEFRY, 1, &proxy1) == RES_OK);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_THREEFRY, 1, &proxy2) == RES_OK);
CHK(ssp_rng_proxy_create_rng(proxy1, 0, &rng1) == RES_OK);
CHK(ssp_rng_proxy_create_rng(proxy2, 0, &rng2) == RES_OK);
- ssp_rng_create(NULL, &ssp_rng_threefry, &rng3);
+ ssp_rng_create(NULL, SSP_RNG_THREEFRY, &rng3);
CHK(ssp_rng_proxy_ref_put(proxy1) == RES_OK);
CHK(ssp_rng_proxy_ref_put(proxy2) == RES_OK);
@@ -301,11 +301,11 @@ test_proxy_from_rng(void)
struct ssp_rng_proxy_create2_args args = SSP_RNG_PROXY_CREATE2_ARGS_NULL;
struct ssp_rng_proxy* proxy;
struct ssp_rng* rng[4];
- struct ssp_rng_type type;
+ enum ssp_rng_type type;
uint64_t r[4];
size_t i, j, k;
- CHK(ssp_rng_create(NULL, &ssp_rng_threefry, &rng[0]) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_THREEFRY, &rng[0]) == RES_OK);
CHK(ssp_rng_discard(rng[0], COUNT) == RES_OK);
CHK(ssp_rng_proxy_create_from_rng(NULL, NULL, 0, NULL) == RES_BAD_ARG);
@@ -332,9 +332,9 @@ test_proxy_from_rng(void)
CHK(ssp_rng_get_type(rng[0], &type) == RES_OK);
FOR_EACH(i, 1, 4) {
- struct ssp_rng_type type2;
+ enum ssp_rng_type type2;
CHK(ssp_rng_get_type(rng[i], &type2) == RES_OK);
- CHK(ssp_rng_type_eq(&type, &type2) == 1);
+ CHK(type == type2);
}
FOR_EACH(i, 0, NRANDS) {
@@ -354,7 +354,7 @@ test_proxy_from_rng(void)
CHK(ssp_rng_proxy_create2(NULL, &args, &proxy) == RES_BAD_ARG);
CHK(ssp_rng_ref_put(rng[0]) == RES_OK);
- CHK(ssp_rng_create(NULL, &ssp_rng_threefry, &rng[0]) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_THREEFRY, &rng[0]) == RES_OK);
CHK(ssp_rng_discard(rng[0], 100) == RES_OK);
args.rng = rng[0];
@@ -385,7 +385,7 @@ test_read(void)
uint64_t r[4];
size_t i, j, k;
- CHK(ssp_rng_create(NULL, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK);
CHK(ssp_rng_discard(rng, COUNT) == RES_OK);
stream = tmpfile();
@@ -393,7 +393,7 @@ test_read(void)
CHK(ssp_rng_write(rng, stream) == RES_OK);
rewind(stream);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_mt19937_64, 4, &proxy) == RES_OK);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_MT19937_64, 4, &proxy) == RES_OK);
CHK(ssp_rng_proxy_read(NULL, NULL) == RES_BAD_ARG);
CHK(ssp_rng_proxy_read(proxy, NULL) == RES_BAD_ARG);
CHK(ssp_rng_proxy_read(NULL, stream) == RES_BAD_ARG);
@@ -432,7 +432,7 @@ test_write(void)
stream = tmpfile();
CHK(stream != NULL);
- CHK(ssp_rng_proxy_create(NULL, &ssp_rng_ranlux48, 1, &proxy) == RES_OK);
+ CHK(ssp_rng_proxy_create(NULL, SSP_RNG_RANLUX48, 1, &proxy) == RES_OK);
CHK(ssp_rng_proxy_create_rng(proxy, 0, &rng0) == RES_OK);
CHK(ssp_rng_proxy_write(NULL, NULL) == RES_BAD_ARG);
@@ -440,7 +440,7 @@ test_write(void)
CHK(ssp_rng_proxy_write(NULL, stream) == RES_BAD_ARG);
CHK(ssp_rng_proxy_write(proxy, stream) == RES_OK);
- CHK(ssp_rng_create(NULL, &ssp_rng_ranlux48, &rng1) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_RANLUX48, &rng1) == RES_OK);
r = ssp_rng_get(rng0);
CHK(r == ssp_rng_get(rng1));
@@ -472,7 +472,7 @@ test_cache(void)
* Mersenne Twister RNG type since its internal state is the greatest one of
* the proposed builtin type and is thus the one that will fill quickly the
* cache stream. */
- args.type = &ssp_rng_mt19937_64;
+ args.type = SSP_RNG_MT19937_64;
args.sequence_size = 4;
args.sequence_pitch = 4;
args.nbuckets = 2;
@@ -484,7 +484,7 @@ test_cache(void)
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);
- CHK(ssp_rng_create(NULL, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK);
FOR_EACH(i, 0, nrands*2) {
if((i / 2) % 2) {
CHK(ssp_rng_get(rng1) == ssp_rng_get(rng));
@@ -500,7 +500,7 @@ test_cache(void)
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);
- CHK(ssp_rng_create(NULL, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK);
/* Generate several RNs for the first RNG only to make under pressure the
* cache stream of 'rng1'. The cache stream limit is set to 32 MB and the
@@ -518,7 +518,7 @@ test_cache(void)
CHK(ssp_rng_ref_put(rng) == RES_OK);
/* Check the cache mechanisme of rng1 */
- CHK(ssp_rng_create(NULL, &ssp_rng_mt19937_64, &rng) == RES_OK);
+ CHK(ssp_rng_create(NULL, SSP_RNG_MT19937_64, &rng) == RES_OK);
CHK(ssp_rng_discard(rng, 2) == RES_OK);
FOR_EACH(i, 0, nrands) {
CHK(ssp_rng_get(rng1) == ssp_rng_get(rng));