PartMC  2.6.1
rand_gsl.c
Go to the documentation of this file.
1 /* Copyright (C) 2010 Matthew West
2  * Licensed under the GNU General Public License version 2 or (at your
3  * option) any later version. See the file COPYING for details.
4  */
5 
6 /** \file
7  * \brief Wrapper routines for GSL random number functions.
8  */
9 
10 #include <stdio.h>
11 #include <time.h>
12 #include <gsl/gsl_errno.h>
13 #include <gsl/gsl_rng.h>
14 #include <gsl/gsl_randist.h>
15 
16 /** \brief Private internal-use variable to store the random number
17  * generator.
18  */
19 static gsl_rng *pmc_rand_gsl_rng = NULL;
20 
21 /** \brief Result code indicating successful completion.
22  */
23 #define PMC_RAND_GSL_SUCCESS 0
24 /** \brief Result code indicating initialization failure.
25  */
26 #define PMC_RAND_GSL_INIT_FAIL 1
27 /** \brief Result code indicating the generator was not initialized
28  * when it should have been.
29  */
30 #define PMC_RAND_GSL_NOT_INIT 2
31 /** \brief Result code indicating the generator was already
32  * initialized when an initialization was attempted.
33  */
34 #define PMC_RAND_GSL_ALREADY_INIT 3
35 
36 /** \brief Initialize the random number generator with the given seed.
37  *
38  * This must be called before any other GSL random number functions
39  * are called.
40  *
41  * \param seed The random seed to use.
42  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
43  * \sa pmc_rand_finalize_gsl() to cleanup the generator.
44  */
45 int pmc_srand_gsl(int seed)
46 {
47  if (pmc_rand_gsl_rng) {
49  }
50  gsl_set_error_handler_off(); // turn off automatic error handling
51  pmc_rand_gsl_rng = gsl_rng_alloc(gsl_rng_mt19937);
52  if (pmc_rand_gsl_rng == NULL) {
54  }
55  gsl_rng_set(pmc_rand_gsl_rng, seed);
56  return PMC_RAND_GSL_SUCCESS;
57 }
58 
59 /** \brief Cleanup and deallocate the random number generator.
60  *
61  * This must be called after pmc_srand_gsl().
62  *
63  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
64  */
66 {
67  if (!pmc_rand_gsl_rng) {
68  return PMC_RAND_GSL_NOT_INIT;
69  }
70  gsl_rng_free(pmc_rand_gsl_rng);
71  pmc_rand_gsl_rng = NULL;
72  return PMC_RAND_GSL_SUCCESS;
73 }
74 
75 /** \brief Generate a uniform random number in \f$[0,1)\f$.
76  *
77  * \param harvest A pointer to the generated random number.
78  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
79  */
80 int pmc_rand_gsl(double *harvest)
81 {
82  if (!pmc_rand_gsl_rng) {
83  return PMC_RAND_GSL_NOT_INIT;
84  }
85  *harvest = gsl_rng_uniform(pmc_rand_gsl_rng);
86  return PMC_RAND_GSL_SUCCESS;
87 }
88 
89 /** \brief Generate a uniform random integer in \f$[1,n]\f$.
90  *
91  * \param n The upper limit of the random integer.
92  * \param harvest A pointer to the generated random number.
93  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
94  */
95 int pmc_rand_int_gsl(int n, int *harvest)
96 {
97  if (!pmc_rand_gsl_rng) {
98  return PMC_RAND_GSL_NOT_INIT;
99  }
100  *harvest = gsl_rng_uniform_int(pmc_rand_gsl_rng, n) + 1;
101  return PMC_RAND_GSL_SUCCESS;
102 }
103 
104 /** \brief Generate a normally-distributed random number.
105  *
106  * \param mean The mean of the distribution.
107  * \param stddev The standard deviation of the distribution.
108  * \param harvest A pointer to the generated random number.
109  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
110  */
111 int pmc_rand_normal_gsl(double mean, double stddev, double *harvest)
112 {
113  if (!pmc_rand_gsl_rng) {
114  return PMC_RAND_GSL_NOT_INIT;
115  }
116  *harvest = gsl_ran_gaussian(pmc_rand_gsl_rng, stddev) + mean;
117  return PMC_RAND_GSL_SUCCESS;
118 }
119 
120 /** \brief Generate a Poisson-distributed random integer.
121  *
122  * \param mean The mean of the distribution.
123  * \param harvest A pointer to the generated random number.
124  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
125  */
126 int pmc_rand_poisson_gsl(double mean, int *harvest)
127 {
128  if (!pmc_rand_gsl_rng) {
129  return PMC_RAND_GSL_NOT_INIT;
130  }
131  *harvest = gsl_ran_poisson(pmc_rand_gsl_rng, mean);
132  return PMC_RAND_GSL_SUCCESS;
133 }
134 
135 /** \brief Generate a Binomial-distributed random integer.
136  *
137  * \param n The sample size for the distribution.
138  * \param p The sample probability for the distribution.
139  * \param harvest A pointer to the generated random number.
140  * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code.
141  */
142 int pmc_rand_binomial_gsl(int n, double p, int *harvest)
143 {
144  unsigned int u;
145 
146  if (!pmc_rand_gsl_rng) {
147  return PMC_RAND_GSL_NOT_INIT;
148  }
149  u = n;
150  *harvest = gsl_ran_binomial(pmc_rand_gsl_rng, p, u);
151  return PMC_RAND_GSL_SUCCESS;
152 }
PMC_RAND_GSL_INIT_FAIL
#define PMC_RAND_GSL_INIT_FAIL
Result code indicating initialization failure.
Definition: rand_gsl.c:26
pmc_srand_gsl
int pmc_srand_gsl(int seed)
Initialize the random number generator with the given seed.
Definition: rand_gsl.c:45
pmc_rand_gsl_rng
static gsl_rng * pmc_rand_gsl_rng
Private internal-use variable to store the random number generator.
Definition: rand_gsl.c:19
pmc_rand_poisson_gsl
int pmc_rand_poisson_gsl(double mean, int *harvest)
Generate a Poisson-distributed random integer.
Definition: rand_gsl.c:126
pmc_rand_finalize_gsl
int pmc_rand_finalize_gsl()
Cleanup and deallocate the random number generator.
Definition: rand_gsl.c:65
pmc_rand_int_gsl
int pmc_rand_int_gsl(int n, int *harvest)
Generate a uniform random integer in .
Definition: rand_gsl.c:95
pmc_rand_gsl
int pmc_rand_gsl(double *harvest)
Generate a uniform random number in .
Definition: rand_gsl.c:80
PMC_RAND_GSL_SUCCESS
#define PMC_RAND_GSL_SUCCESS
Result code indicating successful completion.
Definition: rand_gsl.c:23
PMC_RAND_GSL_NOT_INIT
#define PMC_RAND_GSL_NOT_INIT
Result code indicating the generator was not initialized when it should have been.
Definition: rand_gsl.c:30
pmc_rand_binomial_gsl
int pmc_rand_binomial_gsl(int n, double p, int *harvest)
Generate a Binomial-distributed random integer.
Definition: rand_gsl.c:142
pmc_rand_normal_gsl
int pmc_rand_normal_gsl(double mean, double stddev, double *harvest)
Generate a normally-distributed random number.
Definition: rand_gsl.c:111
PMC_RAND_GSL_ALREADY_INIT
#define PMC_RAND_GSL_ALREADY_INIT
Result code indicating the generator was already initialized when an initialization was attempted.
Definition: rand_gsl.c:34