randistrs(3)

NAME
rds_iuniform, rds_liuniform, rds_uniform, rds_luniform, rds_exponential, rds_lexponential, rds_erlang, rds_lerlang, rds_weibull, rds_lweibull, rds_normal, rds_lnormal, rds_lognormal, rds_llognormal, rds_triangular, rds_ltriangular, rds_int_empirical, rds_double_empirical, rds_continuous_empirical, rd_iuniform, rd_liuniform, rd_uniform, rd_luniform, rd_exponential, rd_lexponential, rd_erlang, rd_lerlang, rd_weibull, rd_lweibull, rd_normal, rd_lnormal, rd_lognormal, rd_llognormal, rd_triangular, rd_ltriangular, rd_empirical_setup, rd_empirical_free, rd_int_empirical, rd_double_empirical, rd_continuous_empirical - generate pseudo-random numbers in various distributions

SYNOPSIS
#defines (see below)
#include "randistrs.h"

C interface:

int32_t rds_iuniform(mt_state* state, int32_t lower, int32_t upper);

int64_t rds_liuniform(mt_state* state,
                  int64_t lower, int64_t upper);

double rds_uniform(mt_state* state, double lower, double upper);

double rds_luniform(mt_state* state, double lower, double upper);

double rds_exponential(mt_state* state, double mean);

double rds_lexponential(mt_state* state, double mean);

double rds_erlang(mt_state* state, int p, double mean);

double rds_lerlang(mt_state* state, int p, double mean);

double rds_weibull(mt_state* state, double shape, double scale);

double rds_lweibull(mt_state* state, double shape, double scale);

double rds_normal(mt_state* state, double mean, double sigma);

double rds_lnormal(mt_state* state, double mean, double sigma);

double rds_lognormal(mt_state* state, double shape, double scale);

double rds_llognormal(mt_state* state, double shape, double scale);

double rds_triangular(mt_state* state, double lower,
                      double upper, double mode);

double rds_ltriangular(mt_state* state, double lower,
                      double upper, double mode);

size_t rds_int_empirical(mt_state* state,
                     rd_empirical_control* control);

double rds_double_empirical(mt_state* state,
                     rd_empirical_control* control);

double rds_continuous_empirical(mt_state* state,
                     rd_empirical_control* control);

int32_t rd_iuniform(int32_t lower, int32_t upper);

int64_t rd_liuniform(int64_t lower, int64_t upper);

double rd_uniform(double lower, double upper);

double rd_luniform(double lower, double upper);

double rd_exponential(double mean);

double rd_lexponential(double mean);

double rd_erlang(int p, double mean);

double rd_lerlang(int p, double mean);

double rd_weibull(double shape, double scale);

double rd_lweibull(double shape, double scale);

double rd_normal(double mean, double sigma);

double rd_lnormal(double mean, double sigma);

double rd_lognormal(double shape, double scale);

double rd_llognormal(double shape, double scale);

double rd_triangular(double lower, double upper, double mode);

double rd_ltriangular(double lower, double upper, double mode);

void rd_empirical_setup(size_t n_probs, const double* probs,
                     const double* values);

void rd_empirical_free(rd_empirical_control* control);

size_t rd_int_empirical(rd_empirical_control* control);

double rd_double_empirical(rd_empirical_control* control);

double rd_continuous_empirical(rd_empirical_control* control);

C++ interface:

mt_distribution rng;

int32_t rng.iuniform(int32_t lower, int32_t upper);

int64_t rng.liuniform(int64_t lower, int64_t upper);

double rng.uniform(double lower, double upper);

double rng.luniform(double lower, double upper);

double rng.exponential(double mean);

double rng.lexponential(double mean);

double rng.erlang(int p, double mean);

double rng.lerlang(int p, double mean);

double rng.weibull(double shape, double scale);

double rng.lweibull(double shape, double scale);

double rng.normal(double mean, double sigma);

double rng.lnormal(double mean, double sigma);

double rng.lognormal(double shape, double scale);

double rng.llognormal(double shape, double scale);

double rng.triangular(double lower, double upper, double mode);

double rng.ltriangular(double lower, double upper, double mode);

mt_empirical_distribution emp (const vector<double> probs);

mt_empirical_distribution emp (const vector<double> probs,
                     const vector<double> values);

size_t emp.int_empirical(mt_prng& rng);

double emp.double_empirical(mt_prng& rng);

double emp.continuous_empirical(mt_prng& rng);

DESCRIPTION
These functions generate pseudo-random numbers in various distributions using the Mersenne Twist algorithm described in mtwist(3).

The C interface provides four flavors of each function: rds_xxx, rds_lxxx, rd_xxx, and rd_lxxx. The "rds" versions accept an explicit Mersenne Twist state vector, as described in mtwist(3). The "rd" versions use the default global state vector; in general these functions should be avoided except for unimportant applications. The versions with no "l" after the underscore use the 32-bit version of the PRNG, while the "l" versions generate more bits (53 for floating-point values, 64 for integers) to increase the accuracy of the generated distribution at the expense of speed.

In the C++ interface, the mt_distribution class is derived from mt_prng (see mtwist(3)), and provides all the functionality of that class as well as the extended functions for generating specific distributions.

With the exception of the *iuniform functions, all functions return a double-precision result. The range of the result depends on the distribution and the parameters. However, in all cases the precision of the result of non-"l" functions is limited to 32 bits, or about 1 part in 4 billion.

The *iuniform functions generate integers selected from a uniform distribution in the range [lower, upper). If the total range given to the non-"l" functions is less than 429497 (2^32 / 10^4), a fast but slightly inaccurate method is used; the bias in this case will never exceed If the range exceeds that value, a slightly slower but precise method is used.

The *liuniform functions also generate uniformly distributed integers, but they will support a range greater than 4294967295. The *liuniform functions should never be used unless a large range is required.

The *uniform functions generate double-precision numbers selected from a uniform distribution in the range [lower, upper). This function should not be used to generate uniformly distributed random integers. Use the *iuniform family instead.

The *exponential functions generate an exponential distribution with the given mean. The *erlang functions generate a p-Erlang distribution with the given mean. The *weibull functions generate a Weibull function with the given shape and scale parameters.

The *normal functions generate a normal (Gaussian) distribution with the given mean and a standard deviation equal to sigma. The *lognormal functions generate a lognormal distribution with the given shape and scale parameters.

The *triangular functions generate a triangular distribution in the range [lower, upper) and with the given mode.

The *empirical functions generate empirically determined distributions. The caller must supply a control structure that has been created by rd_empirical_setup, which accepts an array probs that contains n_probs weights specifying the relative frequencies of the various output values. (The weights do not need to sum to 1.0; they are normalized if they do not.) The values array, if not NULL, must contain n_probs+ 1 values; see below. The control structure can be freed by rd_empirical_free when it is no longer needed.

The rd_int_empirical function generates empirically distributed integers in the range [0, n_probs). This function ignores the values given to rd_empirical_setup.

The rd_double_empirical function uses the results of rd_int_empirical as an index into the values array; in this case values[n_probs+1] entry is ignored (but must nevertheless be provided). If no values were provided to rd_empirical_setup, the output values will be evenly spaced on [0, 1).

The rd_continuous_empirical function generates continuous empirically determined distributions. It is similar to rd_double_empirical except that it chooses a result that is uniformly values[i] and values[i+1] for some randomly chosen i in [0, n_probs]. The net effect is a piecewise linear approximation to the underlying CDF of the empirically observed distribution.

C++ INTERFACE

The C++ interface to the functions is based on a class derived from mt_prng; as such, the PRNG state is implied by the derived class. Otherwise, the C++ functions behave exactly like the similary named C functions.

The sole exception is empirical distributions; here, an auxiliary class is used to support the internal state needed to track the distribution. Since the generating functions require an mt_prng as an argument, an mt_distribution can also be used for this purpose.

NOTES

It would be helpful if the package supported even more distributions. Please e-mail the author (geoff@cs.hmc.edu) with suggestions for other distributions and (if possible) algorithms for generating them.

The *iuniform functions keep internal state in an attempt to speed up their performance when the range is large. This internal state makes them non-reentrant.

When the range is small, *iuniform functions exhibit a very slight bias in favor of some values. This bias isn't significant for any application less demanding than gambling. To eliminate the bias, compile randistrs.c with RD_MAX_BIAS set to zero.

The state-saving optimization in the *iuniform functions doesn't help when they are called with varying ranges, even if a different state vector is used for each range.

The naming of the C++ empirical-distribution is redundant, since "empirical" is implied by the class name. However, dropping that string would create conflicts with C++ type names, so the suffix was kept for consistency.

SEE ALSO
mtwist(3)

Any good statistics or simulation textbook for descriptions of the distributions.