star-mc

Parallel estimation of Monte Carlo integrators
git clone git://git.meso-star.fr/star-mc.git
Log | Files | Refs | README | LICENSE

commit adf0b3137f54dbba6d35d965c64fc984323c5369
parent 70b4beb0a8c71f6eaa748623f9cb60909a2b5f7a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 23 Jan 2018 10:36:27 +0100

Merge branch 'release_0.4'

Diffstat:
MREADME.md | 14+++++++++++++-
Mcmake/CMakeLists.txt | 26+++++++++++++-------------
Msrc/smc.h | 65++++++++++-------------------------------------------------------
Dsrc/smc_accumulator.c | 237-------------------------------------------------------------------------------
Msrc/smc_device.c | 11++++++++++-
Msrc/smc_device_c.h | 9+--------
Msrc/smc_doubleN.c | 2+-
Msrc/smc_estimator.c | 27+++++++++++++++------------
Msrc/smc_type.c | 2+-
Msrc/smc_type_c.h | 12+-----------
Msrc/smc_type_real.h | 2+-
Msrc/test_smc_device.c | 81++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/test_smc_doubleN.c | 42++++++++++++++++++++----------------------
Msrc/test_smc_errors.c | 38++++++++++++++++++--------------------
Dsrc/test_smc_integrate.c | 182-------------------------------------------------------------------------------
Msrc/test_smc_light_path.c | 134+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/test_smc_solve.c | 77+++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/test_smc_utils.h | 2+-
18 files changed, 255 insertions(+), 708 deletions(-)

diff --git a/README.md b/README.md @@ -20,9 +20,21 @@ RCMake package, the RSys and the Star-Sampling libraries, respectively. The generated project can be edited, built, tested and installed as any CMake project. +## Release notes + +### Version 0.4 + +- Remove the raw integration functionality. +- Rename the `max_steps` integrator attribute in `max_realisation`. +- Update the profile of the integrand function of the integrator: the + identifier of the thread that invokes the integrand is provided has an input + parameter. +- Add the `smc_device_get_threads_count` function that returns the maximum + number of threads used by the device. + ## License -Star-MC is Copyright (C) |Meso|Star> 2015-2016 (<contact@meso-star.com>). It is +Star-MC is Copyright (C) |Meso|Star> 2015-2018 (<contact@meso-star.com>). It is a free software released under the [OSI](http://opensource.org)-approved CeCILL license. You are welcome to redistribute it under certain conditions; refer to the COPYING files for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +# Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) # # This software is a computer program whose purpose is to generate files # used to build the Star-MC library. @@ -40,10 +40,10 @@ option(NO_TEST "Disable the test" OFF) # Check dependencies ################################################################################ find_package(RCMake 0.3 REQUIRED) -find_package(RSys 0.4 REQUIRED) -find_package(StarSP 0.4 REQUIRED) +find_package(RSys 0.6 REQUIRED) +find_package(StarSP 0.5 REQUIRED) +find_package(OpenMP 1.2 REQUIRED) find_package(Star3D 0.4) -find_package(OpenMP) if(NOT OPENMP_FOUND) message(STATUS "No OpenMP support: muti-threading is disabled") @@ -59,12 +59,11 @@ include(rcmake_runtime) # Configure and define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 3) -set(VERSION_PATCH 1) +set(VERSION_MINOR 4) +set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SMC_FILES_SRC - smc_accumulator.c smc_device.c smc_doubleN.c smc_estimator.c @@ -88,11 +87,9 @@ set_target_properties(smc PROPERTIES VERSION ${VERSION} SOVERSION ${VERSION_MAJOR}) -if(OPENMP_FOUND) - set_target_properties(smc PROPERTIES COMPILE_FLAGS ${OpenMP_C_FLAGS}) - if(CMAKE_COMPILER_IS_GNUCC) - set_target_properties(smc PROPERTIES LINK_FLAGS ${OpenMP_C_FLAGS}) - endif() +set_target_properties(smc PROPERTIES COMPILE_FLAGS ${OpenMP_C_FLAGS}) +if(CMAKE_COMPILER_IS_GNUCC) + set_target_properties(smc PROPERTIES LINK_FLAGS ${OpenMP_C_FLAGS}) endif() target_link_libraries(smc RSys StarSP) @@ -125,9 +122,12 @@ if(NOT NO_TEST) new_test(test_smc_device) new_test(test_smc_solve ${MATH_LIB}) new_test(test_smc_doubleN ${MATH_LIB}) - new_test(test_smc_integrate ${MATH_LIB}) new_test(test_smc_errors) + set_target_properties(test_smc_device PROPERTIES + COMPILE_FLAGS ${OpenMP_C_FLAGS} + LINK_FLAGS ${OpenMP_C_FLAGS}) + if(NOT TARGET Star3D) rcmake_copy_runtime_libraries(test_smc_solve) message(STATUS diff --git a/src/smc.h b/src/smc.h @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -75,15 +75,6 @@ struct smc_type { void (*sqrt)(void* result, const void* value); }; -/* Type for raw integration, i.e. whithout estimator. Experiment results are - * simply accumulated */ -struct smc_type_accum { - void* (*create)(struct mem_allocator* allocator, void* ctx); - void (*destroy)(struct mem_allocator*, void* accum); - void (*clear)(void* accum); - void (*add)(void* result, const void* op0, const void* op1); -}; - static const struct smc_type SMC_TYPE_NULL = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; @@ -95,37 +86,20 @@ struct smc_estimator_status { size_t NF; /* Failed samples count */ }; -struct smc_accumulator_status { - void* value; /* Accumulated value */ - size_t N; /* Samples count */ -}; - struct smc_integrator { - res_T (*integrand)(void* value, struct ssp_rng* rng, void* ctx); + res_T (*integrand) + (void* value, struct ssp_rng* rng, const unsigned ithread, void* ctx); const struct smc_type* type; - size_t max_steps; /* Maximum # of experiments */ + size_t max_realisations; /* Maximum # of realisations */ size_t max_failures; /* Cancel integration past # failed samples */ }; static const struct smc_integrator SMC_INTEGRATOR_NULL = { NULL, NULL, SIZE_MAX, SIZE_MAX }; -#define SMC_AUTO_CANCEL_OFF SIZE_MAX - -struct smc_integrator_accum { - res_T (*integrand)(void* accum, struct ssp_rng* rng, void* ctx); - const struct smc_type_accum* type; - size_t max_steps; /* Maximum # of accumulation */ - size_t max_failures; /* Cancel integration past # failed samples */ -}; - -static const struct smc_integrator_accum SMC_INTEGRATOR_ACCUM_NULL = -{ NULL, NULL, SIZE_MAX, SIZE_MAX }; - /* Forward declaration of opaque types */ struct smc_device; /* Entry point of the library */ struct smc_estimator; /* Estimator of an integrator */ -struct smc_accumulator; /* Accumulated values of a integration */ BEGIN_DECLS @@ -176,6 +150,12 @@ smc_device_get_rng_type (struct smc_device* dev, struct ssp_rng_type* type); +/* Return the maximum number of threads internally used by the device */ +SMC_API res_T +smc_device_get_threads_count + (const struct smc_device* dev, + unsigned* nthreads); + /******************************************************************************* * Integration API ******************************************************************************/ @@ -208,31 +188,6 @@ smc_estimator_get_status (struct smc_estimator* estimator, struct smc_estimator_status* status); -/******************************************************************************* - * Accumulation API - ******************************************************************************/ -/* Raw integration. - * The realisations must be accumulated by the user defined integrand */ -SMC_API res_T -smc_integrate - (struct smc_device* dev, - struct smc_integrator_accum* integrator, - void* ctx, - struct smc_accumulator** accumulator); - -SMC_API res_T -smc_accumulator_ref_get - (struct smc_accumulator* accumulator); - -SMC_API res_T -smc_accumulator_ref_put - (struct smc_accumulator* accumulator); - -SMC_API res_T -smc_accumulator_get_status - (struct smc_accumulator* accumulator, - struct smc_accumulator_status* status); - END_DECLS #endif /* SMC_H */ diff --git a/src/smc_accumulator.c b/src/smc_accumulator.c @@ -1,237 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) - * - * This software is a computer program whose purpose is to manage the - * statistical estimation of a function. - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#include "smc.h" -#include "smc_device_c.h" -#include "smc_type_c.h" - -#include <rsys/mem_allocator.h> - -#include <omp.h> - -struct smc_accumulator { - struct smc_type_accum type; - struct smc_accumulator_status status; - struct smc_device* dev; - ref_T ref; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static res_T -accumulator_create - (struct smc_device* dev, - const struct smc_type_accum* type, - void* ctx, - struct smc_accumulator** out_accum) -{ - struct smc_accumulator* accum = NULL; - res_T res = RES_OK; - ASSERT(out_accum && dev && type); - - accum = MEM_CALLOC(dev->allocator, 1, sizeof(struct smc_accumulator)); - if(!accum) { - res = RES_MEM_ERR; - goto error; - } - SMC(device_ref_get(dev)); - accum->dev = dev; - ref_init(&accum->ref); - - accum->status.value = type->create(dev->allocator, ctx); - if(!accum->status.value) { - res = RES_MEM_ERR; - goto error; - } - type->clear(accum->status.value); - - accum->status.N = 0; - accum->type = *type; - -exit: - *out_accum = accum; - return res; -error: - if(accum) { - SMC(accumulator_ref_put(accum)); - accum = NULL; - } - goto exit; -} - -static char -check_integrator_accum(struct smc_integrator_accum* integrator) -{ - ASSERT(integrator); - return integrator->integrand - && integrator->type - && integrator->max_steps - && check_type_accum(integrator->type); -} - -static void -accumulator_release(ref_T* ref) -{ - struct smc_accumulator* accum; - struct smc_device* dev; - ASSERT(ref); - - accum = CONTAINER_OF(ref, struct smc_accumulator, ref); - dev = accum->dev; - if(accum->status.value) - accum->type.destroy(dev->allocator, accum->status.value); - MEM_RM(dev->allocator, accum); - SMC(device_ref_put(dev)); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -smc_integrate - (struct smc_device* dev, - struct smc_integrator_accum* integrator, - void* ctx, - struct smc_accumulator** out_accum) -{ - struct smc_accumulator* accum = NULL; - int64_t i; - size_t nthreads = 0; - void** accums = NULL; - size_t* nsamples = NULL; - res_T res = RES_OK; - size_t nfailed = 0; - int cancel = 0; - - if(!dev || !integrator || !out_accum || !check_integrator_accum(integrator)) { - res = RES_BAD_ARG; - goto error; - } - nthreads = device_get_threads_count(dev); - - /* Create and initialize per thread memory variables */ - nsamples = MEM_CALLOC(dev->allocator, nthreads, sizeof(size_t)); - if(!nsamples) { - res = RES_MEM_ERR; - goto error; - } - - accums = MEM_CALLOC(dev->allocator, nthreads, sizeof(void*)); - if(!accums) { - res = RES_MEM_ERR; - goto error; - } - - FOR_EACH(i, 0, (int64_t)nthreads) { - accums[i] = integrator->type->create(dev->allocator, ctx); - if(!accums[i]) { - res = RES_MEM_ERR; - goto error; - } - integrator->type->clear(accums[i]); - } - - /* Create the accumulator */ - res = accumulator_create(dev, integrator->type, ctx, &accum); - if(res != RES_OK) goto error; - - /* Parallel evaluation of the integrator */ - #pragma omp parallel shared(cancel, nfailed) - { - const int ithread = omp_get_thread_num(); - #pragma omp for schedule(static) - for(i=0; i < (int64_t)integrator->max_steps; ++i) { - if(!cancel) { - if(integrator->integrand(accums[ithread], dev->rngs[ithread], ctx) == RES_OK) { - /* call succeded */ - ++nsamples[ithread]; - } else { - #pragma omp atomic - ++nfailed; - if (nfailed > integrator->max_failures) { - cancel = 1; - } - } - } - } - } - - /* Merge the parallel estimation into the final estimator */ - FOR_EACH(i, 0, (int64_t)nthreads) { - accum->status.N += nsamples[i]; - integrator->type->add(accum->status.value, accum->status.value, accums[i]); - } - -exit: - if(nsamples) MEM_RM(dev->allocator, nsamples); - if(accums) { - FOR_EACH(i, 0, (int64_t)nthreads) - if(accums[i]) integrator->type->destroy(dev->allocator, accums[i]); - MEM_RM(dev->allocator, accums); - } - if(out_accum) *out_accum = accum; - return res; - -error: - if(accum) { - SMC(accumulator_ref_put(accum)); - accum = NULL; - } - goto exit; -} - -res_T -smc_accumulator_ref_get(struct smc_accumulator* accum) -{ - if(!accum) return RES_BAD_ARG; - ref_get(&accum->ref); - return RES_OK; -} - -res_T -smc_accumulator_ref_put(struct smc_accumulator* accum) -{ - if(!accum) return RES_BAD_ARG; - ref_put(&accum->ref, accumulator_release); - return RES_OK; -} - -res_T -smc_accumulator_get_status - (struct smc_accumulator* accum, - struct smc_accumulator_status* status) -{ - if(!accum || !status) return RES_BAD_ARG; - *status = accum->status; - return RES_OK; -} - diff --git a/src/smc_device.c b/src/smc_device.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -194,3 +194,12 @@ smc_device_get_rng_type(struct smc_device* dev, struct ssp_rng_type* type) return ssp_rng_proxy_get_type(dev->rng_proxy, type); } +res_T +smc_device_get_threads_count(const struct smc_device* dev, unsigned* nthreads) +{ + if(!dev || !nthreads) return RES_BAD_ARG; + ASSERT(dev->nthreads <= UINT_MAX); + *nthreads = (unsigned)dev->nthreads; + return RES_OK; +} + diff --git a/src/smc_device_c.h b/src/smc_device_c.h @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -44,12 +44,5 @@ struct smc_device { ref_T ref; }; -static FINLINE size_t -device_get_threads_count(const struct smc_device* dev) -{ - ASSERT(dev); - return sa_size(dev->rngs); -} - #endif /* SMC_DEVICE_C_H */ diff --git a/src/smc_doubleN.c b/src/smc_doubleN.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. diff --git a/src/smc_estimator.c b/src/smc_estimator.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -112,7 +112,7 @@ check_integrator(struct smc_integrator* integrator) ASSERT(integrator); return integrator->integrand && integrator->type - && integrator->max_steps + && integrator->max_realisations && check_type(integrator->type); } @@ -151,7 +151,7 @@ smc_solve { struct smc_estimator* estimator = NULL; int64_t i; - size_t nthreads = 0; + unsigned nthreads = 0; char* raw = NULL; void** vals = NULL; void** accums = NULL; @@ -165,7 +165,7 @@ smc_solve res = RES_BAD_ARG; goto error; } - nthreads = device_get_threads_count(dev); + SMC(device_get_threads_count(dev, &nthreads)); /* Create per thread temporary variables */ raw = MEM_CALLOC(dev->allocator, nthreads, sizeof(void*)*3 + sizeof(size_t)); @@ -202,9 +202,11 @@ smc_solve { const int ithread = omp_get_thread_num(); #pragma omp for schedule(static) - for(i = 0; i < (int64_t)integrator->max_steps; ++i) { + for(i = 0; i < (int64_t)integrator->max_realisations; ++i) { if(!cancel) { - if(integrator->integrand(vals[ithread], dev->rngs[ithread], ctx) == RES_OK) { + const res_T res_local = integrator->integrand + (vals[ithread], dev->rngs[ithread], (unsigned)ithread, ctx); + if(res_local == RES_OK) { /* call succeded */ integrator->type->add(accums[ithread], accums[ithread], vals[ithread]); integrator->type->mul(vals[ithread], vals[ithread], vals[ithread]); @@ -260,7 +262,7 @@ smc_solve_N { res_T res = RES_OK; int64_t i; - size_t nthreads = 0; + unsigned nthreads = 0; void** vals = NULL; int cancel = 0; @@ -283,7 +285,7 @@ smc_solve_N } /* Create the per thread temporary variables */ - nthreads = device_get_threads_count(dev); + SMC(device_get_threads_count(dev, &nthreads)); vals = MEM_CALLOC(dev->allocator, nthreads, sizeof(void*)); FOR_EACH(i, 0, (int64_t)nthreads) { vals[i] = integrator->type->create @@ -301,11 +303,12 @@ smc_solve_N #pragma omp for schedule(static, 1) for(i = 0; i < (int64_t)count; ++i) { size_t istep; - FOR_EACH(istep, 0, integrator->max_steps) { + FOR_EACH(istep, 0, integrator->max_realisations) { if(!cancel) { - if(integrator->integrand - (vals[ithread], dev->rngs[ithread], (char*)ctx + (size_t)i*sizeof_ctx) - == RES_OK) { + const res_T res_local = integrator->integrand + (vals[ithread], dev->rngs[ithread], (unsigned)ithread, + (char*)ctx + (size_t)i*sizeof_ctx); + if(res_local == RES_OK) { /* call succeded */ integrator->type->add (estimators[i]->value, estimators[i]->value, vals[ithread]); diff --git a/src/smc_type.c b/src/smc_type.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. diff --git a/src/smc_type_c.h b/src/smc_type_c.h @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -49,15 +49,5 @@ check_type(const struct smc_type* type) && type->sqrt != NULL; } -static INLINE char -check_type_accum(const struct smc_type_accum* type) -{ - ASSERT(type); - return type->create != NULL - && type->destroy != NULL - && type->clear != NULL - && type->add != NULL; -} - #endif /* SMC_TYPE_C_H */ diff --git a/src/smc_type_real.h b/src/smc_type_real.h @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. diff --git a/src/test_smc_device.c b/src/test_smc_device.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, @@ -33,6 +33,8 @@ #include <star/ssp.h> +#include <omp.h> + static void log_stream(const char* msg, void* ctx) { @@ -48,62 +50,69 @@ main(int argc, char** argv) struct mem_allocator allocator; struct ssp_rng_type type; struct smc_device* dev; + unsigned nthreads; (void)argc, (void)argv; - CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, NULL), RES_BAD_ARG); - CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, &dev), RES_OK); + CHK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, &dev) == RES_OK); + + CHK(smc_device_get_threads_count(NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_get_threads_count(dev, NULL) == RES_BAD_ARG); + CHK(smc_device_get_threads_count(NULL, &nthreads) == RES_BAD_ARG); + CHK(smc_device_get_threads_count(dev, &nthreads) == RES_OK); + CHK(nthreads == (unsigned)omp_get_num_procs()); - CHECK(smc_device_ref_get(NULL), RES_BAD_ARG); - CHECK(smc_device_ref_get(dev), RES_OK); - CHECK(smc_device_ref_put(NULL), RES_BAD_ARG); - CHECK(smc_device_ref_put(dev), RES_OK); - CHECK(smc_device_ref_put(dev), RES_OK); + CHK(smc_device_ref_get(NULL) == RES_BAD_ARG); + CHK(smc_device_ref_get(dev) == RES_OK); + CHK(smc_device_ref_put(NULL) == RES_BAD_ARG); + CHK(smc_device_ref_put(dev) == RES_OK); + CHK(smc_device_ref_put(dev) == RES_OK); - CHECK(smc_device_create(NULL, NULL, 0, NULL, &dev), RES_BAD_ARG); + CHK(smc_device_create(NULL, NULL, 0, NULL, &dev) == RES_BAD_ARG); mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(MEM_ALLOCATED_SIZE(&allocator), 0); - CHECK(smc_device_create(NULL, &allocator, 1, NULL, NULL), RES_BAD_ARG); - CHECK(smc_device_create(NULL, &allocator, 1, NULL, &dev), RES_OK); - CHECK(smc_device_ref_put(dev), RES_OK); - CHECK(MEM_ALLOCATED_SIZE(&allocator), 0); + CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); + CHK(smc_device_create(NULL, &allocator, 1, NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_create(NULL, &allocator, 1, NULL, &dev) == RES_OK); + CHK(smc_device_ref_put(dev) == RES_OK); + CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); - CHECK(logger_init(&allocator, &logger), RES_OK); + CHK(logger_init(&allocator, &logger) == RES_OK); logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); - CHECK(smc_device_create(&logger, NULL, 1, NULL, NULL), RES_BAD_ARG); - CHECK(smc_device_create(&logger, NULL, 1, NULL, &dev), RES_OK); - CHECK(smc_device_ref_put(dev), RES_OK); + CHK(smc_device_create(&logger, NULL, 1, NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_create(&logger, NULL, 1, NULL, &dev) == RES_OK); + CHK(smc_device_ref_put(dev) == RES_OK); - CHECK(smc_device_create(&logger, &allocator, 4, NULL, NULL), RES_BAD_ARG); - CHECK(smc_device_create(&logger, &allocator, 4, NULL, &dev), RES_OK); + CHK(smc_device_create(&logger, &allocator, 4, NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_create(&logger, &allocator, 4, NULL, &dev) == RES_OK); - CHECK(smc_device_set_rng_type(NULL, NULL), RES_BAD_ARG); - CHECK(smc_device_set_rng_type(dev, NULL), RES_BAD_ARG); - CHECK(smc_device_set_rng_type(NULL, &ssp_rng_ranlux48), RES_BAD_ARG); - CHECK(smc_device_set_rng_type(dev, &ssp_rng_ranlux48), RES_OK); + CHK(smc_device_set_rng_type(NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_set_rng_type(dev, NULL) == RES_BAD_ARG); + CHK(smc_device_set_rng_type(NULL, &ssp_rng_ranlux48) == RES_BAD_ARG); + CHK(smc_device_set_rng_type(dev, &ssp_rng_ranlux48) == RES_OK); - CHECK(smc_device_get_rng_type(NULL, NULL), RES_BAD_ARG); - CHECK(smc_device_get_rng_type(dev, NULL), RES_BAD_ARG); - CHECK(smc_device_get_rng_type(NULL, &type), RES_BAD_ARG); - CHECK(smc_device_get_rng_type(dev, &type), RES_OK); - CHECK(ssp_rng_type_eq(&type, &ssp_rng_ranlux48), 1); + CHK(smc_device_get_rng_type(NULL, NULL) == RES_BAD_ARG); + CHK(smc_device_get_rng_type(dev, NULL) == RES_BAD_ARG); + CHK(smc_device_get_rng_type(NULL, &type) == RES_BAD_ARG); + CHK(smc_device_get_rng_type(dev, &type) == RES_OK); + CHK(ssp_rng_type_eq(&type, &ssp_rng_ranlux48) == 1); - CHECK(smc_device_set_rng_type(dev, &ssp_rng_kiss), RES_OK); - CHECK(smc_device_get_rng_type(dev, &type), RES_OK); - CHECK(ssp_rng_type_eq(&type, &ssp_rng_kiss), 1); + CHK(smc_device_set_rng_type(dev, &ssp_rng_kiss) == RES_OK); + CHK(smc_device_get_rng_type(dev, &type) == RES_OK); + CHK(ssp_rng_type_eq(&type, &ssp_rng_kiss) == 1); - CHECK(smc_device_ref_put(dev), RES_OK); + CHK(smc_device_ref_put(dev) == RES_OK); - CHECK(smc_device_create(&logger, &allocator, 4, &ssp_rng_ranlux48, &dev), RES_OK); - CHECK(smc_device_ref_put(dev), RES_OK); + CHK(smc_device_create(&logger, &allocator, 4, &ssp_rng_ranlux48, &dev) == RES_OK); + CHK(smc_device_ref_put(dev) == RES_OK); logger_release(&logger); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); + CHK(mem_allocated_size() == 0); return 0; } diff --git a/src/test_smc_doubleN.c b/src/test_smc_doubleN.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -45,20 +45,19 @@ enum { struct alpha { double value; }; static res_T -cos_x(void* value, struct ssp_rng* rng, void* context) +cos_x(void* value, struct ssp_rng* rng, const unsigned ithread, void* context) { double* result = SMC_DOUBLEN(value); double samp; struct smc_doubleN_context* ctx = context; const struct alpha* alpha = ctx->integrand_data; - NCHECK(value, NULL); - NCHECK(rng, NULL); + (void)ithread; + CHK(value != NULL); + CHK(rng != NULL); samp = ssp_rng_uniform_double(rng, -PI/4.0, PI/4.0); - result[WEIGHT] = - cos(alpha->value*samp) * PI / 2.0; - result[WEIGHT_SENSIBILITY_ALPHA] = - -samp * sin(alpha->value*samp) * PI/2.0; + result[WEIGHT] = cos(alpha->value*samp) * PI / 2.0; + result[WEIGHT_SENSIBILITY_ALPHA] = -samp * sin(alpha->value*samp) * PI/2.0; return RES_OK; } @@ -79,22 +78,21 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev), - RES_OK); + CHK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev) == RES_OK); integrator.integrand = cos_x; integrator.type = &smc_doubleN; - integrator.max_steps = 100000; + integrator.max_realisations = 100000; alpha.value = a; ctx.count = WEIGHTS_COUNT; ctx.integrand_data = &alpha; - CHECK(smc_solve(dev, &integrator, NULL, &estimator), RES_MEM_ERR); + CHK(smc_solve(dev, &integrator, NULL, &estimator) == RES_MEM_ERR); ctx.count = 0; - CHECK(smc_solve(dev, &integrator, &ctx, &estimator), RES_MEM_ERR); + CHK(smc_solve(dev, &integrator, &ctx, &estimator) == RES_MEM_ERR); ctx.count = WEIGHTS_COUNT; - CHECK(smc_solve(dev, &integrator, &ctx, &estimator), RES_OK); - CHECK(smc_estimator_get_status(estimator, &status), RES_OK); + CHK(smc_solve(dev, &integrator, &ctx, &estimator) == RES_OK); + CHK(smc_estimator_get_status(estimator, &status) == RES_OK); /* Check the estimated result */ result = 2*sin(a*PI/4.0) / a; @@ -102,10 +100,10 @@ main(int argc, char** argv) a, result, SMC_DOUBLEN(status.E)[WEIGHT], SMC_DOUBLEN(status.SE)[WEIGHT]); - CHECK(eq_eps + CHK(eq_eps (result, SMC_DOUBLEN(status.E)[WEIGHT], - SMC_DOUBLEN(status.SE)[WEIGHT]), 1); + SMC_DOUBLEN(status.SE)[WEIGHT])); /* Check the estimated sensibility in alpha */ result = 2*(a*PI/4.0*cos(a*PI/4.0) - sin(a*PI/4.0)) / (a*a); @@ -113,16 +111,16 @@ main(int argc, char** argv) a, result, SMC_DOUBLEN(status.E)[WEIGHT_SENSIBILITY_ALPHA], SMC_DOUBLEN(status.SE)[WEIGHT_SENSIBILITY_ALPHA]); - CHECK(eq_eps + CHK(eq_eps (result, SMC_DOUBLEN(status.E)[WEIGHT_SENSIBILITY_ALPHA], - SMC_DOUBLEN(status.SE)[WEIGHT_SENSIBILITY_ALPHA]), 1); + SMC_DOUBLEN(status.SE)[WEIGHT_SENSIBILITY_ALPHA])); - CHECK(smc_estimator_ref_put(estimator), RES_OK); - CHECK(smc_device_ref_put(dev), RES_OK); + CHK(smc_estimator_ref_put(estimator) == RES_OK); + CHK(smc_device_ref_put(dev) == RES_OK); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); + CHK(mem_allocated_size() == 0); return 0; } diff --git a/src/test_smc_errors.c b/src/test_smc_errors.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is a computer program whose purpose is to manage the * statistical estimation of a function. @@ -35,17 +35,17 @@ #include <star/ssp.h> static res_T -compute_1(void* value, struct ssp_rng* rng, void* context) +compute_1 + (void* value, struct ssp_rng* rng, const unsigned ithread, void* context) { /* pretend that 10% of the realizations fail */ int ok = ssp_rng_canonical(rng) > 0.1; - (void)context; - if (ok) - /* weight is 1 */ - SMC_DOUBLE(value) = 1; - else - /* clear weight */ - SMC_DOUBLE(value) = 0; + (void)context, (void)ithread; + if(ok) { + SMC_DOUBLE(value) = 1; /* weight is 1 */ + } else { + SMC_DOUBLE(value) = 0; /* clear weight */ + } /* a realization has been carried out only if ok */ return ok ? RES_OK : RES_BAD_ARG; } @@ -66,16 +66,14 @@ main(int argc, char** argv) integrator.integrand = &compute_1; integrator.type = &smc_double; - integrator.max_steps = 10000; - /* set auto cancel OFF */ - integrator.max_failures = SMC_AUTO_CANCEL_OFF; + integrator.max_realisations = 10000; SMC(solve(dev, &integrator, NULL, &estimator)); SMC(estimator_get_status(estimator, &status)); /* result must be 1 with std err = 0 */ - CHECK(SMC_DOUBLE(status.E), 1); - CHECK(SMC_DOUBLE(status.SE), 0); + CHK(SMC_DOUBLE(status.E) == 1); + CHK(SMC_DOUBLE(status.SE) == 0); printf("OK realizations = %lu; KO realizations = %lu\n", (unsigned long)status.N, (unsigned long)status.NF); @@ -83,18 +81,18 @@ main(int argc, char** argv) SMC(estimator_ref_put(estimator)); /* set auto cancel ON */ - integrator.max_failures = integrator.max_steps / 1000; + integrator.max_failures = integrator.max_realisations / 1000; SMC(solve(dev, &integrator, NULL, &estimator)); SMC(estimator_get_status(estimator, &status)); /* it is expected that solve was auto-canceled */ - NCHECK(integrator.max_steps, status.N); - CHECK(status.NF >= integrator.max_failures + 1, 1); + CHK(integrator.max_realisations != status.N); + CHK(status.NF >= integrator.max_failures + 1); /* result must be 1 with std err = 0 */ - CHECK(SMC_DOUBLE(status.E), 1); - CHECK(SMC_DOUBLE(status.SE), 0); + CHK(SMC_DOUBLE(status.E) == 1); + CHK(SMC_DOUBLE(status.SE) == 0); printf("OK realizations = %lu; KO realizations = %lu\n", (unsigned long)status.N, (unsigned long)status.NF); @@ -104,7 +102,7 @@ main(int argc, char** argv) check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); + CHK(mem_allocated_size() == 0); return 0; } diff --git a/src/test_smc_integrate.c b/src/test_smc_integrate.c @@ -1,182 +0,0 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) - * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ - -#include "smc.h" -#include "test_smc_utils.h" - -#include <star/ssp.h> - -#include <math.h> - -static void* -dbl2_create(struct mem_allocator* allocator, void* ctx) -{ - NCHECK(allocator, NULL); - CHECK(ctx, (void*)0xC0DE); - return MEM_CALLOC(allocator, 2, sizeof(double)); -} - -static void -dbl2_destroy(struct mem_allocator* allocator, void* data) -{ - NCHECK(allocator, NULL); - NCHECK(data, NULL); - MEM_RM(allocator, data); -} - -static void -dbl2_clear(void* data) -{ - ((double*)data)[0] = ((double*)data)[1] = 0.0; -} - -static void -dbl2_add(void* result, const void* op0, const void* op1) -{ - int i; - FOR_EACH(i, 0, 2) { - ((double*)result)[i] = ((double*)op0)[i] + ((double*)op1)[i]; - } -} - -static const struct smc_type_accum smc_accum_dbl2 = { - dbl2_create, - dbl2_destroy, - dbl2_clear, - dbl2_add -}; - -static res_T -rcp_x(void* value, struct ssp_rng* rng, void* ctx) -{ - double* result = value; - double samp; - double val; - NCHECK(value, NULL); - NCHECK(rng, NULL); - CHECK(ctx, (void*)0xC0DE); - samp = ssp_rng_uniform_double(rng, 1.0, 4.0); - val = 1.0 / samp * 3; - result[0] += val; - result[1] += val*val; - return RES_OK; -} - -static res_T -cos_x(void* value, struct ssp_rng* rng, void* ctx) -{ - double* result = value; - double samp; - double val; - NCHECK(value, NULL); - NCHECK(rng, NULL); - CHECK(ctx, (void*)0xC0DE); - samp = ssp_rng_uniform_double(rng, -PI/4.0, PI/4.0); - val = cos(samp) * PI / 2.0; - result[0] += val; - result[1] += val*val; - return RES_OK; -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct smc_device* dev; - struct smc_integrator_accum integrator = SMC_INTEGRATOR_ACCUM_NULL; - struct smc_accumulator* accum; - struct smc_accumulator_status status; - double* val; - double E, V, SE; - (void)argc, (void)argv; - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev), - RES_OK); - - integrator.integrand = rcp_x; - integrator.type = &smc_accum_dbl2; - integrator.max_steps = 10000; - - CHECK(smc_integrate(NULL, NULL, (void*)0xC0DE, NULL), RES_BAD_ARG); - CHECK(smc_integrate(dev, NULL, (void*)0xC0DE, NULL), RES_BAD_ARG); - CHECK(smc_integrate(NULL, &integrator, (void*)0xC0DE, NULL), RES_BAD_ARG); - CHECK(smc_integrate(dev, &integrator, (void*)0xC0DE, NULL), RES_BAD_ARG); - CHECK(smc_integrate(NULL, NULL, (void*)0xC0DE, &accum), RES_BAD_ARG); - CHECK(smc_integrate(dev, NULL, (void*)0xC0DE, &accum), RES_BAD_ARG); - CHECK(smc_integrate(NULL, &integrator, (void*)0xC0DE, &accum), RES_BAD_ARG); - CHECK(smc_integrate(dev, &integrator, (void*)0xC0DE, &accum), RES_OK); - - CHECK(smc_accumulator_get_status(NULL, NULL), RES_BAD_ARG); - CHECK(smc_accumulator_get_status(accum, NULL), RES_BAD_ARG); - CHECK(smc_accumulator_get_status(NULL, &status), RES_BAD_ARG); - CHECK(smc_accumulator_get_status(accum, &status), RES_OK); - - val = status.value; - E = val[0] / (double)status.N; - V = val[1] / (double)status.N - (val[0]*val[0]) / (double)(status.N * status.N); - SE = sqrt(V / (double)status.N); - - printf("Integral[1, 4] 1/x dx = %g; E = %g; SE = %g\n", - log(4.0) - log(1.0), E, SE); - CHECK(eq_eps(log(4.0) - log(1.0), E, 2.0 * SE), 1); - - CHECK(smc_accumulator_ref_get(NULL), RES_BAD_ARG); - CHECK(smc_accumulator_ref_get(accum), RES_OK); - CHECK(smc_accumulator_ref_put(NULL), RES_BAD_ARG); - CHECK(smc_accumulator_ref_put(accum), RES_OK); - CHECK(smc_accumulator_ref_put(accum), RES_OK); - - integrator.type = NULL; - CHECK(smc_integrate(dev, &integrator, NULL, &accum), RES_BAD_ARG); - integrator.type = &smc_accum_dbl2; - integrator.integrand = NULL; - CHECK(smc_integrate(dev, &integrator, NULL, &accum), RES_BAD_ARG); - - integrator.integrand = cos_x; - CHECK(smc_integrate(dev, &integrator, (void*)0xC0DE, &accum), RES_OK); - CHECK(smc_accumulator_get_status(accum, &status), RES_OK); - - val = status.value; - E = val[0] / (double)status.N; - V = val[1] / (double)status.N - (val[0]*val[0]) / (double)(status.N * status.N); - SE = sqrt(V / (double)status.N); - - printf("Integral[-PI/4, PI/4] cos(x) dx = %g; E = %g; SE = %g\n", - 2*sin(PI/4.0), E, SE); - CHECK(eq_eps(2*sin(PI/4.0), E, 2 * SE), 1); - - CHECK(smc_accumulator_ref_put(accum), RES_OK); - CHECK(smc_device_ref_put(dev), RES_OK); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); - return 0; -} - diff --git a/src/test_smc_light_path.c b/src/test_smc_light_path.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, @@ -129,7 +129,7 @@ cbox_get_ids(const unsigned itri, unsigned ids[3], void* data) { const unsigned id = itri * 3; struct cbox_desc* desc = data; - NCHECK(desc, NULL); + CHK(desc != NULL); ids[0] = desc->indices[id + 0]; ids[1] = desc->indices[id + 1]; ids[2] = desc->indices[id + 2]; @@ -139,7 +139,7 @@ static INLINE void cbox_get_position(const unsigned ivert, float position[3], void* data) { struct cbox_desc* desc = data; - NCHECK(desc, NULL); + CHK(desc != NULL); position[0] = desc->vertices[ivert*3 + 0]; position[1] = desc->vertices[ivert*3 + 1]; position[2] = desc->vertices[ivert*3 + 2]; @@ -165,9 +165,9 @@ camera_init(struct camera* cam) ASSERT(cam); f3_set(cam->pos, pos); - f = f3_normalize(cam->z, f3_sub(cam->z, tgt, pos)); NCHECK(f, 0); - f = f3_normalize(cam->x, f3_cross(cam->x, cam->z, up)); NCHECK(f, 0); - f = f3_normalize(cam->y, f3_cross(cam->y, cam->z, cam->x)); NCHECK(f, 0); + f = f3_normalize(cam->z, f3_sub(cam->z, tgt, pos)); CHK(f != 0); + f = f3_normalize(cam->x, f3_cross(cam->x, cam->z, up)); CHK(f != 0); + f = f3_normalize(cam->y, f3_cross(cam->y, cam->z, cam->x)); CHK(f != 0); f3_divf(cam->z, cam->z, (float)tan(fov_x*0.5f)); f3_divf(cam->y, cam->y, proj_ratio); } @@ -185,7 +185,7 @@ camera_ray f3_mulf(x, cam->x, pixel[0]*2.f - 1.f); f3_mulf(y, cam->y, pixel[1]*2.f - 1.f); f3_add(dir, f3_add(dir, x, y), cam->z); - f = f3_normalize(dir, dir); NCHECK(f, 0); + f = f3_normalize(dir, dir); CHK(f != 0); f3_set(org, cam->pos); } @@ -211,10 +211,10 @@ direct_lighting float wi[3]; float range[2]; - NCHECK(view, NULL); - NCHECK(pos, NULL); - NCHECK(N, NULL); - CHECK(f3_is_normalized(N), 1); + CHK(view != NULL); + CHK(pos != NULL); + CHK(N != NULL); + CHK(f3_is_normalized(N) == 1); f3_sub(wi, light_pos, pos); len = f3_normalize(wi, wi); @@ -222,7 +222,7 @@ direct_lighting /* Trace shadow ray */ range[0] = EPSILON; range[1] = len; - CHECK(s3d_scene_view_trace_ray(view, pos, wi, range, NULL, &hit), RES_OK); + CHK(s3d_scene_view_trace_ray(view, pos, wi, range, NULL, &hit) == RES_OK); if(!S3D_HIT_NONE(&hit)) return 0.f; /* Light is occluded */ len *= 0.01f; /* Transform len from centimer to meter */ @@ -239,13 +239,14 @@ skydome_lighting(const float wi[3]) const float sky_irradiance = 12.0f; float u; - NCHECK(wi, NULL); + CHK(wi != NULL); u = CLAMP(wi[2], 0.f, 0.05f) * 1.f; return u * sky_irradiance + (1.f - u) * ground_irradiance; } static res_T -light_path_integrator(void* value, struct ssp_rng* rng, void* data) +light_path_integrator + (void* value, struct ssp_rng* rng, const unsigned ithread, void* data) { struct integrator_context* ctx = data; float pix_lower[2], pix_upper[2]; /* Pixel AABB */ @@ -255,9 +256,11 @@ light_path_integrator(void* value, struct ssp_rng* rng, void* data) float throughput = 1.f; int idepth; - NCHECK(value, NULL); - NCHECK(rng, NULL); - NCHECK(data, NULL); + (void)ithread; + + CHK(value != NULL); + CHK(rng != NULL); + CHK(data != NULL); /* Compute the pixel bound */ pix_lower[0] = (float)ctx->ipixel[0] / (float)IMG_WIDTH; @@ -275,15 +278,13 @@ light_path_integrator(void* value, struct ssp_rng* rng, void* data) FOR_EACH(idepth, 0, LIGHT_PATH_DEPTH) { struct s3d_hit hit = S3D_HIT_NULL; - double Nd[3]; - double sample[4]; float cos_theta; float pdf; float pos[3]; float N[3] = {0, 0, 0}; - CHECK(s3d_scene_view_trace_ray - (ctx->view, ray_org, ray_dir, ray_range, NULL, &hit), RES_OK); + CHK(s3d_scene_view_trace_ray + (ctx->view, ray_org, ray_dir, ray_range, NULL, &hit) == RES_OK); if(S3D_HIT_NONE(&hit)) { /* Skydome lighting */ L += throughput * skydome_lighting(ray_dir); @@ -299,12 +300,9 @@ light_path_integrator(void* value, struct ssp_rng* rng, void* data) L += throughput * direct_lighting(ctx->view, pos, N); /* New ray */ - d3_normalize(Nd, d3_set_f3(Nd, N)); - ssp_ran_hemisphere_cos(rng, Nd, sample); - pdf = (float)sample[3]; - cos_theta = (float)d3_dot(Nd, sample); + ssp_ran_hemisphere_cos_float(rng, N, ray_dir, &pdf); + cos_theta = f3_dot(N, ray_dir); f3_set(ray_org, pos); - f3_normalize(ray_dir, f3_set_d3(ray_dir, sample)); ray_range[0] = EPSILON; throughput *= (float)(ALBEDO / PI) / pdf * cos_theta; } @@ -336,58 +334,58 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(image_init(&allocator, &img), RES_OK); - CHECK(image_setup - (&img, IMG_WIDTH, IMG_HEIGHT, 3*IMG_WIDTH, IMAGE_RGB8, NULL), RES_OK); + CHK(image_init(&allocator, &img) == RES_OK); + CHK(image_setup + (&img, IMG_WIDTH, IMG_HEIGHT, 3*IMG_WIDTH, IMAGE_RGB8, NULL) == RES_OK); - CHECK(s3d_device_create(NULL, &allocator, 0, &dev), RES_OK); - CHECK(s3d_scene_create(dev, &scn), RES_OK); + CHK(s3d_device_create(NULL, &allocator, 0, &dev) == RES_OK); + CHK(s3d_scene_create(dev, &scn) == RES_OK); attrib.usage = S3D_POSITION; attrib.type = S3D_FLOAT3; attrib.get = cbox_get_position; - CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); - CHECK(s3d_mesh_setup_indexed_vertices(shape, cbox_walls_ntris, cbox_get_ids, - cbox_walls_nverts, &attrib, 1, &cbox_walls_desc), RES_OK); - CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); - CHECK(s3d_shape_ref_put(shape), RES_OK); + CHK(s3d_shape_create_mesh(dev, &shape) == RES_OK); + CHK(s3d_mesh_setup_indexed_vertices(shape, cbox_walls_ntris, cbox_get_ids, + cbox_walls_nverts, &attrib, 1, &cbox_walls_desc) == RES_OK); + CHK(s3d_scene_attach_shape(scn, shape) == RES_OK); + CHK(s3d_shape_ref_put(shape) == RES_OK); - CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); - CHECK(s3d_mesh_setup_indexed_vertices(shape, cbox_block_ntris, cbox_get_ids, - cbox_short_block_nverts, &attrib, 1, &cbox_short_block_desc), RES_OK); - CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); - CHECK(s3d_shape_ref_put(shape), RES_OK); + CHK(s3d_shape_create_mesh(dev, &shape) == RES_OK); + CHK(s3d_mesh_setup_indexed_vertices(shape, cbox_block_ntris, cbox_get_ids, + cbox_short_block_nverts, &attrib, 1, &cbox_short_block_desc) == RES_OK); + CHK(s3d_scene_attach_shape(scn, shape) == RES_OK); + CHK(s3d_shape_ref_put(shape) == RES_OK); - CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); - CHECK(s3d_mesh_setup_indexed_vertices(shape, cbox_block_ntris, cbox_get_ids, - cbox_tall_block_nverts, &attrib, 1, &cbox_tall_block_desc), RES_OK); - CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); - CHECK(s3d_shape_ref_put(shape), RES_OK); + CHK(s3d_shape_create_mesh(dev, &shape) == RES_OK); + CHK(s3d_mesh_setup_indexed_vertices(shape, cbox_block_ntris, cbox_get_ids, + cbox_tall_block_nverts, &attrib, 1, &cbox_tall_block_desc) == RES_OK); + CHK(s3d_scene_attach_shape(scn, shape) == RES_OK); + CHK(s3d_shape_ref_put(shape) == RES_OK); - CHECK(s3d_scene_instantiate(scn, &shape), RES_OK); - CHECK(s3d_scene_ref_put(scn), RES_OK); - CHECK(s3d_instance_set_position(shape, f3(pos, -100.f, 0.f, -2.f)), RES_OK); + CHK(s3d_scene_instantiate(scn, &shape) == RES_OK); + CHK(s3d_scene_ref_put(scn) == RES_OK); + CHK(s3d_instance_set_position(shape, f3(pos, -100.f, 0.f, -2.f)) == RES_OK); - CHECK(s3d_scene_create(dev, &scn), RES_OK); - CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); - CHECK(s3d_shape_ref_put(shape), RES_OK); + CHK(s3d_scene_create(dev, &scn) == RES_OK); + CHK(s3d_scene_attach_shape(scn, shape) == RES_OK); + CHK(s3d_shape_ref_put(shape) == RES_OK); - CHECK(s3d_scene_view_create(scn, S3D_TRACE, &view), RES_OK); + CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK); - CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &smc), - RES_OK); + CHK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &smc) + == RES_OK); integrator.integrand = light_path_integrator; integrator.type = &smc_float; - integrator.max_steps = 4; + integrator.max_realisations = 4; contexts = MEM_CALLOC (&allocator, IMG_WIDTH*IMG_HEIGHT, sizeof(struct integrator_context)); - NCHECK(contexts, NULL); + CHK(contexts != NULL); estimators = MEM_CALLOC (&allocator, IMG_WIDTH*IMG_HEIGHT, sizeof(struct smc_estimator*)); - NCHECK(estimators, NULL); + CHK(estimators != NULL); camera_init(&cam); @@ -402,8 +400,8 @@ main(int argc, char** argv) contexts[ictx].ipixel[1] = iy; }} - CHECK(smc_solve_N(smc, &integrator, IMG_WIDTH * IMG_HEIGHT, contexts, - sizeof(struct integrator_context), estimators), RES_OK); + CHK(smc_solve_N(smc, &integrator, IMG_WIDTH * IMG_HEIGHT, contexts, + sizeof(struct integrator_context), estimators) == RES_OK); FOR_EACH(iy, 0, IMG_HEIGHT) { FOR_EACH(ix, 0, IMG_WIDTH) { @@ -413,27 +411,27 @@ main(int argc, char** argv) float col; unsigned char colu; - CHECK(smc_estimator_get_status(estimators[iestimator], &status), RES_OK); + CHK(smc_estimator_get_status(estimators[iestimator], &status) == RES_OK); col = (float)pow(SMC_FLOAT(status.E), 1.0/GAMMA); /* Gamma correction */ colu = (uint8_t)(CLAMP(col, 0.f, 1.f) * 255.f); /* Float to U8 */ pix[0] = pix[1] = pix[2] = colu; - CHECK(smc_estimator_ref_put(estimators[iestimator]), RES_OK); + CHK(smc_estimator_ref_put(estimators[iestimator]) == RES_OK); }} image_write_ppm_stream(&img, 0, stdout); - CHECK(image_release(&img), RES_OK); + CHK(image_release(&img) == RES_OK); MEM_RM(&allocator, contexts); MEM_RM(&allocator, estimators); - CHECK(s3d_scene_view_ref_put(view), RES_OK); + CHK(s3d_scene_view_ref_put(view) == RES_OK); - CHECK(s3d_device_ref_put(dev), RES_OK); - CHECK(s3d_scene_ref_put(scn), RES_OK); - CHECK(smc_device_ref_put(smc), RES_OK); + CHK(s3d_device_ref_put(dev) == RES_OK); + CHK(s3d_scene_ref_put(scn) == RES_OK); + CHK(smc_device_ref_put(smc) == RES_OK); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); + CHK(mem_allocated_size() == 0); return 0; } diff --git a/src/test_smc_solve.c b/src/test_smc_solve.c @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, @@ -35,26 +35,28 @@ #include <math.h> static res_T -rcp_x(void* value, struct ssp_rng* rng, void* ctx) +rcp_x(void* value, struct ssp_rng* rng, const unsigned ithread, void* ctx) { double* result = value; double samp; - NCHECK(value, NULL); - NCHECK(rng, NULL); - CHECK(ctx, NULL); + (void)ithread; + CHK(value != NULL); + CHK(rng != NULL); + CHK(ctx == NULL); samp = ssp_rng_uniform_double(rng, 1.0, 4.0); *result = 1.0 / samp * 3; return RES_OK; } static res_T -cos_x(void* value, struct ssp_rng* rng, void* ctx) +cos_x(void* value, struct ssp_rng* rng, const unsigned ithread, void* ctx) { float* result = value; double samp; - NCHECK(value, NULL); - NCHECK(rng, NULL); - CHECK(ctx, (void*)0xC0DE); + (void)ithread; + CHK(value != NULL); + CHK(rng != NULL); + CHK(ctx == (void*)0xC0DE); samp = ssp_rng_uniform_double(rng, -PI/4.0, PI/4.0); *result = (float)(cos(samp) * PI / 2.0); return RES_OK; @@ -72,53 +74,52 @@ main(int argc, char** argv) mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev), - RES_OK); + CHK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev) == RES_OK); integrator.integrand = rcp_x; integrator.type = &smc_double; - integrator.max_steps = 10000; - - CHECK(smc_solve(NULL, NULL, NULL, NULL), RES_BAD_ARG); - CHECK(smc_solve(dev, NULL, NULL, NULL), RES_BAD_ARG); - CHECK(smc_solve(NULL, &integrator, NULL, NULL), RES_BAD_ARG); - CHECK(smc_solve(dev, &integrator, NULL, NULL), RES_BAD_ARG); - CHECK(smc_solve(NULL, NULL, NULL, &estimator), RES_BAD_ARG); - CHECK(smc_solve(dev, NULL, NULL, &estimator), RES_BAD_ARG); - CHECK(smc_solve(NULL, &integrator, NULL, &estimator), RES_BAD_ARG); - CHECK(smc_solve(dev, &integrator, NULL, &estimator), RES_OK); - - CHECK(smc_estimator_get_status(NULL, NULL), RES_BAD_ARG); - CHECK(smc_estimator_get_status(estimator, NULL), RES_BAD_ARG); - CHECK(smc_estimator_get_status(NULL, &status), RES_BAD_ARG); - CHECK(smc_estimator_get_status(estimator, &status), RES_OK); + integrator.max_realisations = 10000; + + CHK(smc_solve(NULL, NULL, NULL, NULL) == RES_BAD_ARG); + CHK(smc_solve(dev, NULL, NULL, NULL) == RES_BAD_ARG); + CHK(smc_solve(NULL, &integrator, NULL, NULL) == RES_BAD_ARG); + CHK(smc_solve(dev, &integrator, NULL, NULL) == RES_BAD_ARG); + CHK(smc_solve(NULL, NULL, NULL, &estimator) == RES_BAD_ARG); + CHK(smc_solve(dev, NULL, NULL, &estimator) == RES_BAD_ARG); + CHK(smc_solve(NULL, &integrator, NULL, &estimator) == RES_BAD_ARG); + CHK(smc_solve(dev, &integrator, NULL, &estimator) == RES_OK); + + CHK(smc_estimator_get_status(NULL, NULL) == RES_BAD_ARG); + CHK(smc_estimator_get_status(estimator, NULL) == RES_BAD_ARG); + CHK(smc_estimator_get_status(NULL, &status) == RES_BAD_ARG); + CHK(smc_estimator_get_status(estimator, &status) == RES_OK); printf("Integral[1, 4] 1/x dx = %g; E = %g; SE = %g\n", log(4.0) - log(1.0), SMC_DOUBLE(status.E), SMC_DOUBLE(status.SE)); - CHECK(eq_eps - (log(4.0) - log(1.0), SMC_DOUBLE(status.E), 2.0 * SMC_DOUBLE(status.SE)), 1); - CHECK(smc_estimator_ref_put(estimator), RES_OK); + CHK(eq_eps + (log(4.0) - log(1.0), SMC_DOUBLE(status.E), 2.0 * SMC_DOUBLE(status.SE))); + CHK(smc_estimator_ref_put(estimator) == RES_OK); integrator.type = NULL; - CHECK(smc_solve(dev, &integrator, NULL, &estimator), RES_BAD_ARG); + CHK(smc_solve(dev, &integrator, NULL, &estimator) == RES_BAD_ARG); integrator.type = &smc_double; integrator.integrand = NULL; - CHECK(smc_solve(dev, &integrator, NULL, &estimator), RES_BAD_ARG); + CHK(smc_solve(dev, &integrator, NULL, &estimator) == RES_BAD_ARG); integrator.integrand = cos_x; integrator.type = &smc_float; - CHECK(smc_solve(dev, &integrator, (void*)0xC0DE, &estimator), RES_OK); - CHECK(smc_estimator_get_status(estimator, &status), RES_OK); + CHK(smc_solve(dev, &integrator, (void*)0xC0DE, &estimator) == RES_OK); + CHK(smc_estimator_get_status(estimator, &status) == RES_OK); printf("Integral[-PI/4, PI/4] cos(x) dx = %f; E = %f; SE = %f\n", 2*sin(PI/4.0), SMC_FLOAT(status.E), SMC_FLOAT(status.SE)); - CHECK(eq_eps - ((float)2*sin(PI/4.0), SMC_FLOAT(status.E), 2 * SMC_FLOAT(status.SE)), 1); - CHECK(smc_device_ref_put(dev), RES_OK); + CHK(eq_eps + ((float)2*sin(PI/4.0), SMC_FLOAT(status.E), 2 * SMC_FLOAT(status.SE))); + CHK(smc_device_ref_put(dev) == RES_OK); - CHECK(smc_estimator_ref_put(estimator), RES_OK); + CHK(smc_estimator_ref_put(estimator) == RES_OK); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); + CHK(mem_allocated_size() == 0); return 0; } diff --git a/src/test_smc_utils.h b/src/test_smc_utils.h @@ -1,4 +1,4 @@ -/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) +/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com) * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use,