star-sp

Random number generators and distributions
git clone git://git.meso-star.fr/star-sp.git
Log | Files | Refs | README | LICENSE

commit fb337ef6236d964991f8fd43c274a56f7405385f
parent b6cb3e32af3963739a363c265f196fda4f494748
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu,  7 Jul 2016 10:15:47 +0200

Add uniform disk distribution.

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssp.h | 20++++++++++++++++++++
Asrc/test_ssp_ran_uniform_disk.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -156,6 +156,7 @@ if(NOT NO_TEST) new_test(test_ssp_rng_proxy) new_test(test_ssp_ran_gaussian) new_test(test_ssp_ran_piecewise_linear) + new_test(test_ssp_ran_uniform_disk) endif() ################################################################################ diff --git a/src/ssp.h b/src/ssp.h @@ -643,6 +643,26 @@ ssp_ran_piecewise_linear_get struct ssp_rng* rng, double *res); +/******************************************************************************* + * Uniform disk distribution + ******************************************************************************/ + +static FINLINE res_T +ssp_ran_uniform_disk + (struct ssp_rng* rng, + double radius, + double pt[2]) +{ + double theta, r; + if(!rng || !pt || radius <= 0) return RES_BAD_ARG; + + theta = ssp_rng_uniform_double(rng, 0, 2 * PI); + r = radius * sqrt(ssp_rng_canonical(rng)); + pt[0] = r * cos(theta); + pt[1] = r * sin(theta); + return RES_OK; +} + END_DECLS #endif /* SSP_H */ diff --git a/src/test_ssp_ran_uniform_disk.c b/src/test_ssp_ran_uniform_disk.c @@ -0,0 +1,95 @@ +/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) + * + * This software is a program whose purpose is to test the spp library. + * + * 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 "ssp.h" +#include "test_ssp_utils.h" +#include <rsys/math.h> + +#define NBS 1000000 + +int +main(int argc, char** argv) +{ + struct ssp_rng_proxy* proxy; + struct ssp_rng* rng; + struct mem_allocator allocator; + int i; + unsigned r, c, nb = 0; + double pt[2]; + double x = 0, x2 = 0; + double mean, std; + double exp_mean = 20 * 20 * NBS / (PI * 100 * 100 ), exp_std = 0; + unsigned counts[10][10] = {0}; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + CHECK(ssp_rng_proxy_create(&allocator, &ssp_rng_threefry, 1, &proxy), RES_OK); + CHECK(ssp_rng_proxy_create_rng(proxy, 0, &rng), RES_OK); + + CHECK(ssp_ran_uniform_disk(NULL, 100, pt), RES_BAD_ARG); + CHECK(ssp_ran_uniform_disk(rng, -100, pt), RES_BAD_ARG); + CHECK(ssp_ran_uniform_disk(rng, 100, pt), RES_OK); + + for (i = 0; i < NBS; i++) { + CHECK(ssp_ran_uniform_disk(rng, 100, pt), RES_OK); + /* locate pt in a 10x10 grid */ + r = (unsigned)((100 + pt[0]) / 20); + c = (unsigned)((100 + pt[1]) / 20); + ++counts[r][c]; + } + + for (r = 0; r < 10; r++) { + unsigned _x = (r >= 5 ? r - 4 : r - 5) * 20; + for (c = 0; c < 10; c++) { + unsigned _y = (c >= 5 ? c - 4 : c - 5) * 20; + unsigned r2 = _x * _x + _y * _y; + if (r2 > 100 * 100) + /* this square is not (fully) in the disk */ + continue; + ++nb; + x += counts[r][c]; + x2 += counts[r][c] * counts[r][c]; + } + } + mean = x/nb; + std = sqrt(x2/nb - x/nb*x/nb); + printf("%g %g\n", mean, std); + CHECK(fabs(mean - exp_mean) < 10, 1); + CHECK(fabs(std - exp_std) < 100, 1); + + CHECK(ssp_rng_ref_put(rng), RES_OK); + CHECK(ssp_rng_proxy_ref_put(proxy), RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +}