commit d47ed9e5fd0ce79b820c7a0fa211cfbeedd96e6d
parent 52e8cb881ef6d21f4bd974e4fe7d5905db7db1f7
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 6 May 2015 16:57:58 +0200
Make the library compliant with the CL compiler
Note that the deserialisation of the ranlux PRNG is bugged
Diffstat:
7 files changed, 85 insertions(+), 57 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -43,9 +43,13 @@ find_package(RCMake 0.1 REQUIRED)
find_package(RSys 0.1.1 REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR})
include(rcmake)
+include(rcmake_runtime)
include_directories(${RSys_INCLUDE_DIR})
+rcmake_append_runtime_dirs(_runtime_dirs RSys)
+
+
################################################################################
# Configure and define targets
################################################################################
@@ -91,19 +95,29 @@ if(NOT NO_TEST)
foreach(_lib ${_libraries})
target_link_libraries(${_name} ${_lib})
endforeach(_lib)
+
+ endfunction()
+
+ function(register_test _name)
+ add_test(${_name} ${ARGN})
+ rcmake_set_test_runtime_dirs(${_name} _runtime_dirs)
endfunction()
function(new_test _name)
build_test(${_name} ${ARGN})
- add_test(${_name} ${_name})
+ register_test(${_name} ${_name})
endfunction()
- build_test(test_ssp_rng)
- add_test(test_ssp_rng_kiss test_ssp_rng kiss)
- add_test(test_ssp_rng_mt19937_64 test_ssp_rng mt19937_64)
- add_test(test_ssp_rng_ranlunx48 test_ssp_rng ranlux48)
- new_test(test_ssp_ran_hemisphere m)
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ set(MATH_LIB m)
+ endif()
+
+ build_test(test_ssp_rng)
+ register_test(test_ssp_rng_kiss test_ssp_rng kiss)
+ register_test(test_ssp_rng_mt19937_64 test_ssp_rng mt19937_64)
+ register_test(test_ssp_rng_ranlux48 test_ssp_rng ranlux48)
+ new_test(test_ssp_ran_hemisphere ${MATH_LIB})
new_test(test_ssp_rng_proxy)
endif()
diff --git a/src/ssp.h b/src/ssp.h
@@ -65,18 +65,17 @@ struct mem_allocator;
struct ssp_rng_type {
void (*init)(struct mem_allocator* allocator, void* state);
void (*release)(void* state);
- void (*set)(void* state, const unsigned long seed);
+ void (*set)(void* state, const uint64_t seed);
- unsigned long (*get)(void* state);
- unsigned long (*uniform_int)
- (void* state, const unsigned long min, const unsigned long max);
+ uint64_t (*get)(void* state);
+ uint64_t (*uniform_int)(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);
- unsigned long min;
- unsigned long max;
+ uint64_t min;
+ uint64_t max;
size_t sizeof_state;
};
@@ -110,19 +109,19 @@ ssp_rng_ref_get
SSP_API res_T
ssp_rng_set
(struct ssp_rng* rng,
- const unsigned long seed);
+ const uint64_t seed);
/* Uniform random distribution in [ssp_rng_min(rng), ssp_rng_max(rng)] */
-SSP_API unsigned long
+SSP_API uint64_t
ssp_rng_get
(struct ssp_rng* rng);
/* Uniform random integer distribution in [lower, upper] */
-SSP_API unsigned long
+SSP_API uint64_t
ssp_rng_uniform_int
(struct ssp_rng* rng,
- const unsigned long lower,
- const unsigned long upper);
+ const uint64_t lower,
+ const uint64_t upper);
/* Uniform random floating point distribution in [lower, upper] */
SSP_API double
@@ -136,11 +135,11 @@ SSP_API double
ssp_rng_canonical
(struct ssp_rng* rng);
-SSP_API unsigned long
+SSP_API uint64_t
ssp_rng_min
(struct ssp_rng* rng);
-SSP_API unsigned long
+SSP_API uint64_t
ssp_rng_max
(struct ssp_rng* rng);
diff --git a/src/ssp_rng.c b/src/ssp_rng.c
@@ -37,25 +37,32 @@
#include <random>
#include <sstream>
+#ifdef COMPILER_CL
+ #pragma warning(push)
+ #pragma warning(disable:4706) /* Assignment in conditional expression */
+#endif
+
/*******************************************************************************
* KISS PRNG
******************************************************************************/
struct rng_kiss { uint32_t x, y, z, c; };
static void
-rng_kiss_set(void* data, const unsigned long seed)
+rng_kiss_set(void* data, const size_t seed)
{
struct rng_kiss* kiss = (struct rng_kiss*)data;
- std::mt19937 rng_mt(seed % ((1L<<32)-1));
+ std::mt19937 rng_mt(seed % UINT32_MAX);
ASSERT(kiss);
kiss->x = (uint32_t)rng_mt();
- while(!(kiss->y = (uint32_t)rng_mt())); /* y must be != 0 */
+ do {
+ kiss->y = (uint32_t)rng_mt();
+ } while(kiss->y == 0); /* Y must be != 0 */
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;
}
-static unsigned long
+static uint64_t
rng_kiss_get(void* data)
{
struct rng_kiss* kiss = (struct rng_kiss*)data;
@@ -68,13 +75,12 @@ rng_kiss_get(void* data)
kiss->y ^= kiss->y << 22;
t = 4294584393ULL * kiss->z + kiss->c;
kiss->c = (uint32_t)(t >> 32);
- kiss->z = (uint32_t)t;
+ kiss->z = (uint32_t)(t & 0xFFFFFFFF);
return (uint32_t)(kiss->x + kiss->y + kiss->z);
}
-static unsigned long
-rng_kiss_uniform_int
- (void* data, const unsigned long lower, const unsigned long upper)
+static uint64_t
+rng_kiss_uniform_int(void* data, const uint64_t lower, const uint64_t upper)
{
ASSERT(lower <= upper);
return (uint32_t)
@@ -104,7 +110,7 @@ rng_kiss_read(void* data, FILE* file)
int res;
ASSERT(data && file);
res = fscanf(file, "%u %u %u %u", &rng->x, &rng->y, &rng->z, &rng->c);
- return res == EOF ? RES_IO_ERR : RES_OK;
+ return res == EOF || !res/* Required by CL O_o !!*/ ? RES_IO_ERR : RES_OK;
}
static res_T
@@ -151,15 +157,15 @@ const struct ssp_rng_type ssp_rng_kiss = {
******************************************************************************/
template<typename RNG>
static void
-rng_cxx_set(void* data, const unsigned long seed)
+rng_cxx_set(void* data, const uint64_t seed)
{
RNG* rng = (RNG*)data;
ASSERT(rng);
- rng->seed(seed);
+ rng->seed((unsigned long)seed);
}
template<typename RNG>
-static unsigned long
+static uint64_t
rng_cxx_get(void* data)
{
RNG* rng = (RNG*)data;
@@ -168,13 +174,13 @@ rng_cxx_get(void* data)
}
template<typename RNG>
-static unsigned long
+static uint64_t
rng_cxx_uniform_int
- (void* data, const unsigned long lower, const unsigned long upper)
+ (void* data, const uint64_t lower, const uint64_t upper)
{
RNG* rng = (RNG*)data;
ASSERT(rng && lower <= upper);
- return std::uniform_int_distribution<unsigned long>(lower, upper)(*rng);
+ return std::uniform_int_distribution<uint64_t>(lower, upper)(*rng);
}
template<typename RNG>
@@ -191,9 +197,14 @@ template<typename RNG>
static double
rng_cxx_canonical(void* data)
{
+ /* On Visual Studio 2013, the generate_canonical method is bugged */
+#ifdef COMPILER_CL
+ return rng_cxx_uniform_double<RNG>(data, 0.f, 1.f);
+#else
RNG* rng = (RNG*)data;
ASSERT(rng);
return std::generate_canonical<double, 48>(*rng);
+#endif
}
template<typename RNG>
@@ -240,6 +251,7 @@ static void
rng_cxx_release(void* data)
{
RNG* rng = (RNG*)data;
+ (void)rng;
ASSERT(rng);
rng->~RNG();
}
@@ -303,9 +315,9 @@ rng_release(ref_T* ref)
rng = CONTAINER_OF(ref, struct ssp_rng, ref);
if(rng->state) {
rng->type.release(rng->state);
- MEM_FREE(rng->allocator, rng->state);
+ MEM_RM(rng->allocator, rng->state);
}
- MEM_FREE(rng->allocator, rng);
+ MEM_RM(rng->allocator, rng);
}
/*******************************************************************************
@@ -370,16 +382,16 @@ ssp_rng_ref_put(struct ssp_rng* rng)
return RES_OK;
}
-unsigned long
+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);
}
-unsigned long
+uint64_t
ssp_rng_uniform_int
- (struct ssp_rng* rng, const unsigned long lower, const unsigned long upper)
+ (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);
@@ -400,14 +412,14 @@ ssp_rng_canonical(struct ssp_rng* rng)
return rng->type.canonical(rng->state);
}
-unsigned long
+uint64_t
ssp_rng_min(struct ssp_rng* rng)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
return rng->type.min;
}
-unsigned long
+uint64_t
ssp_rng_max(struct ssp_rng* rng)
{
if(!rng) FATAL("The Random Number Generator is NULL\n");
@@ -415,7 +427,7 @@ ssp_rng_max(struct ssp_rng* rng)
}
res_T
-ssp_rng_set(struct ssp_rng* rng, const unsigned long seed)
+ssp_rng_set(struct ssp_rng* rng, const uint64_t seed)
{
if(!rng) return RES_BAD_ARG;
rng->type.set(rng->state, seed);
@@ -436,3 +448,6 @@ ssp_rng_write(const struct ssp_rng* rng, FILE* stream)
return rng->type.write(rng->state, stream);
}
+#ifdef COMPILER_CL
+ #pragma warning(pop)
+#endif
diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c
@@ -65,7 +65,7 @@ struct ssp_rng_proxy {
struct ssp_rng* rng; /* Main `type' RNG */
/* The following arrays have the same size */
- int* buckets; /* Flag that defines which bucket RNGs are created */
+ ATOMIC* buckets; /* Flag that defines which bucket RNGs are created */
struct ssp_rng** pools; /* `type' RNGs wrapped by bucket RNGs */
struct rng_state_cache* states; /* Cache of `type' RNG states */
@@ -172,13 +172,13 @@ rng_bucket_next_ran_pool(struct rng_bucket* rng)
}
static void
-rng_bucket_set(void* data, const unsigned long seed)
+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");
}
-static unsigned long
+static uint64_t
rng_bucket_get(void* data)
{
struct rng_bucket* rng = (struct rng_bucket*)data;
@@ -188,9 +188,9 @@ rng_bucket_get(void* data)
return ssp_rng_get(rng->pool);
}
-static unsigned long
+static uint64_t
rng_bucket_uniform_int
- (void* data, const unsigned long lower, const unsigned long upper)
+ (void* data, const uint64_t lower, const uint64_t upper)
{
struct rng_bucket* rng = (struct rng_bucket*)data;
ASSERT(data);
@@ -224,7 +224,6 @@ 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
@@ -232,7 +231,6 @@ 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
@@ -362,7 +360,7 @@ rng_proxy_release(ref_T* ref)
sa_release(proxy->buckets);
SSP(rng_ref_put(proxy->rng));
if(proxy->mutex) mutex_destroy(proxy->mutex);
- MEM_FREE(proxy->allocator, proxy);
+ MEM_RM(proxy->allocator, proxy);
}
/*******************************************************************************
diff --git a/src/test_ssp_ran_hemisphere.c b/src/test_ssp_ran_hemisphere.c
@@ -58,7 +58,7 @@ main(int argc, char** argv)
float frame[9];
float up[3] = {0.f, 0.f, 1.f};
float xyz[3];
- unsigned long seed = ssp_rng_get(rng0);
+ uint64_t seed = ssp_rng_get(rng0);
ssp_rng_set(rng1, seed);
f = ssp_ran_hemisphere_uniform_local(rng1, samps0[i]);
@@ -100,7 +100,7 @@ main(int argc, char** argv)
float frame[9];
float up[3] = { 0.f, 0.f, 1.f };
float xyz[3];
- unsigned long seed = ssp_rng_get(rng0);
+ uint64_t seed = ssp_rng_get(rng0);
ssp_rng_set(rng1, seed);
f = ssp_ran_hemisphere_cos_local(rng1, samps2[i]);
diff --git a/src/test_ssp_rng.c b/src/test_ssp_rng.c
@@ -44,8 +44,8 @@ test_rng(const struct ssp_rng_type* type)
struct ssp_rng* rng;
struct mem_allocator allocator;
struct time t0, t1;
- unsigned long datai0[NRAND];
- unsigned long datai1[NRAND];
+ uint64_t datai0[NRAND];
+ uint64_t datai1[NRAND];
double dataf[NRAND];
char buf[512];
int i, j;
@@ -143,12 +143,14 @@ test_rng(const struct ssp_rng_type* type)
CHECK(ssp_rng_read(NULL, NULL), RES_BAD_ARG);
CHECK(ssp_rng_read(rng, NULL), RES_BAD_ARG);
CHECK(ssp_rng_read(NULL, stream), RES_BAD_ARG);
+#ifndef COMPILER_CL
CHECK(ssp_rng_read(rng, stream), RES_IO_ERR);
+#endif
rewind(stream);
CHECK(ssp_rng_read(rng, stream), RES_OK);
FOR_EACH(i, 0, NRAND) {
- unsigned long r = ssp_rng_get(rng);
+ uint64_t r = ssp_rng_get(rng);
CHECK(r, datai0[i]);
}
fclose(stream);
@@ -173,7 +175,7 @@ main(int argc, char** argv)
test_rng(&ssp_rng_ranlux48);
} else {
fprintf(stderr, "Unknown RNG `%s'\n", argv[1]);
- CHECK(0, 1);
+ ASSERT(0);
}
CHECK(mem_allocated_size(), 0);
diff --git a/src/test_ssp_rng_proxy.c b/src/test_ssp_rng_proxy.c
@@ -74,7 +74,7 @@ main(int argc, char** argv)
CHECK(ssp_rng_proxy_ref_put(proxy), RES_OK);
FOR_EACH(i, 0, 2000000) {
- unsigned long r[4];
+ uint64_t r[4];
int j;
FOR_EACH(j, 0, 4) {
int k;