PartMC
2.2.0
|
00001 /* Copyright (C) 2010 Matthew West 00002 * Licensed under the GNU General Public License version 2 or (at your 00003 * option) any later version. See the file COPYING for details. 00004 */ 00005 00006 /** \file 00007 * \brief Wrapper routines for GSL random number functions. 00008 */ 00009 00010 #include <stdio.h> 00011 #include <time.h> 00012 #include <gsl/gsl_errno.h> 00013 #include <gsl/gsl_rng.h> 00014 #include <gsl/gsl_randist.h> 00015 00016 /** \brief Private internal-use variable to store the random number 00017 * generator. 00018 */ 00019 static gsl_rng *pmc_rand_gsl_rng = NULL; 00020 00021 /** \brief Result code indicating successful completion. 00022 */ 00023 #define PMC_RAND_GSL_SUCCESS 0 00024 /** \brief Result code indicating initialization failure. 00025 */ 00026 #define PMC_RAND_GSL_INIT_FAIL 1 00027 /** \brief Result code indicating the generator was not initialized 00028 * when it should have been. 00029 */ 00030 #define PMC_RAND_GSL_NOT_INIT 2 00031 /** \brief Result code indicating the generator was already 00032 * initialized when an initialization was attempted. 00033 */ 00034 #define PMC_RAND_GSL_ALREADY_INIT 3 00035 00036 /** \brief Initialize the random number generator with the given seed. 00037 * 00038 * This must be called before any other GSL random number functions 00039 * are called. 00040 * 00041 * \param seed The random seed to use. 00042 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00043 * \sa pmc_rand_finalize_gsl() to cleanup the generator. 00044 */ 00045 int pmc_srand_gsl(int seed) 00046 { 00047 if (pmc_rand_gsl_rng) { 00048 return PMC_RAND_GSL_ALREADY_INIT; 00049 } 00050 gsl_set_error_handler_off(); // turn off automatic error handling 00051 pmc_rand_gsl_rng = gsl_rng_alloc(gsl_rng_mt19937); 00052 if (pmc_rand_gsl_rng == NULL) { 00053 return PMC_RAND_GSL_INIT_FAIL; 00054 } 00055 gsl_rng_set(pmc_rand_gsl_rng, seed); 00056 return PMC_RAND_GSL_SUCCESS; 00057 } 00058 00059 /** \brief Cleanup and deallocate the random number generator. 00060 * 00061 * This must be called after pmc_srand_gsl(). 00062 * 00063 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00064 */ 00065 int pmc_rand_finalize_gsl() 00066 { 00067 if (!pmc_rand_gsl_rng) { 00068 return PMC_RAND_GSL_NOT_INIT; 00069 } 00070 gsl_rng_free(pmc_rand_gsl_rng); 00071 pmc_rand_gsl_rng = NULL; 00072 return PMC_RAND_GSL_SUCCESS; 00073 } 00074 00075 /** \brief Generate a uniform random number in \f$[0,1)\f$. 00076 * 00077 * \param harvest A pointer to the generated random number. 00078 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00079 */ 00080 int pmc_rand_gsl(double *harvest) 00081 { 00082 if (!pmc_rand_gsl_rng) { 00083 return PMC_RAND_GSL_NOT_INIT; 00084 } 00085 *harvest = gsl_rng_uniform(pmc_rand_gsl_rng); 00086 return PMC_RAND_GSL_SUCCESS; 00087 } 00088 00089 /** \brief Generate a uniform random integer in \f$[1,n]\f$. 00090 * 00091 * \param n The upper limit of the random integer. 00092 * \param harvest A pointer to the generated random number. 00093 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00094 */ 00095 int pmc_rand_int_gsl(int n, int *harvest) 00096 { 00097 if (!pmc_rand_gsl_rng) { 00098 return PMC_RAND_GSL_NOT_INIT; 00099 } 00100 *harvest = gsl_rng_uniform_int(pmc_rand_gsl_rng, n) + 1; 00101 return PMC_RAND_GSL_SUCCESS; 00102 } 00103 00104 /** \brief Generate a normally-distributed random number. 00105 * 00106 * \param mean The mean of the distribution. 00107 * \param stddev The standard deviation of the distribution. 00108 * \param harvest A pointer to the generated random number. 00109 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00110 */ 00111 int pmc_rand_normal_gsl(double mean, double stddev, double *harvest) 00112 { 00113 if (!pmc_rand_gsl_rng) { 00114 return PMC_RAND_GSL_NOT_INIT; 00115 } 00116 *harvest = gsl_ran_gaussian(pmc_rand_gsl_rng, stddev) + mean; 00117 return PMC_RAND_GSL_SUCCESS; 00118 } 00119 00120 /** \brief Generate a Poisson-distributed random integer. 00121 * 00122 * \param mean The mean of the distribution. 00123 * \param harvest A pointer to the generated random number. 00124 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00125 */ 00126 int pmc_rand_poisson_gsl(double mean, int *harvest) 00127 { 00128 if (!pmc_rand_gsl_rng) { 00129 return PMC_RAND_GSL_NOT_INIT; 00130 } 00131 *harvest = gsl_ran_poisson(pmc_rand_gsl_rng, mean); 00132 return PMC_RAND_GSL_SUCCESS; 00133 } 00134 00135 /** \brief Generate a Binomial-distributed random integer. 00136 * 00137 * \param n The sample size for the distribution. 00138 * \param p The sample probability for the distribution. 00139 * \param harvest A pointer to the generated random number. 00140 * \return PMC_RAND_GSL_SUCCESS on success, otherwise an error code. 00141 */ 00142 int pmc_rand_binomial_gsl(int n, double p, int *harvest) 00143 { 00144 unsigned int u; 00145 00146 if (!pmc_rand_gsl_rng) { 00147 return PMC_RAND_GSL_NOT_INIT; 00148 } 00149 u = n; 00150 *harvest = gsl_ran_binomial(pmc_rand_gsl_rng, p, u); 00151 return PMC_RAND_GSL_SUCCESS; 00152 }