PartMC  2.2.1
rand_gsl.c
Go to the documentation of this file.
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 }