UNU.RAN – Universal Non-Uniform RANdom number generators
1 Introduction
1.1 Usage of this document
1.2 Installation
1.3 Using the library
1.4 Concepts of UNU.RAN
1.5 Contact the authors
2 Examples
2.1 As short as possible
2.2 As short as possible (String API)
2.3 Select a method
2.4 Select a method (String API)
2.5 Arbitrary distributions
2.6 Arbitrary distributions (String API)
2.7 Change parameters of the method
2.8 Change parameters of the method (String API)
2.9 Change uniform random generator
2.10 Change parameters of underlying distribution
2.11 Sample pairs of antithetic random variates
2.12 Sample pairs of antithetic random variates (String API)
2.13 More examples
3 String Interface
3.1 Syntax of String Interface
3.2 Distribution String
3.2.1 Keys for Distribution String
3.3 Function String
3.4 Method String
3.4.1 Keys for Method String
3.5 Uniform RNG String
4 Handling distribution objects
4.1 Functions for all kinds of distribution objects
4.2 Continuous univariate distributions
4.3 Continuous univariate order statistics
4.4 Continuous empirical univariate distributions
4.5 Continuous multivariate distributions
4.6 Continuous univariate full conditional distribution
4.7 Continuous empirical multivariate distributions
4.8 MATRix distributions
4.9 Discrete univariate distributions
5 Methods for generating non-uniform random variates
5.1 Routines for all generator objects
5.2 AUTO – Select method automatically
5.3 Methods for continuous univariate distributions
5.3.1 AROU – Automatic Ratio-Of-Uniforms method
5.3.2 ARS – Adaptive Rejection Sampling
5.3.3 CEXT – wrapper for Continuous EXTernal generators
5.3.4 CSTD – Continuous STandarD distributions
5.3.5 HINV – Hermite interpolation based INVersion of CDF
5.3.6 HRB – Hazard Rate Bounded
5.3.7 HRD – Hazard Rate Decreasing
5.3.8 HRI – Hazard Rate Increasing
5.3.9 ITDR – Inverse Transformed Density Rejection
5.3.10 NINV – Numerical INVersion
5.3.11 NROU – Naive Ratio-Of-Uniforms method
5.3.12 PINV – Polynomial interpolation based INVersion of CDF
5.3.13 SROU – Simple Ratio-Of-Uniforms method
5.3.14 SSR – Simple Setup Rejection
5.3.15 TABL – a TABLe method with piecewise constant hats
5.3.16 TDR – Transformed Density Rejection
5.3.17 UTDR – Universal Transformed Density Rejection
5.4 Methods for continuous empirical univariate distributions
5.4.1 EMPK – EMPirical distribution with Kernel smoothing
5.4.2 EMPL – EMPirical distribution with Linear interpolation
5.4.3 HIST – HISTogramm of empirical distribution
5.5 Methods for continuous multivariate distributions
5.5.1 MVSTD – MultiVariate continuous STandarD distributions
5.5.2 MVTDR – Multi-Variate Transformed Density Rejection
5.5.3 NORTA – NORmal To Anything
5.5.4 VNROU – Multivariate Naive Ratio-Of-Uniforms method
5.6 Markov chain samplers for continuous multivariate distributions
5.6.1 GIBBS – Markov Chain - GIBBS sampler
5.6.2 HITRO – Markov Chain - HIT-and-run sampler with Ratio-Of-uniforms
5.7 Methods for continuous empirical multivariate distributions
5.7.1 VEMPK – (Vector) EMPirical distribution with Kernel smoothing
5.8 Methods for discrete univariate distributions
5.8.1 DARI – Discrete Automatic Rejection Inversion
5.8.2 DAU – (Discrete) Alias-Urn method
5.8.3 DEXT – wrapper for Discrete EXTernal generators
5.8.4 DGT – (Discrete) Guide Table method (indexed search)
5.8.5 DSROU – Discrete Simple Ratio-Of-Uniforms method
5.8.6 DSS – (Discrete) Sequential Search method
5.8.7 DSTD – Discrete STandarD distributions
5.9 Methods for random matrices
5.9.1 MCORR – Random CORRelation matrix
5.10 Methods for uniform univariate distributions
5.10.1 UNIF – wrapper for UNIForm random number generator
5.11 Meta Methods for univariate distributions
5.11.1 MIXT – MIXTure of distributions
6 Using uniform random number generators
6.1 Simple interface for uniform random number generators
6.2 Interface to GSL uniform random number generators
6.3 Interface to GSL generators for quasi-random points
6.4 Interface to Otmar Lendl’s pseudo-random number generators
6.5 Interface to L’Ecuyer’s RNGSTREAM random number generators
6.6 Combine point set generator with random shifts
7 UNU.RAN Library of standard distributions
7.1 UNU.RAN Library of continuous univariate distributions
7.1.1 ‘F’ – F-distribution
7.1.2 ‘beta’ – Beta distribution
7.1.3 ‘cauchy’ – Cauchy distribution
7.1.4 ‘chi’ – Chi distribution
7.1.5 ‘chisquare’ – Chisquare distribution
7.1.6 ‘exponential’ – Exponential distribution
7.1.7 ‘extremeI’ – Extreme value type I (Gumbel-type) distribution
7.1.8 ‘extremeII’ – Extreme value type II (Frechet-type) distribution
7.1.9 ‘gamma’ – Gamma distribution
7.1.10 ‘gig’ – Generalized Inverse Gaussian distribution
7.1.11 ‘gig2’ – Generalized Inverse Gaussian distribution
7.1.12 ‘hyperbolic’ – Hyperbolic distribution
7.1.13 ‘ig’ – Inverse Gaussian distribution
7.1.14 ‘laplace’ – Laplace distribution
7.1.15 ‘logistic’ – Logistic distribution
7.1.16 ‘lognormal’ – Log-Normal distribution
7.1.17 ‘lomax’ – Lomax distribution (Pareto distribution of second kind)
7.1.18 ‘normal’ – Normal distribution
7.1.19 ‘pareto’ – Pareto distribution (of first kind)
7.1.20 ‘powerexponential’ – Powerexponential (Subbotin) distribution
7.1.21 ‘rayleigh’ – Rayleigh distribution
7.1.22 ‘slash’ – Slash distribution
7.1.23 ‘student’ – Student’s t distribution
7.1.24 ‘triangular’ – Triangular distribution
7.1.25 ‘uniform’ – Uniform distribution
7.1.26 ‘weibull’ – Weibull distribution
7.2 UNU.RAN Library of continuous multivariate distributions
7.2.1 ‘copula’ – Copula (distribution with uniform marginals)
7.2.2 ‘multicauchy’ – Multicauchy distribution
7.2.3 ‘multiexponential’ – Multiexponential distribution
7.2.4 ‘multinormal’ – Multinormal distribution
7.2.5 ‘multistudent’ – Multistudent distribution
7.3 UNU.RAN Library of discrete univariate distributions
7.3.1 ‘binomial’ – Binomial distribution
7.3.2 ‘geometric’ – Geometric distribution
7.3.3 ‘hypergeometric’ – Hypergeometric distribution
7.3.4 ‘logarithmic’ – Logarithmic distribution
7.3.5 ‘negativebinomial’ – Negative Binomial distribution
7.3.6 ‘poisson’ – Poisson distribution
7.4 UNU.RAN Library of random matrices
7.4.1 ‘correlation’ – Random correlation matrix
8 Error handling and Debugging
8.1 Output streams
8.2 Debugging
8.3 Error reporting
8.4 Error codes
8.5 Error handlers
9 Testing
10 Miscelleanous
10.1 Mathematics
Appendix A A Short Introduction to Random Variate Generation
A.1 The Inversion Method
A.2 The Rejection Method
A.3 The Composition Method
A.4 The Ratio-of-Uniforms Method
A.5 Inversion for Discrete Distributions
A.6 Indexed Search (Guide Table Method)
Appendix B Glossary
Appendix C Bibliography
Appendix D Function Index
UNU.RAN – Universal Non-Uniform RANdom number generators
********************************************************
This is the online-documentation of UNU.RAN.
Version: 1.11.0
Date: 21 April 2023
UNU.RAN (Universal Non-Uniform RAndom Number generator) is a collection of
algorithms for generating non-uniform pseudorandom variates as a library of C
functions designed and implemented by the ARVAG (Automatic Random VAriate
Generation) project group in Vienna, and released under the GNU Public License
(GPL). It is especially designed for such situations where
− a non-standard distribution or a truncated distribution is needed.
− experiments with different types of distributions are made.
− random variates for variance reduction techniques are used.
− fast generators of predictable quality are necessary.
Of course it is also well suited for standard distributions. However due to
its more sophisticated programming interface it might not be as easy to use if
you only look for a generator for the standard normal distribution. (Although
UNU.RAN provides generators that are superior in many aspects to those found in
quite a number of other libraries.)
UNU.RAN implements several methods for generating random numbers. The choice
depends primary on the information about the distribution can be provided and –
if the user is familar with the different methods – on the preferences of the
user.
The design goals of UNU.RAN are to provide _reliable_, _portable_ and
_robust_ (as far as this is possible) functions with a consisent and easy to use
interface. It is suitable for all situation where experiments with different
distributions including non-standard distributions. For example it is no
problem to replace the normal distribution by an empirical distribution in a
model.
Since originally designed as a library for so called black-box or universal
algorithms its interface is different from other libraries. (Nevertheless it
also contains special generators for standard distributions.) It does not
provide subroutines for random variate generation for particular distributions.
Instead it uses an object-oriented interface. Distributions and generators are
treated as independent objects. This approach allows one not only to have
different methods for generating non-uniform random variates. It is also
possible to choose the method which is optimal for a given situation (e.g.
speed, quality of random numbers, using for variance reduction techniques,
etc.). It also allows to sample from non-standard distribution or even from
distributions that arise in a model and can only be computed in a complicated
subroutine.
Sampling from a particular distribution requires the following steps:
1. Create a distribution object. (Objects for standard distributions are
available in the library)
2. Choose a method.
3. Initialize the generator, i.e., create the generator object. If the
choosen method is not suitable for the given distribution (or if the
distribution object contains too little information about the distribution)
the initialization routine fails and produces an error message. Thus the
generator object does (probably) not produce false results (random variates
of a different distribution).
4. Use this generator object to sample from the distribution.
There are four types of objects that can be manipulated independently:
• *Distribution objects:* hold all information about the random variates that
should be generated. The following types of distributions are available:
− Continuous and Discrete distributions
− Empirical distributions
− Multivariate distributions
Of course a library of standard distributions is included (and these can be
further modified to get, e.g., truncated distributions). Moreover the
library provides subroutines to build almost arbitrary distributions.
• *Generator objects:* hold the generators for the given distributions. It
is possible to build independent generator objects for the same
distribution object which might use the same or different methods for
generation. (If the choosen method is not suitable for the given method, a
‘NULL’ pointer is returned in the initialization step).
• *Parameter objects:* Each transformation method requires several parameters
to adjust the generator to a given distribution. The parameter object
holds all this information. When created it contains all necessary default
settings. It is only used to create a generator object and destroyed
immediately. Altough there is no need to change these parameters or even
know about their existence for “usual distributions”, they allow a fine
tuning of the generator to work with distributions with some awkward
properties. The library provides all necessary functions to change these
default parameters.
• *Uniform Random Number Generators:* All generator objects need one (or
more) streams of uniform random numbers that are transformed into random
variates of the given distribution. These are given as pointers to
appropriate functions or structures (objects). Two generator objects may
have their own uniform random number generators or share a common one. Any
functions that produce uniform (pseudo-) random numbers can be used. We
suggest Otmar Lendl’s PRNG library.
1 Introduction
**************
1.1 Usage of this document
==========================
We designed this document in a way such that one can use UNU.RAN with reading as
little as necessary. Read *note Installation:: for the instructions to install
the library. *note Concepts of UNU.RAN: Concepts, discribes the basics of
UNU.RAN. It also has a short guideline for choosing an appropriate method. In
*note Examples:: examples are given that can be copied and modified. They also
can be found in the directory ‘examples’ in the source tree.
Further information are given in consecutive chapters. *note Handling
distribution objects: Distribution_objects, describes how to create and
manipulate distribution objects. *note standard distributions: Stddist,
describes predefined distribution objects that are ready to use. *note
Methods:: describes the various methods in detail. For each of possible
distribution classes (continuous, discrete, empirical, multivariate) there
exists a short overview section that can be used to choose an appropriate method
followed by sections that describe each of the particular methods in detail.
These are merely for users with some knowledge about the methods who want to
change method-specific parameters and can be ignored by others.
Abbreviations and explanation of some basic terms can be found in *note
Glossary::.
1.2 Installation
================
UNU.RAN was developed on an Intel architecture under Linux with the GNU C
compiler but should compile and run on any computing environment. It requires
an ANSI compliant C compiler.
Below find the installation instructions for unices.
Uniform random number generator
...............................
UNU.RAN can be used with any uniform random number generator but (at the moment)
some features work best with Pierre L’Ecuyer’s RngStreams library (see
for a description and
downloading. For details on using uniform random number in UNU.RAN see *note
Using uniform random number generators: URNG.
Install the required libraries first.
UNU.RAN
.......
1. First unzip and untar the package and change to the directory:
tar zxvf unuran-1.11.0.tar.gz
cd unuran-1.11.0
2. Optional: Edit the file ‘src/unuran_config.h’
3. Run a configuration script:
sh ./configure --prefix=
where ‘’ is the root of the installation tree. When omitted
‘/usr/local’ is used.
Use ‘./configure --help’ to get a list of other options. In particular the
following flags are important:
• Enable support for some external sources of uniform random number
generators (*note Using uniform random number generators: URNG.):
‘--with-urng-rngstream’
URNG: use Pierre L’Ecuyer’s RNGSTREAM library [default=‘no’]
‘--with-urng-prng’
URNG: use Otmar Lendl’s PRNG library [default=‘no’]
‘--with-urng-gsl’
URNG: use random number generators from GNU Scientific Library
[default=‘no’]
‘--with-urng-default’
URNG: global default URNG (builtin|rngstream) [default=‘builtin’]
We strongly recommend to use RngStreams library:
sh ./configure --with-urng-rngstream --with-urng-default=rngstream
_Important:_ You must install the respective libraries ‘RngStreams’,
‘PRNG’ and ‘GSL’ before ‘./configure’ is executed.
• Also make a shared library:
‘--enable-shared’
build shared libraries [default=‘no’]
• The library provides the function ‘unur_gen_info’ for information
about generator objects. This is intented for using in interactive
computing environments. This feature can be enabled / disabled by
means of the configure flag
‘--enable-info’
INFO: provide function with information about generator objects
[default=‘yes’]
• Enable support for deprecated UNU.RAN routines if you have some
problems with older application after upgrading the library:
‘--enable-deprecated’
enable support for deprecated UNU.RAN routines [default=‘no’]
• Enable debugging tools:
‘--enable-check-struct’
Debug: check validity of pointers to structures [default=‘no’]
‘--enable-logging’
Debug: print informations about generator into logfile
[default=no]
4. Compile and install the libray:
make
make install
Obviously ‘$(prefix)/include’ and ‘$(prefix)/lib’ must be in the search
path of your compiler. You can use environment variables to add these
directories to the search path. If you are using the bash type (or add to
your profile):
export LIBRARY_PATH="/lib"
export C_INCLURE_PATH="/include"
If you want to make a shared library, then making such a library can be
enabled using
sh ./configure --enable-shared
If you want to link against the shared library make sure that it can be
found when executing the binary that links to the library. If it is not
installed in the usual path, then the easiest way is to set the
‘LD_LIBRARY_PATH’ environment variable. See any operating system
documentation about shared libraries for more information, such as the
ld(1) and ld.so(8) manual pages.
5. Documentation in various formats (PDF, HTML, info, plain text) can be found
in directory ‘doc’.
6. You can run some tests by
make check
However, some of these tests requires the usage of the PRNG or RngStreams
library and are only executed if these are installed enabled by the
corresponding configure flag.
An extended set of tests is run by
make fullcheck
However some of these might fail occasionally due to roundoff errors or the
mysteries of floating point arithmetic, since we have used some extreme
settings to test the library.
Upgrading
.........
− _Important:_
UNU.RAN now relies on some aspects of IEEE 754 compliant floating point
arithmetic. In particular, ‘1./0.’ and ‘0./0.’ must result in ‘infinity’
and ‘NaN’ (not a number), respectively, and must not cause a floating point
exception. For allmost all modern compting architecture this is
implemented in hardware. For others there should be a special compiler
flag to get this feature (e.g., ‘-MIEEE’ on DEC alpha or ‘-mp’ for the
Intel C complier).
− Upgrading UNU.RAN from version 0.9.x or earlier:
With UNU.RAN version 1.0.x some of the macro definitions in file
‘src/unuran_config.h’ are moved into file ‘config.h’ and are set/controlled
by the ‘./configure’ script.
Writting logging information into the logfile must now be enabled when
running the configure script:
sh ./configure --enable-logging
− Upgrading UNU.RAN from version 0.7.x or earlier:
With UNU.RAN version 0.8.0 the interface for changing underlying
distributions and running a reinitialization routine has been simplified.
The old routines can be compiled into the library using the following
configure flag:
sh ./configure --enable-deprecated
Notice: Using these deprecated routines is not supported any more and this
strong discouraged.
Wrapper functions for external sources of uniform random numbers are now
enabled by configure flags and not by macros defined in file
‘src/unuran_config.h’.
The file ‘src/unuran_config.h’ is not installed any more. It is now only
included when the library is compiled. It should be removed from the
global include path of the compiler.
1.3 Using the library
=====================
ANSI C Compliance
.................
The library is written in ANSI C and is intended to conform to the ANSI C
standard. It should be portable to any system with a working ANSI C compiler.
The library does not rely on any non-ANSI extensions in the interface it
exports to the user. Programs you write using UNU.RAN can be ANSI compliant.
Extensions which can be used in a way compatible with pure ANSI C are supported,
however, via conditional compilation. This allows the library to take advantage
of compiler extensions on those platforms which support them.
To avoid namespace conflicts all exported function names and variables have
the prefix ‘unur_’, while exported macros have the prefix ‘UNUR_’.
Compiling and Linking
.....................
If you want to use the library you must include the UNU.RAN header file
#include
If you also need the test routines then also add
#include
If wrapper functions for external sources of uniform random number generators
are used, the corresponding header files must also be included, e.g.,
#include
If these header files are not installed on the standard search path of your
compiler you will also need to provide its location to the preprocessor as a
command line flag. The default location of the ‘unuran.h’ is
‘/usr/local/include’. A typical compilation command for a source file ‘app.c’
with the GNU C compiler ‘gcc’ is,
gcc -I/usr/local/include -c app.c
This results in an object file ‘app.o’. The default include path for ‘gcc’
searches ‘/usr/local/include’ automatically so the ‘-I’ option can be omitted
when UNU.RAN is installed in its default location.
The library is installed as a single file, ‘libunuran.a’. A shared version
of the library is also installed on systems that support shared libraries. The
default location of these files is ‘/usr/local/lib’. To link against the
library you need to specify the main library. The following example shows how
to link an application with the library (and the the RNGSTREAMS library if you
decide to use this source of uniform pseudo-random numbers),
gcc app.o -lunuran -lrngstreams -lm
Shared Libraries
................
To run a program linked with the shared version of the library it may be
necessary to define the shell variable ‘LD_LIBRARY_PATH’ to include the
directory where the library is installed. For example,
LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
To compile a statically linked version of the program instead, use the ‘-static’
flag in ‘gcc’,
gcc -static app.o -lunuran -lrngstreams -lm
Compatibility with C++
......................
The library header files automatically define functions to have ‘extern "C"’
linkage when included in C++ programs.
1.4 Concepts of UNU.RAN
=======================
UNU.RAN is a C library for generating non-uniformly distributed random variates.
Its emphasis is on the generation of non-standard distribution and on streams of
random variates of special purposes. It is designed to provide a consistent
tool to sample from distributions with various properties. Since there is no
universal method that fits for all situations, various methods for sampling are
implemented.
UNU.RAN solves this complex task by means of an object oriented programming
interface. Three basic objects are used:
• distribution object ‘UNUR_DISTR’
Hold all information about the random variates that should be generated.
• generator object ‘UNUR_GEN’
Hold the generators for the given distributions. Two generator objects are
completely independent of each other. They may share a common uniform
random number generator or have their owns.
• parameter object ‘UNUR_PAR’
Hold all information for creating a generator object. It is necessary due
to various parameters and switches for each of these generation methods.
Notice that the parameter objects only hold pointers to arrays but do not
have their own copy of such an array. Especially, if a dynamically
allocated array is used it _must not_ be freed until the generator object
has been created!
The idea behind these structures is that creatin distributions, choosing a
generation method and draing samples are orthogonal (ie. independent) functions
of the library. The parameter object is only introduced due to the necessity to
deal with various parameters and switches for each of these generation methods
which are required to adjust the algorithms to unusual distributions with
extreme properties but have default values that are suitable for most
applications. These parameters and the data for distributions are set by
various functions.
Once a generator object has been created sampling (from the univariate
continuous distribution) can be done by the following command:
double x = unur_sample_cont(generator);
Analogous commands exist for discrete and multivariate distributions. For
detailed examples that can be copied and modified see *note Examples::.
Distribution objects
--------------------
All information about a distribution are stored in objects (structures) of type
‘UNUR_DISTR’. UNU.RAN has five different types of distribution objects:
‘cont’
Continuous univariate distributions.
‘cvec’
Continuous multivariate distributions.
‘discr’
Discrete univariate distributions.
‘cemp’
Continuous empirical univariate distribution, ie. given by a sample.
‘cvemp’
Continuous empirical multivariate distribution, ie. given by a sample.
‘matr’
Matrix distributions.
Distribution objects can be created from scratch by the following call
distr = unur_distr__new();
where ‘’ is one of the five possible types from the above table. Notice
that these commands only create an _empty_ object which still must be filled by
means of calls for each type of distribution object (*note Handling distribution
objects: Distribution_objects.). The naming scheme of these functions is
designed to indicate the corresponding type of the distribution object and the
task to be performed. It is demonstated on the following example.
unur_distr_cont_set_pdf(distr, mypdf);
This command stores a PDF named ‘mypdf’ in the distribution object ‘distr’ which
must have the type ‘cont’.
Of course UNU.RAN provides an easier way to use standard distributions.
Instead of using ‘unur_distr__new’ calls and fuctions
‘unur_distr__set_<...>’ for setting data, objects for standard
distribution can be created by a single call. Eg. to get an object for the
normal distribution with mean 2 and standard deviation 5 use
double parameter[2] = {2.0 ,5.0};
UNUR_DISTR *distr = unur_distr_normal(parameter, 2);
For a list of standard distributions see *note Standard distributions: Stddist.
Generation methods
------------------
The information that a distribution object must contain depends heavily on the
chosen generation method choosen.
Brackets indicate optional information while a tilde indicates that only an
approximation must be provided. See *note Glossary::, for unfamiliar terms.
Methods for continuous univariate distributions
sample with ‘unur_sample_cont’
method PDF dPDF CDF mode area other
AROU x x [x] T-concave
ARS x x T-concave
CEXT wrapper for external generator
CSTD build-in standard distribution
HINV [x] [x] x
HRB bounded hazard rate
HRD decreasing hazard rate
HRI increasing hazard rate
ITDR x x x monotone with pole
NINV [x] x
NROU x [x]
PINV x [x] [~]
SROU x x x T-concave
SSR x x x T-concave
TABL x x [~] all local extrema
TDR x x T-concave
UTDR x x ~ T-concave
Methods for continuous empirical univariate distributions
sample with ‘unur_sample_cont’
EMPK: Requires an observed sample.
EMPL: Requires an observed sample.
Methods for continuous multivariate distributions
sample with ‘unur_sample_vec’
NORTA: Requires rank correlation matrix and marginal distributions.
VNROU: Requires the PDF.
MVSTD: Generator for built-in standard distributions.
MVTDR: Requires PDF and gradiant of PDF.
Methods for continuous empirical multivariate distributions
sample with ‘unur_sample_vec’
VEMPK: Requires an observed sample.
Methods for discrete univariate distributions
sample with ‘unur_sample_discr’
method PMF PV mode sum other
DARI x x ~ T-concave
DAU [x] x
DEXT wrapper for external generator
DGT [x] x
DSROU x x x T-concave
DSS [x] x x
DSTD build-in standard distribution
Methods for matrix distributions
sample with ‘unur_sample_matr’
MCORR: Distribution object for random correlation matrix.
Markov Chain Methods for continuous multivariate distributions
sample with ‘unur_sample_vec’
GIBBS: T-concave logPDF and derivatives of logPDF.
HITRO: Requires PDF.
Because of tremendous variety of possible problems, UNU.RAN provides many
methods. All information for creating a generator object has to be collected in
a parameter object first. For example, if the task is to sample from a
continuous distribution the method AROU might be a good choice. Then the call
UNUR_PAR *par = unur_arou_new(distribution);
creates an parameter object ‘par’ with a pointer to the distribution object and
default values for all necessary parameters for method AROU. Other methods can
be used by replacing ‘arou’ with the name of the desired methods (in lower case
letters):
UNUR_PAR *par = unur__new(distribution);
This sets the default values for all necessary parameters for the chosen method.
These are suitable for almost all applications. Nevertheless, it is possible to
control the behavior of the method using corresponding ‘set’ calls for each
method. This might be necessary to adjust the algorithm for an unusual
distribution with extreme properties, or just for fine tuning the perforence of
the algorithm. The following example demonstrates how to change the maximum
number of iterations for method NINV to the value 50:
unur_ninv_set_max_iteration(par, 50);
All available methods are described in details in *note Methods::.
Creating a generator object
---------------------------
Now it is possible to create a generator object:
UNUR_GEN *generator = unur_init(par);
if (generator == NULL) exit(EXIT_FAILURE);
*Important:* You must always check whether ‘unur_init’ has been executed
successfully. Otherwise the ‘NULL’ pointer is returned which causes a
segmentation fault when used for sampling.
*Important:* The call of ‘unur_init’ *destroys* the parameter object!
Moreover, it is recommended to call ‘unur_init’ immediately after the parameter
object ‘par’ has created and modified.
An existing generator object is a rather static construct. Nevertheless,
some of the parameters can still be modified by ‘chg’ calls, e.g.
unur_ninv_chg_max_iteration(gen, 30);
Notice that it is important _when_ parameters are changed because different
functions must be used:
The function name includes the term ‘set’ and the first argument must be of
type ‘UNUR_PAR’ when the parameters are changed _before_ the generator object is
created.
The function name includes the term ‘chg’ and the first argument must be of
type ‘UNUR_GEN’ when the parameters are changed for an _existing_ generator
object.
For details see *note Methods::.
Sampling
--------
You can now use your generator object in any place of your program to sample
from your distribution. You only have to take care about the type of variates
it computes: ‘double’, ‘int’ or a vector (array of ‘double’s). Notice that at
this point it does not matter whether you are sampling from a gamma
distribution, a truncated normal distribution or even an empirical distribution.
Reinitializing
--------------
It is possible for a generator object to change the parameters and the domain of
the underlying distribution. This must be done by extracting this object by
means of a ‘unur_get_distr’ call and changing the distribution using the
correspondig set calls, see *note Handling distribution objects:
Distribution_objects. The generator object *must* then be reinitialized by
means of the ‘unur_reinit’ call.
_Important_: Currently not all methods allow reinitialization, see the
description of the particular method (keyword Reinit).
Destroy
-------
When you do not need your generator object any more, you should destroy it:
unur_free(generator);
Uniform random numbers
----------------------
Each generator object can have its own uniform random number generator or share
one with others. When created a parameter object the pointer for the uniform
random number generator is set to the default generator. However, it can be
changed at any time to any other generator:
unur_set_urng(par, urng);
or
unur_chg_urng(generator, urng);
respectively. See *note Using uniform random number generators: URNG, for
details.
1.5 Contact the authors
=======================
If you have any problems with UNU.RAN, suggestions how to improve the library,
or find a bug, please contact us via email .
For news please visit out homepage at .
2 Examples
**********
The examples in this chapter should compile cleanly and can be found in the
directory ‘examples’ of the source tree of UNU.RAN. Assuming that UNU.RAN as
well as the PRNG libraries have been installed properly (*note Installation::)
each of these can be compiled (using the GCC in this example) with
gcc -Wall -O2 -o example example.c -lunuran -lprng -lm
_Remark:_ ‘-lprng’ must be omitted when the PRNG library is not installed. Then
however some of the examples might not work.
The library uses three objects: ‘UNUR_DISTR’, ‘UNUR_PAR’ and ‘UNUR_GEN’. It
is not important to understand the details of these objects but it is important
not to changed the order of their creation. The distribution object can be
destroyed _after_ the generator object has been made. (The parameter object is
freed automatically by the ‘unur_init’ call.) It is also important to check the
result of the ‘unur_init’ call. If it has failed the ‘NULL’ pointer is returned
and causes a segmentation fault when used for sampling.
We give all examples with the UNU.RAN standard API and the more convenient
string API.
2.1 As short as possible
========================
Select a distribution and let UNU.RAN do all necessary steps.
/* ------------------------------------------------------------- */
/* File: example0.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Use a predefined standard distribution: */
/* Gaussian with mean zero and standard deviation 1. */
/* Since this is the standard form of the distribution, */
/* we need not give these parameters. */
distr = unur_distr_normal(NULL, 0);
/* Use method AUTO: */
/* Let UNURAN select a suitable method for you. */
par = unur_auto_new(distr);
/* Now you can change some of the default settings for the */
/* parameters of the chosen method. We don't do it here. */
/* Create the generator object. */
gen = unur_init(par);
/* Notice that this call has also destroyed the parameter */
/* object `par' as a side effect. */
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the standard Gaussian distribution. */
/* Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.2 As short as possible (String API)
=====================================
Select a distribution and let UNU.RAN do all necessary steps.
/* ------------------------------------------------------------- */
/* File: example0_str.c */
/* ------------------------------------------------------------- */
/* String API. */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare UNURAN generator object. */
UNUR_GEN *gen; /* generator object */
/* Create the generator object. */
/* Use a predefined standard distribution: */
/* Standard Gaussian distribution. */
/* Use method AUTO: */
/* Let UNURAN select a suitable method for you. */
gen = unur_str2gen("normal()");
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Now you can use the generator object `gen' to sample from */
/* the standard Gaussian distribution. */
/* Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.3 Select a method
===================
Select method AROU and use it with default parameters.
/* ------------------------------------------------------------- */
/* File: example1.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Use a predefined standard distribution: */
/* Gaussian with mean zero and standard deviation 1. */
/* Since this is the standard form of the distribution, */
/* we need not give these parameters. */
distr = unur_distr_normal(NULL, 0);
/* Choose a method: AROU. */
/* For other (suitable) methods replace "arou" with the */
/* respective name (in lower case letters). */
par = unur_arou_new(distr);
/* Now you can change some of the default settings for the */
/* parameters of the chosen method. We don't do it here. */
/* Create the generator object. */
gen = unur_init(par);
/* Notice that this call has also destroyed the parameter */
/* object `par' as a side effect. */
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the standard Gaussian distribution. */
/* Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.4 Select a method (String API)
================================
Select method AROU and use it with default parameters.
/* ------------------------------------------------------------- */
/* File: example1_str.c */
/* ------------------------------------------------------------- */
/* String API. */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare UNURAN generator object. */
UNUR_GEN *gen; /* generator object */
/* Create the generator object. */
/* Use a predefined standard distribution: */
/* Standard Gaussian distribution. */
/* Choose a method: AROU. */
/* For other (suitable) methods replace "arou" with the */
/* respective name. */
gen = unur_str2gen("normal() & method=arou");
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Now you can use the generator object `gen' to sample from */
/* the standard Gaussian distribution. */
/* Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.5 Arbitrary distributions
===========================
If you want to sample from a non-standard distribution, UNU.RAN might be exactly
what you need. Depending on the information is available, a method must be
choosen for sampling, see *note Concepts:: for an overview and *note Methods::
for details.
/* ------------------------------------------------------------- */
/* File: example2.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
/* In this example we build a distribution object from scratch */
/* and sample from this distribution. */
/* */
/* We use method TDR (Transformed Density Rejection) which */
/* required a PDF and the derivative of the PDF. */
/* ------------------------------------------------------------- */
/* Define the PDF and dPDF of our distribution. */
/* */
/* Our distribution has the PDF */
/* */
/* / 1 - x*x if |x| <= 1 */
/* f(x) = < */
/* \ 0 otherwise */
/* */
/* The PDF of our distribution: */
double mypdf( double x, const UNUR_DISTR *distr )
/* The second argument (`distr') can be used for parameters */
/* for the PDF. (We do not use parameters in our example.) */
{
if (fabs(x) >= 1.)
return 0.;
else
return (1.-x*x);
} /* end of mypdf() */
/* The derivative of the PDF of our distribution: */
double mydpdf( double x, const UNUR_DISTR *distr )
{
if (fabs(x) >= 1.)
return 0.;
else
return (-2.*x);
} /* end of mydpdf() */
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Create a new distribution object from scratch. */
/* It is a continuous distribution, and we need a PDF and the */
/* derivative of the PDF. Moreover we set the domain. */
/* Get empty distribution object for a continuous distribution */
distr = unur_distr_cont_new();
/* Assign the PDF and dPDF (defined above). */
unur_distr_cont_set_pdf( distr, mypdf );
unur_distr_cont_set_dpdf( distr, mydpdf );
/* Set the domain of the distribution (optional for TDR). */
unur_distr_cont_set_domain( distr, -1., 1. );
/* Choose a method: TDR. */
par = unur_tdr_new(distr);
/* Now you can change some of the default settings for the */
/* parameters of the chosen method. We don't do it here. */
/* Create the generator object. */
gen = unur_init(par);
/* Notice that this call has also destroyed the parameter */
/* object `par' as a side effect. */
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.6 Arbitrary distributions (String API)
========================================
If you want to sample from a non-standard distribution, UNU.RAN might be exactly
what you need. Depending on the information is available, a method must be
choosen for sampling, see *note Concepts:: for an overview and *note Methods::
for details.
/* ------------------------------------------------------------- */
/* File: example2_str.c */
/* ------------------------------------------------------------- */
/* String API. */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
/* In this example we use a generic distribution object */
/* and sample from this distribution. */
/* */
/* The PDF of our distribution is given by */
/* */
/* / 1 - x*x if |x| <= 1 */
/* f(x) = < */
/* \ 0 otherwise */
/* */
/* We use method TDR (Transformed Density Rejection) which */
/* required a PDF and the derivative of the PDF. */
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare UNURAN generator object. */
UNUR_GEN *gen; /* generator object */
/* Create the generator object. */
/* Use a generic continuous distribution. */
/* Choose a method: TDR. */
gen = unur_str2gen(
"distr = cont; pdf=\"1-x*x\"; domain=(-1,1) & method=tdr");
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.7 Change parameters of the method
===================================
Each method for generating random numbers allows several parameters to be
modified. If you do not want to use default values, it is possible to change
them. The following example illustrates how to change parameters. For details
see *note Methods::.
/* ------------------------------------------------------------- */
/* File: example3.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
double fparams[2]; /* array for parameters for distribution */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Use a predefined standard distribution: */
/* Gaussian with mean 2. and standard deviation 0.5. */
fparams[0] = 2.;
fparams[1] = 0.5;
distr = unur_distr_normal( fparams, 2 );
/* Choose a method: TDR. */
par = unur_tdr_new(distr);
/* Change some of the default parameters. */
/* We want to use T(x)=log(x) for the transformation. */
unur_tdr_set_c( par, 0. );
/* We want to have the variant with immediate acceptance. */
unur_tdr_set_variant_ia( par );
/* We want to use 10 construction points for the setup */
unur_tdr_set_cpoints ( par, 10, NULL );
/* Create the generator object. */
gen = unur_init(par);
/* Notice that this call has also destroyed the parameter */
/* object `par' as a side effect. */
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* It is possible with method TDR to truncate the distribution */
/* for an existing generator object ... */
unur_tdr_chg_truncated( gen, -1., 0. );
/* ... and sample again. */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.8 Change parameters of the method (String API)
================================================
Each method for generating random numbers allows several parameters to be
modified. If you do not want to use default values, it is possible to change
them. The following example illustrates how to change parameters. For details
see *note Methods::.
/* ------------------------------------------------------------- */
/* File: example3_str.c */
/* ------------------------------------------------------------- */
/* String API. */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare UNURAN generator object. */
UNUR_GEN *gen; /* generator object */
/* Create the generator object. */
/* Use a predefined standard distribution: */
/* Gaussian with mean 2. and standard deviation 0.5. */
/* Choose a method: TDR with parameters */
/* c = 0: use T(x)=log(x) for the transformation; */
/* variant "immediate acceptance"; */
/* number of construction points = 10. */
gen = unur_str2gen(
"normal(2,0.5) & method=tdr; c=0.; variant_ia; cpoints=10");
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* It is possible with method TDR to truncate the distribution */
/* for an existing generator object ... */
unur_tdr_chg_truncated( gen, -1., 0. );
/* ... and sample again. */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.9 Change uniform random generator
===================================
All generator object use the same default uniform random number generator by
default. This can be changed to any generator of your choice such that each
generator object has its own random number generator or can share it with some
other objects. It is also possible to change the default generator at any time.
See *note Using uniform random number generators: URNG, for details.
The following example shows how the uniform random number generator can be
set or changed for a generator object. It requires the RNGSTREAMS library to be
installed and used. Otherwise the example must be modified accordingly.
/* ------------------------------------------------------------- */
/* File: example_rngstreams.c */
/* ------------------------------------------------------------- */
#ifdef UNURAN_SUPPORTS_RNGSTREAM
/* ------------------------------------------------------------- */
/* This example makes use of the RNGSTREAM library for */
/* for generating uniform random numbers. */
/* (see http://statmath.wu.ac.at/software/RngStreams/) */
/* To compile this example you must have set */
/* ./configure --with-urng-rngstream */
/* (Of course the executable has to be linked against the */
/* RNGSTREAM library.) */
/* ------------------------------------------------------------- */
/* Include UNURAN header files. */
#include
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
double fparams[2]; /* array for parameters for distribution */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Declare objects for uniform random number generators. */
UNUR_URNG *urng1, *urng2; /* uniform generator objects */
/* The RNGSTREAMS library sets a package seed. */
unsigned long seed[] = {111u, 222u, 333u, 444u, 555u, 666u};
RngStream_SetPackageSeed(seed);
/* RngStreams only: */
/* Make a object for uniform random number generator. */
/* For details see */
/* http://statmath.wu.ac.at/software/RngStreams/ */
urng1 = unur_urng_rngstream_new("urng-1");
if (urng1 == NULL) exit (EXIT_FAILURE);
/* Use a predefined standard distribution: */
/* Beta with parameters 2 and 3. */
fparams[0] = 2.;
fparams[1] = 3.;
distr = unur_distr_beta( fparams, 2 );
/* Choose a method: TDR. */
par = unur_tdr_new(distr);
/* Set uniform generator in parameter object */
unur_set_urng( par, urng1 );
/* Create the generator object. */
gen = unur_init(par);
/* Notice that this call has also destroyed the parameter */
/* object `par' as a side effect. */
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* Now we want to switch to a different (independent) stream */
/* of uniform random numbers. */
urng2 = unur_urng_rngstream_new("urng-2");
if (urng2 == NULL) exit (EXIT_FAILURE);
unur_chg_urng( gen, urng2 );
/* ... and sample again. */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
/* We also should destroy the uniform random number generators.*/
unur_urng_free(urng1);
unur_urng_free(urng2);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
#else
#include
#include
int main(void) {
printf("You must enable the RNGSTREAM library to run this example!\n\n");
exit (77); /* exit code for automake check routines */
}
#endif
/* ------------------------------------------------------------- */
2.10 Change parameters of underlying distribution
=================================================
One a generator object has been created it allows to draw samples from the
distribution with the given parameters. However, some methods allow to change
the parameters of the underlying distribution and reinitialize the generator
object again. Thus when the parameters of the distribution vary for each draw
we save overhead for destroying the old object and creating a new one.
The following example shows how the parameters of a GIG distribution can be
changed when method CSTD is used.
/* ------------------------------------------------------------- */
/* File: example_reinit.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
/* In this example we show how the parameters of the underlying */
/* distribution can be changed for an existing generator object. */
/* We use the GIG distribution with method CSTD. */
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Parameters of distribution. */
double dparam[3] = {0.5, 1., 5.};
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Create initial GIG distribution object */
distr = unur_distr_gig(dparam, 3);
/* Choose a method: CSTD. */
par = unur_cstd_new(distr);
/* Create the generator object. */
gen = unur_init(par);
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* It is possible for method CSTD to change the parameters of */
/* underlying distribution. However, we have to extract to */
/* pointer to the distribution. Be carefull with this pointer! */
distr = unur_get_distr(gen);
/* Change the parameter(s). */
dparam[2] = 0.001;
unur_distr_cont_set_pdfparams(distr,dparam,3);
/* Do not forget to reinitialize the generator object. */
/* Check the return code. */
/* (and try to find a better error handling) */
if (unur_reinit(gen) != UNUR_SUCCESS) {
fprintf(stderr, "ERROR: cannot reinitialize generator object\n");
exit (EXIT_FAILURE);
}
/* Draw a new sample. */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* Changing parameters can be repeated. */
dparam[2] = 1000;
unur_distr_cont_set_pdfparams(distr,dparam,3);
if (unur_reinit(gen) != UNUR_SUCCESS) {
fprintf(stderr, "ERROR: cannot reinitialize generator object\n");
exit (EXIT_FAILURE);
}
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
2.11 Sample pairs of antithetic random variates
===============================================
Using Method TDR it is easy to sample pairs of antithetic random variates.
/* ------------------------------------------------------------- */
/* File: example_anti.c */
/* ------------------------------------------------------------- */
#ifdef UNURAN_SUPPORTS_PRNG
/* ------------------------------------------------------------- */
/* This example makes use of the PRNG library for generating */
/* uniform random numbers. */
/* (see http://statmath.wu.ac.at/prng/) */
/* To compile this example you must have set */
/* ./configure --with-urng-prng */
/* (Of course the executable has to be linked against the */
/* PRNG library.) */
/* ------------------------------------------------------------- */
/* Example how to sample from two streams of antithetic random */
/* variates from Gaussian N(2,5) and Gamma(4) distribution, resp.*/
/* ------------------------------------------------------------- */
/* Include UNURAN header files. */
#include
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double xn, xg; /* will hold the random number */
double fparams[2]; /* array for parameters for distribution */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen_normal, *gen_gamma;
/* generator objects */
/* Declare objects for uniform random number generators. */
UNUR_URNG *urng1, *urng2; /* uniform generator objects */
/* PRNG only: */
/* Make a object for uniform random number generator. */
/* For details see http://statmath.wu.ac.at/prng/. */
/* The first generator: Gaussian N(2,5) */
/* uniform generator: We use the Mersenne Twister. */
urng1 = unur_urng_prng_new("mt19937(1237)");
if (urng1 == NULL) exit (EXIT_FAILURE);
/* UNURAN generator object for N(2,5) */
fparams[0] = 2.;
fparams[1] = 5.;
distr = unur_distr_normal( fparams, 2 );
/* Choose method TDR with variant PS. */
par = unur_tdr_new( distr );
unur_tdr_set_variant_ps( par );
/* Set uniform generator in parameter object. */
unur_set_urng( par, urng1 );
/* Set auxilliary uniform random number generator. */
/* We use the default generator. */
unur_use_urng_aux_default( par );
/* Alternatively you can create and use your own auxilliary */
/* uniform random number generator: */
/* UNUR_URNG *urng_aux; */
/* urng_aux = unur_urng_prng_new("tt800"); */
/* if (urng_aux == NULL) exit (EXIT_FAILURE); */
/* unur_set_urng_aux( par, urng_aux ); */
/* Create the generator object. */
gen_normal = unur_init(par);
if (gen_normal == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Destroy distribution object (gen_normal has its own copy). */
unur_distr_free(distr);
/* The second generator: Gamma(4) with antithetic variates. */
/* uniform generator: We use the Mersenne Twister. */
urng2 = unur_urng_prng_new("anti(mt19937(1237))");
if (urng2 == NULL) exit (EXIT_FAILURE);
/* UNURAN generator object for gamma(4) */
fparams[0] = 4.;
distr = unur_distr_gamma( fparams, 1 );
/* Choose method TDR with variant PS. */
par = unur_tdr_new( distr );
unur_tdr_set_variant_ps( par );
/* Set uniform generator in parameter object. */
unur_set_urng( par, urng2 );
/* Set auxilliary uniform random number generator. */
/* We use the default generator. */
unur_use_urng_aux_default( par );
/* Alternatively you can create and use your own auxilliary */
/* uniform random number generator (see above). */
/* Notice that both generator objects gen_normal and */
/* gen_gamma can share the same auxilliary URNG. */
/* Create the generator object. */
gen_gamma = unur_init(par);
if (gen_gamma == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Destroy distribution object (gen_normal has its own copy). */
unur_distr_free(distr);
/* Now we can sample pairs of negatively correlated random */
/* variates. E.g.: */
for (i=0; i<10; i++) {
xn = unur_sample_cont(gen_normal);
xg = unur_sample_cont(gen_gamma);
printf("%g, %g\n",xn,xg);
}
/* When you do not need the generator objects any more, you */
/* can destroy it. */
unur_free(gen_normal);
unur_free(gen_gamma);
/* We also should destroy the uniform random number generators.*/
unur_urng_free(urng1);
unur_urng_free(urng2);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
#else
#include
#include
int main(void) {
printf("You must enable the PRNG library to run this example!\n\n");
exit (77); /* exit code for automake check routines */
}
#endif
/* ------------------------------------------------------------- */
2.12 Sample pairs of antithetic random variates (String API)
============================================================
Using Method TDR it is easy to sample pairs of antithetic random variates.
/* ------------------------------------------------------------- */
/* File: example_anti_str.c */
/* ------------------------------------------------------------- */
/* String API. */
/* ------------------------------------------------------------- */
#ifdef UNURAN_SUPPORTS_PRNG
/* ------------------------------------------------------------- */
/* This example makes use of the PRNG library for generating */
/* uniform random numbers. */
/* (see http://statmath.wu.ac.at/prng/) */
/* To compile this example you must have set */
/* ./configure --with-urng-prng */
/* (Of course the executable has to be linked against the */
/* PRNG library.) */
/* ------------------------------------------------------------- */
/* Example how to sample from two streams of antithetic random */
/* variates from Gaussian N(2,5) and Gamma(4) distribution, resp.*/
/* ------------------------------------------------------------- */
/* Include UNURAN header files. */
#include
#include
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double xn, xg; /* will hold the random number */
/* Declare UNURAN generator objects. */
UNUR_GEN *gen_normal, *gen_gamma;
/* PRNG only: */
/* Make a object for uniform random number generator. */
/* For details see http://statmath.wu.ac.at/prng/. */
/* Create the first generator: Gaussian N(2,5) */
gen_normal = unur_str2gen("normal(2,5) & method=tdr; variant_ps & urng=mt19937(1237)");
if (gen_normal == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Set auxilliary uniform random number generator. */
/* We use the default generator. */
unur_chgto_urng_aux_default(gen_normal);
/* The second generator: Gamma(4) with antithetic variates. */
gen_gamma = unur_str2gen("gamma(4) & method=tdr; variant_ps & urng=anti(mt19937(1237))");
if (gen_gamma == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
unur_chgto_urng_aux_default(gen_gamma);
/* Now we can sample pairs of negatively correlated random */
/* variates. E.g.: */
for (i=0; i<10; i++) {
xn = unur_sample_cont(gen_normal);
xg = unur_sample_cont(gen_gamma);
printf("%g, %g\n",xn,xg);
}
/* When you do not need the generator objects any more, you */
/* can destroy it. */
/* But first we have to destroy the uniform random number */
/* generators. */
unur_urng_free(unur_get_urng(gen_normal));
unur_urng_free(unur_get_urng(gen_gamma));
unur_free(gen_normal);
unur_free(gen_gamma);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
#else
#include
#include
int main(void) {
printf("You must enable the PRNG library to run this example!\n\n");
exit (77); /* exit code for automake check routines */
}
#endif
/* ------------------------------------------------------------- */
2.13 More examples
==================
*Note Methods for continuous univariate distributions: Methods_for_CONT.
*Note Methods for continuous empirical univariate distributions:
Methods_for_CEMP.
*Note Methods for continuous empirical multivariate distributions:
Methods_for_CVEMP.
*Note Methods for discrete univariate distributions: Methods_for_DISCR.
3 String Interface
******************
The string interface (string API) provided by the ‘unur_str2gen’ call is the
easiest way to use UNU.RAN. This function takes a character string as its
argument. The string is parsed and the information obtained is used to create a
generator object. It returns ‘NULL’ if this fails, either due to a syntax
error, or due to invalid data. In both cases ‘unur_error’ is set to the
corresponding error codes (*note Error reporting: Error_reporting.).
Additionally there exists the call ‘unur_str2distr’ that only produces a
distribution object.
Notice that the string interface does not implement all features of the
UNU.RAN library. For trickier tasks it might be necessary to use the UNU.RAN
calls.
In *note Examples::, all examples are given using both the UNU.RAN standard
API and this convenient string API. The corresponding programm codes are
equivalent.
Function reference
------------------
-- Function: UNUR_GEN* unur_str2gen (const CHAR* STRING)
Get a generator object for the distribution, method and uniform random
number generator as described in the given STRING. See *note Syntax of
String Interface: StringSyntax, for details.
-- Function: UNUR_DISTR* unur_str2distr (const CHAR* STRING)
Get a distribution object for the distribution described in STRING. See
*note Syntax of String Interface: StringSyntax, and *note Distribution
String: StringDistr, for details. However, only the block for the
distribution object is allowed.
-- Function: UNUR_GEN* unur_makegen_ssu (const CHAR* DISTRSTR, const CHAR*
METHODSTR, UNUR_URNG* URNG)
-- Function: UNUR_GEN* unur_makegen_dsu (const UNUR_DISTR* DISTRIBUTION, const
CHAR* METHODSTR, UNUR_URNG* URNG)
Make a generator object for the distribution, method and uniform random
number generator. The distribution can be given either as string DISTRSTR
or as a distribution object DISTR. The method must be given as a string
METHODSTR. For the syntax of these strings see *note Syntax of String
Interface: StringSyntax. However, the ‘method’ keyword is optional for
these calls and can be omitted. If METHODSTR is the empty (blank) string
or ‘NULL’ method AUTO is used. The uniform random number generator is
optional. If URNG is ‘NULL’ then the default uniform random number
generator is used.
3.1 Syntax of String Interface
==============================
The given string holds information about the requested distribution and
(optional) about the sampling method and the uniform random number generator
invoked. The interpretation of the string is not case-sensitive, all white
spaces are ignored.
The string consists of up to three blocks, separated by ampersands ‘&’.
Each block consists of ‘=’ pairs, separated by semicolons ‘;’.
The first key in each block is used to indicate each block. We have three
different blocks with the following (first) keys:
‘distr’
definition of the distribution (*note Distribution String: StringDistr.).
‘method’
description of the transformation method (*note Method String:
StringMethod.).
‘urng’
uniform random number generation (*note Uniform RNG String: StringURNG.).
The ‘distr’ block must be the very first block and is obligatory. All the
other blocks are optional and can be arranged in arbitrary order.
For details see the following description of each block.
In the following example
distr = normal(3.,0.75); domain = (0,inf) & method = tdr; c = 0
we have a distribution block for the truncated normal distribution with mean 3
and standard deviation 0.75 on domain (0,infinity); and block for choosing
method TDR with parameter c set to 0.
The ‘=’ pairs that follow the first (initial) pair in each block
are used to set parameters. The name of the parameter is given by the ‘’
string. It is deduced from the UNU.RAN set calls by taking the part after
‘..._set_’. The ‘’ string holds the parameters to be set, separated by
commata ‘,’. There are three types of parameters:
_string ‘"..."’ or ‘'...'’_
i.e. any sequence of characters enclosed by double quotes ‘"..."’ or
single quotes ‘'...'’ (there is no distinction between double quotes ‘"’
and single quotes ‘'’).
_list ‘(...,...)’_
i.e. list of _numbers_, separated by commata ‘,’, enclosed in parenthesis
‘(...)’.
_number_
a sequence of characters that is not enclosed by double quotes ‘"..."’,
single quotes ‘'...'’, or parenthesis ‘(...)’. It is interpreted as float
or integer depending on the type of the corresponding parameter.
The ‘’ string (including the character ‘=’) can be omitted when no
argument is required.
At the moment not all ‘set’ calls are supported. The syntax for the
‘’ can be directly derived from the corresponding ‘set’ calls. To
simplify the syntax additional shortcuts are possible. The following table
lists the parameters for the ‘set’ calls that are supported by the string
interface; the entry in parenthesis gives the type of the argument as ‘’
string:
‘int (number):’
The number is interpreted as an integer. ‘true’ and ‘on’ are transformed
to ‘1’, ‘false’ and ‘off’ are transformed to ‘0’. A missing argument is
interpreted as ‘1’.
‘int, int (number, number or list):’
The two numbers or the first two entries in the list are interpreted as a
integers. ‘inf’ and ‘-inf’ are transformed to ‘INT_MAX’ and ‘INT_MIN’
respectively, i.e. the largest and smallest integers that can be
represented by the computer.
‘unsigned (number):’
The number is interpreted as an unsigned hexadecimal integer.
‘double (number):’
The number is interpreted as a floating point number. ‘inf’ is transformed
to ‘UNUR_INFINITY’.
‘double, double (number, number or list):’
The two numbers or the first two entries in the list are interpreted as a
floating point numbers. ‘inf’ is transformed to ‘UNUR_INFINITY’. However
using ‘inf’ in the list might not work for all versions of C. Then it is
recommended to use two single numbers instead of a list.
‘int, double* ([number,] list or number):’
− The list is interpreted as a double array. The (first) number as its
length. If it is less than the actual size of the array only the
first entries of the array are used.
− If only the list is given (i.e., if the first number is omitted), the
first number is set to the actual size of the array.
− If only the number is given (i.e., if the list is omitted), the ‘NULL’
pointer is used instead an array as argument.
‘double*, int (list [,number]):’
The list is interpreted as a double array. The (second) number as its
length. If the length is omitted, it is replaced by the actual size of the
array. (Only in the ‘distribution’ block!)
‘char* (string):’
The character string is passed as is to the corresponding set call.
Notice that missing entries in a list of numbers are interpreted as ‘0’.
E.g, a the list ‘(1,,3)’ is read as ‘(1,0,3)’, the list ‘(1,2,)’ as ‘(1,2,0)’.
The the list of ‘key’ strings in *note Keys for Distribution String:
KeysDistr, and *note Keys for Method String: KeysMethod, for further details.
3.2 Distribution String
=======================
The ‘distr’ block must be the very first block and is obligatory. For that
reason the keyword ‘distr’ is optional and can be omitted (together with the ‘=’
character). Moreover it is ignored while parsing the string. However, to avoid
some possible confusion it has to start with the letter ‘d’ (if it is given at
all).
The value of the ‘distr’ key is used to get the distribution object, either
via a ‘unur_distr_’ call for a standard distribution via a
‘unur_distr__new’ call to get an object of a generic distribution.
However not all generic distributions are supported yet.
The parameters for the standard distribution are given as a list. There must
not be any character (other than white space) between the name of the standard
distribution and the opening parenthesis ‘(’ of this list. E.g., to get a beta
distribution, use
distr = beta(2,4)
To get an object for a discrete distribution with probability vector
(0.5,0.2,0.3), use
distr = discr; pv = (0.5,0.2,0.3)
It is also possible to set a PDF, PMF, or CDF using a string. E.g., to
create a continuous distribution with PDF proportional to ‘exp(-sqrt(2+(x-1)^2)
+ (x-1))’ and domain (0,inf) use
distr = cont; pdf = "exp(-sqrt(2+(x-1)^2) + (x-1))"
Notice: If this string is used in an ‘unur_str2distr’ or ‘unur_str2gen’ call the
double quotes ‘"’ must be protected by ‘\"’. Alternatively, single quotes may
be used instead
distr = cont; pdf = 'exp(-sqrt(2+(x-1)^2) + (x-1))'
For the details of function strings see *note Function String: StringFunct.
3.2.1 Keys for Distribution String
----------------------------------
List of standard distributions *note Standard distributions: Stddist.
− ‘[distr =] beta(...)’ ⇒ *note beta::
− ‘[distr =] binomial(...)’ ⇒ *note binomial::
− ‘[distr =] cauchy(...)’ ⇒ *note cauchy::
− ‘[distr =] chi(...)’ ⇒ *note chi::
− ‘[distr =] chisquare(...)’ ⇒ *note chisquare::
− ‘[distr =] exponential(...)’ ⇒ *note exponential::
− ‘[distr =] extremeI(...)’ ⇒ *note extremeI::
− ‘[distr =] extremeII(...)’ ⇒ *note extremeII::
− ‘[distr =] F(...)’ ⇒ *note F::
− ‘[distr =] gamma(...)’ ⇒ *note gamma::
− ‘[distr =] geometric(...)’ ⇒ *note geometric::
− ‘[distr =] gig(...)’ ⇒ *note gig::
− ‘[distr =] gig2(...)’ ⇒ *note gig2::
− ‘[distr =] hyperbolic(...)’ ⇒ *note hyperbolic::
− ‘[distr =] hypergeometric(...)’ ⇒ *note hypergeometric::
− ‘[distr =] ig(...)’ ⇒ *note ig::
− ‘[distr =] laplace(...)’ ⇒ *note laplace::
− ‘[distr =] logarithmic(...)’ ⇒ *note logarithmic::
− ‘[distr =] logistic(...)’ ⇒ *note logistic::
− ‘[distr =] lognormal(...)’ ⇒ *note lognormal::
− ‘[distr =] lomax(...)’ ⇒ *note lomax::
− ‘[distr =] negativebinomial(...)’ ⇒ *note negativebinomial::
− ‘[distr =] normal(...)’ ⇒ *note normal::
− ‘[distr =] pareto(...)’ ⇒ *note pareto::
− ‘[distr =] poisson(...)’ ⇒ *note poisson::
− ‘[distr =] powerexponential(...)’ ⇒ *note powerexponential::
− ‘[distr =] rayleigh(...)’ ⇒ *note rayleigh::
− ‘[distr =] slash(...)’ ⇒ *note slash::
− ‘[distr =] student(...)’ ⇒ *note student::
− ‘[distr =] triangular(...)’ ⇒ *note triangular::
− ‘[distr =] uniform(...)’ ⇒ *note uniform::
− ‘[distr =] weibull(...)’ ⇒ *note weibull::
List of generic distributions *note Handling Distribution Objects:
Distribution_objects.
− ‘[distr =] cemp’ ⇒ *note CEMP::
− ‘[distr =] cont’ ⇒ *note CONT::
− ‘[distr =] discr’ ⇒ *note DISCR::
_Notice_: Order statistics for continuous distributions (*note CORDER::) are
supported by using the key ‘orderstatistics’ for distributions of type ‘CONT’.
List of keys that are available via the String API. For description see the
corresponding UNU.RAN set calls.
• All distribution types
‘name = ""’
⇒ *note ‘unur_distr_set_name’: funct:unur_distr_set_name.
• ‘cemp’ (Distribution Type) (*note CEMP::)
‘data = () [, ]’
⇒ *note ‘unur_distr_cemp_set_data’: funct:unur_distr_cemp_set_data.
‘hist_bins = () [, ]’
⇒ *note ‘unur_distr_cemp_set_hist_bins’:
funct:unur_distr_cemp_set_hist_bins.
‘hist_domain = , | ()’
⇒ *note ‘unur_distr_cemp_set_hist_domain’:
funct:unur_distr_cemp_set_hist_domain.
‘hist_prob = () [, ]’
⇒ *note ‘unur_distr_cemp_set_hist_prob’:
funct:unur_distr_cemp_set_hist_prob.
• ‘cont’ (Distribution Type) (*note CONT::)
‘cdf = ""’
⇒ *note ‘unur_distr_cont_set_cdfstr’:
funct:unur_distr_cont_set_cdfstr.
‘center = ’
⇒ *note ‘unur_distr_cont_set_center’:
funct:unur_distr_cont_set_center.
‘domain = , | ()’
⇒ *note ‘unur_distr_cont_set_domain’:
funct:unur_distr_cont_set_domain.
‘hr = ""’
⇒ *note ‘unur_distr_cont_set_hrstr’: funct:unur_distr_cont_set_hrstr.
‘logcdf = ""’
⇒ *note ‘unur_distr_cont_set_logcdfstr’:
funct:unur_distr_cont_set_logcdfstr.
‘logpdf = ""’
⇒ *note ‘unur_distr_cont_set_logpdfstr’:
funct:unur_distr_cont_set_logpdfstr.
‘mode = ’
⇒ *note ‘unur_distr_cont_set_mode’: funct:unur_distr_cont_set_mode.
‘pdf = ""’
⇒ *note ‘unur_distr_cont_set_pdfstr’:
funct:unur_distr_cont_set_pdfstr.
‘pdfarea = ’
⇒ *note ‘unur_distr_cont_set_pdfarea’:
funct:unur_distr_cont_set_pdfarea.
‘pdfparams = () [, ]’
⇒ *note ‘unur_distr_cont_set_pdfparams’:
funct:unur_distr_cont_set_pdfparams.
‘orderstatistics = , | ()’
Make order statistics for given distribution. The first parameter
gives the sample size, the second parameter its rank. (see *note
‘unur_distr_corder_new’: funct:unur_distr_corder_new.)
• ‘discr’ (Distribution Type) (*note DISCR::)
‘cdf = ""’
⇒ *note ‘unur_distr_discr_set_cdfstr’:
funct:unur_distr_discr_set_cdfstr.
‘domain = , | ()’
⇒ *note ‘unur_distr_discr_set_domain’:
funct:unur_distr_discr_set_domain.
‘mode [= ]’
⇒ *note ‘unur_distr_discr_set_mode’: funct:unur_distr_discr_set_mode.
‘pmf = ""’
⇒ *note ‘unur_distr_discr_set_pmfstr’:
funct:unur_distr_discr_set_pmfstr.
‘pmfparams = () [, ]’
⇒ *note ‘unur_distr_discr_set_pmfparams’:
funct:unur_distr_discr_set_pmfparams.
‘pmfsum = ’
⇒ *note ‘unur_distr_discr_set_pmfsum’:
funct:unur_distr_discr_set_pmfsum.
‘pv = () [, ]’
⇒ *note ‘unur_distr_discr_set_pv’: funct:unur_distr_discr_set_pv.
3.3 Function String
===================
In unuran it is also possible to define functions (e.g. CDF or PDF) as strings.
As you can see in Example 2 (*note Example_2_str::) it is very easy to define
the PDF of a distribution object by means of a string. The possibilities using
this string interface are more restricted than using a pointer to a routine
coded in C (*note Example_2::). But the differences in evaluation time is
small. When a distribution object is defined using this string interface then
of course the same conditions on the given density or CDF must be satisfied for
a chosen method as for the standard API. This string interface can be used for
both within the UNU.RAN string API using the ‘unur_str2gen’ call, and for calls
that define the density or CDF for a particular distribution object as done with
(e.g.) the call ‘unur_distr_cont_set_pdfstr’. Here is an example for the
latter case:
unur_distr_cont_set_pdfstr(distr,"1-x*x");
Syntax
------
The syntax for the function string is case insensitive, white spaces are
ingnored. The expressions are similar to most programming languages and
mathematical programs (see also the examples below). It is especially
influenced by C. The usual preceedence rules are used (from highest to lowest
preceedence: functions, power, multiplication, addition, relation operators).
Use parentheses in case of doubt or when these preceedences should be changed.
Relation operators can be used as indicator functions, i.e. the term ‘(x>1)’
is evaluted as ‘1’ if this relation is satisfied, and as ‘0’ otherwise.
The first unknown symbol (letter or word) is interpreted as the variable of
the function. It is recommended to use ‘x’. Only one variable can be used.
_Important_: The symbol ‘e’ is used twice, for Euler’s constant (= 2.7182...)
and as exponent. The multiplication operator ‘*’ must not be omitted, i.e. ‘2
x’ is interpreted as the string ‘2x’ (which will result in a syntax error).
List of symbols
---------------
Numbers
Numbers are composed using digits and, optionally, a sign, a decimal point, and
an exponent indicated by ‘e’.
Symbol Explanation Examples
‘0...9’ digits ‘2343’
‘.’ decimal point ‘165.567’
‘-’ negative sign ‘-465.223’
‘e’ exponet ‘13.2e-4’ (=0.00132)
Constants
‘pi’ pi = 3.1415... ‘3*pi+2’
‘e’ Euler’s constant ‘3*e+2’ (= 10.15...; do not
cofuse with ‘3e2’ = 300)
‘inf’ infinity (used for domains)
Special symbols
‘(’ opening parenthesis ‘2*(3+x)’
‘)’ closing parenthesis ‘2*(3+x)’
‘,’ (argument) list separator ‘mod(13,2)’
Relation operators (Indicator functions)
‘<’ less than ‘(x<1)’
‘=’ equal ‘(2=x)’
‘==’ same as ‘=’ ‘(x==3)’
‘>’ greater than ‘(x>0)’
‘<=’ less than or equal ‘(x<=1)’
‘!=’ not equal ‘(x!0)’
‘<>’ same as ‘!=’ ‘(x<>pi)’
‘>=’ greater or equal ‘(x>=1)’
Arithmetic operators
‘+’ addition ‘2+x’
‘-’ subtraction ‘2-x’
‘*’ multiplication ‘2*x’
‘/’ division ‘x/2’
‘^’ power ‘x^2’
Functions
‘mod’ ‘mod(m,n)’ remainder of mod(x,2)
devision m over n
‘exp’ exponential function ‘exp(-x^2)’ (same as
(same as ‘e^x’) ‘e^(-x^2)’)
‘log’ natural logarithm ‘log(x)’
‘sin’ sine ‘sin(x)’
‘cos’ cosine ‘cos(x)’
‘tan’ tangent ‘tan(x)’
‘sec’ secant ‘sec(x*2)’
‘sqrt’ square root ‘sqrt(2*x)’
‘abs’ absolute value ‘abs(x)’
‘sgn’ sign function ‘sign(x)*3’
Variable
‘x’ variable ‘3*x^2’
Examples
--------
1.231+7.9876*x-1.234e-3*x^2+3.335e-5*x^3
sin(2*pi*x)+x^2
exp(-((x-3)/2.1)^2)
It is also possible to define functions using different terms on separate
domains. However, instead of constructs using ‘if ... then ... else ...’
indicator functions are available.
For example to define the density of triangular distribution with domain (-1,1)
and mode 0 use
(x>-1)*(x<0)*(1+x) + (x>=0)*(x<1)*(1-x)
3.4 Method String
=================
The key ‘method’ is obligatory, it must be the first key and its value is the
name of a method suitable for the choosen standard distribution. E.g., if
method AROU is chosen, use
method = arou
Of course the all following keys dependend on the method choosen at first.
All corresponding ‘set’ calls of UNU.RAN are available and the key is the string
after the ‘unur__set_’ part of the command. E.g., UNU.RAN provides
the command ‘unur_arou_set_max_sqhratio’ to set a parameter of method AROU. To
call this function via the string-interface, the key ‘max_sqhratio’ can be used:
max_sqhratio = 0.9
Additionally the keyword ‘debug’ can be used to set debugging flags (see *note
Debugging: Debug, for details).
If this block is omitted, a suitable default method is used. Notice however
that the default method may change in future versions of UNU.RAN.
3.4.1 Keys for Method String
----------------------------
List of methods and keys that are available via the String API. For description
see the corresponding UNU.RAN set calls.
• ‘method = arou’ ⇒ ‘unur_arou_new’ (*note AROU::)
‘cpoints = [, ()] | ()’
⇒ *note ‘unur_arou_set_cpoints’: funct:unur_arou_set_cpoints.
‘darsfactor = ’
⇒ *note ‘unur_arou_set_darsfactor’: funct:unur_arou_set_darsfactor.
‘guidefactor = ’
⇒ *note ‘unur_arou_set_guidefactor’: funct:unur_arou_set_guidefactor.
‘max_segments [= ]’
⇒ *note ‘unur_arou_set_max_segments’:
funct:unur_arou_set_max_segments.
‘max_sqhratio = ’
⇒ *note ‘unur_arou_set_max_sqhratio’:
funct:unur_arou_set_max_sqhratio.
‘pedantic [= ]’
⇒ *note ‘unur_arou_set_pedantic’: funct:unur_arou_set_pedantic.
‘usecenter [= ]’
⇒ *note ‘unur_arou_set_usecenter’: funct:unur_arou_set_usecenter.
‘usedars [= ]’
⇒ *note ‘unur_arou_set_usedars’: funct:unur_arou_set_usedars.
‘verify [= ]’
⇒ *note ‘unur_arou_set_verify’: funct:unur_arou_set_verify.
• ‘method = ars’ ⇒ ‘unur_ars_new’ (*note ARS::)
‘cpoints = [, ()] | ()’
⇒ *note ‘unur_ars_set_cpoints’: funct:unur_ars_set_cpoints.
‘max_intervals [= ]’
⇒ *note ‘unur_ars_set_max_intervals’:
funct:unur_ars_set_max_intervals.
‘max_iter [= ]’
⇒ *note ‘unur_ars_set_max_iter’: funct:unur_ars_set_max_iter.
‘pedantic [= ]’
⇒ *note ‘unur_ars_set_pedantic’: funct:unur_ars_set_pedantic.
‘reinit_ncpoints [= ]’
⇒ *note ‘unur_ars_set_reinit_ncpoints’:
funct:unur_ars_set_reinit_ncpoints.
‘reinit_percentiles = [, ()] | ()’
⇒ *note ‘unur_ars_set_reinit_percentiles’:
funct:unur_ars_set_reinit_percentiles.
‘verify [= ]’
⇒ *note ‘unur_ars_set_verify’: funct:unur_ars_set_verify.
• ‘method = auto’ ⇒ ‘unur_auto_new’ (*note AUTO::)
‘logss [= ]’
⇒ *note ‘unur_auto_set_logss’: funct:unur_auto_set_logss.
• ‘method = cstd’ ⇒ ‘unur_cstd_new’ (*note CSTD::)
‘variant = ’
⇒ *note ‘unur_cstd_set_variant’: funct:unur_cstd_set_variant.
• ‘method = dari’ ⇒ ‘unur_dari_new’ (*note DARI::)
‘cpfactor = ’
⇒ *note ‘unur_dari_set_cpfactor’: funct:unur_dari_set_cpfactor.
‘squeeze [= ]’
⇒ *note ‘unur_dari_set_squeeze’: funct:unur_dari_set_squeeze.
‘tablesize [= ]’
⇒ *note ‘unur_dari_set_tablesize’: funct:unur_dari_set_tablesize.
‘verify [= ]’
⇒ *note ‘unur_dari_set_verify’: funct:unur_dari_set_verify.
• ‘method = dau’ ⇒ ‘unur_dau_new’ (*note DAU::)
‘urnfactor = ’
⇒ *note ‘unur_dau_set_urnfactor’: funct:unur_dau_set_urnfactor.
• ‘method = dgt’ ⇒ ‘unur_dgt_new’ (*note DGT::)
‘guidefactor = ’
⇒ *note ‘unur_dgt_set_guidefactor’: funct:unur_dgt_set_guidefactor.
‘variant = ’
⇒ *note ‘unur_dgt_set_variant’: funct:unur_dgt_set_variant.
• ‘method = dsrou’ ⇒ ‘unur_dsrou_new’ (*note DSROU::)
‘cdfatmode = ’
⇒ *note ‘unur_dsrou_set_cdfatmode’: funct:unur_dsrou_set_cdfatmode.
‘verify [= ]’
⇒ *note ‘unur_dsrou_set_verify’: funct:unur_dsrou_set_verify.
• ‘method = dstd’ ⇒ ‘unur_dstd_new’ (*note DSTD::)
‘variant = ’
⇒ *note ‘unur_dstd_set_variant’: funct:unur_dstd_set_variant.
• ‘method = empk’ ⇒ ‘unur_empk_new’ (*note EMPK::)
‘beta = ’
⇒ *note ‘unur_empk_set_beta’: funct:unur_empk_set_beta.
‘kernel = ’
⇒ *note ‘unur_empk_set_kernel’: funct:unur_empk_set_kernel.
‘positive [= ]’
⇒ *note ‘unur_empk_set_positive’: funct:unur_empk_set_positive.
‘smoothing = ’
⇒ *note ‘unur_empk_set_smoothing’: funct:unur_empk_set_smoothing.
‘varcor [= ]’
⇒ *note ‘unur_empk_set_varcor’: funct:unur_empk_set_varcor.
• ‘method = gibbs’ ⇒ ‘unur_gibbs_new’ (*note GIBBS::)
‘burnin [= ]’
⇒ *note ‘unur_gibbs_set_burnin’: funct:unur_gibbs_set_burnin.
‘c = ’
⇒ *note ‘unur_gibbs_set_c’: funct:unur_gibbs_set_c.
‘thinning [= ]’
⇒ *note ‘unur_gibbs_set_thinning’: funct:unur_gibbs_set_thinning.
‘variant_coordinate’
⇒ *note ‘unur_gibbs_set_variant_coordinate’:
funct:unur_gibbs_set_variant_coordinate.
‘variant_random_direction’
⇒ *note ‘unur_gibbs_set_variant_random_direction’:
funct:unur_gibbs_set_variant_random_direction.
• ‘method = hinv’ ⇒ ‘unur_hinv_new’ (*note HINV::)
‘boundary = , | ()’
⇒ *note ‘unur_hinv_set_boundary’: funct:unur_hinv_set_boundary.
‘cpoints = (), ’
⇒ *note ‘unur_hinv_set_cpoints’: funct:unur_hinv_set_cpoints.
‘guidefactor = ’
⇒ *note ‘unur_hinv_set_guidefactor’: funct:unur_hinv_set_guidefactor.
‘max_intervals [= ]’
⇒ *note ‘unur_hinv_set_max_intervals’:
funct:unur_hinv_set_max_intervals.
‘order [= ]’
⇒ *note ‘unur_hinv_set_order’: funct:unur_hinv_set_order.
‘u_resolution = ’
⇒ *note ‘unur_hinv_set_u_resolution’:
funct:unur_hinv_set_u_resolution.
• ‘method = hitro’ ⇒ ‘unur_hitro_new’ (*note HITRO::)
‘adaptive_multiplier = ’
⇒ *note ‘unur_hitro_set_adaptive_multiplier’:
funct:unur_hitro_set_adaptive_multiplier.
‘burnin [= ]’
⇒ *note ‘unur_hitro_set_burnin’: funct:unur_hitro_set_burnin.
‘r = ’
⇒ *note ‘unur_hitro_set_r’: funct:unur_hitro_set_r.
‘thinning [= ]’
⇒ *note ‘unur_hitro_set_thinning’: funct:unur_hitro_set_thinning.
‘use_adaptiveline [= ]’
⇒ *note ‘unur_hitro_set_use_adaptiveline’:
funct:unur_hitro_set_use_adaptiveline.
‘use_adaptiverectangle [= ]’
⇒ *note ‘unur_hitro_set_use_adaptiverectangle’:
funct:unur_hitro_set_use_adaptiverectangle.
‘use_boundingrectangle [= ]’
⇒ *note ‘unur_hitro_set_use_boundingrectangle’:
funct:unur_hitro_set_use_boundingrectangle.
‘v = ’
⇒ *note ‘unur_hitro_set_v’: funct:unur_hitro_set_v.
‘variant_coordinate’
⇒ *note ‘unur_hitro_set_variant_coordinate’:
funct:unur_hitro_set_variant_coordinate.
‘variant_random_direction’
⇒ *note ‘unur_hitro_set_variant_random_direction’:
funct:unur_hitro_set_variant_random_direction.
• ‘method = hrb’ ⇒ ‘unur_hrb_new’ (*note HRB::)
‘upperbound = ’
⇒ *note ‘unur_hrb_set_upperbound’: funct:unur_hrb_set_upperbound.
‘verify [= ]’
⇒ *note ‘unur_hrb_set_verify’: funct:unur_hrb_set_verify.
• ‘method = hrd’ ⇒ ‘unur_hrd_new’ (*note HRD::)
‘verify [= ]’
⇒ *note ‘unur_hrd_set_verify’: funct:unur_hrd_set_verify.
• ‘method = hri’ ⇒ ‘unur_hri_new’ (*note HRI::)
‘p0 = ’
⇒ *note ‘unur_hri_set_p0’: funct:unur_hri_set_p0.
‘verify [= ]’
⇒ *note ‘unur_hri_set_verify’: funct:unur_hri_set_verify.
• ‘method = itdr’ ⇒ ‘unur_itdr_new’ (*note ITDR::)
‘cp = ’
⇒ *note ‘unur_itdr_set_cp’: funct:unur_itdr_set_cp.
‘ct = ’
⇒ *note ‘unur_itdr_set_ct’: funct:unur_itdr_set_ct.
‘verify [= ]’
⇒ *note ‘unur_itdr_set_verify’: funct:unur_itdr_set_verify.
‘xi = ’
⇒ *note ‘unur_itdr_set_xi’: funct:unur_itdr_set_xi.
• ‘method = mvtdr’ ⇒ ‘unur_mvtdr_new’ (*note MVTDR::)
‘boundsplitting = ’
⇒ *note ‘unur_mvtdr_set_boundsplitting’:
funct:unur_mvtdr_set_boundsplitting.
‘maxcones [= ]’
⇒ *note ‘unur_mvtdr_set_maxcones’: funct:unur_mvtdr_set_maxcones.
‘stepsmin [= ]’
⇒ *note ‘unur_mvtdr_set_stepsmin’: funct:unur_mvtdr_set_stepsmin.
‘verify [= ]’
⇒ *note ‘unur_mvtdr_set_verify’: funct:unur_mvtdr_set_verify.
• ‘method = ninv’ ⇒ ‘unur_ninv_new’ (*note NINV::)
‘max_iter [= ]’
⇒ *note ‘unur_ninv_set_max_iter’: funct:unur_ninv_set_max_iter.
‘start = , | ()’
⇒ *note ‘unur_ninv_set_start’: funct:unur_ninv_set_start.
‘table [= ]’
⇒ *note ‘unur_ninv_set_table’: funct:unur_ninv_set_table.
‘u_resolution = ’
⇒ *note ‘unur_ninv_set_u_resolution’:
funct:unur_ninv_set_u_resolution.
‘usebisect’
⇒ *note ‘unur_ninv_set_usebisect’: funct:unur_ninv_set_usebisect.
‘usenewton’
⇒ *note ‘unur_ninv_set_usenewton’: funct:unur_ninv_set_usenewton.
‘useregula’
⇒ *note ‘unur_ninv_set_useregula’: funct:unur_ninv_set_useregula.
‘x_resolution = ’
⇒ *note ‘unur_ninv_set_x_resolution’:
funct:unur_ninv_set_x_resolution.
• ‘method = nrou’ ⇒ ‘unur_nrou_new’ (*note NROU::)
‘center = ’
⇒ *note ‘unur_nrou_set_center’: funct:unur_nrou_set_center.
‘r = ’
⇒ *note ‘unur_nrou_set_r’: funct:unur_nrou_set_r.
‘u = , | ()’
⇒ *note ‘unur_nrou_set_u’: funct:unur_nrou_set_u.
‘v = ’
⇒ *note ‘unur_nrou_set_v’: funct:unur_nrou_set_v.
‘verify [= ]’
⇒ *note ‘unur_nrou_set_verify’: funct:unur_nrou_set_verify.
• ‘method = pinv’ ⇒ ‘unur_pinv_new’ (*note PINV::)
‘boundary = , | ()’
⇒ *note ‘unur_pinv_set_boundary’: funct:unur_pinv_set_boundary.
‘extra_testpoints [= ]’
⇒ *note ‘unur_pinv_set_extra_testpoints’:
funct:unur_pinv_set_extra_testpoints.
‘keepcdf [= ]’
⇒ *note ‘unur_pinv_set_keepcdf’: funct:unur_pinv_set_keepcdf.
‘max_intervals [= ]’
⇒ *note ‘unur_pinv_set_max_intervals’:
funct:unur_pinv_set_max_intervals.
‘order [= ]’
⇒ *note ‘unur_pinv_set_order’: funct:unur_pinv_set_order.
‘searchboundary = , | ()’
⇒ *note ‘unur_pinv_set_searchboundary’:
funct:unur_pinv_set_searchboundary.
‘smoothness [= ]’
⇒ *note ‘unur_pinv_set_smoothness’: funct:unur_pinv_set_smoothness.
‘u_resolution = ’
⇒ *note ‘unur_pinv_set_u_resolution’:
funct:unur_pinv_set_u_resolution.
‘use_upoints [= ]’
⇒ *note ‘unur_pinv_set_use_upoints’: funct:unur_pinv_set_use_upoints.
‘usecdf’
⇒ *note ‘unur_pinv_set_usecdf’: funct:unur_pinv_set_usecdf.
‘usepdf’
⇒ *note ‘unur_pinv_set_usepdf’: funct:unur_pinv_set_usepdf.
• ‘method = srou’ ⇒ ‘unur_srou_new’ (*note SROU::)
‘cdfatmode = ’
⇒ *note ‘unur_srou_set_cdfatmode’: funct:unur_srou_set_cdfatmode.
‘pdfatmode = ’
⇒ *note ‘unur_srou_set_pdfatmode’: funct:unur_srou_set_pdfatmode.
‘r = ’
⇒ *note ‘unur_srou_set_r’: funct:unur_srou_set_r.
‘usemirror [= ]’
⇒ *note ‘unur_srou_set_usemirror’: funct:unur_srou_set_usemirror.
‘usesqueeze [= ]’
⇒ *note ‘unur_srou_set_usesqueeze’: funct:unur_srou_set_usesqueeze.
‘verify [= ]’
⇒ *note ‘unur_srou_set_verify’: funct:unur_srou_set_verify.
• ‘method = ssr’ ⇒ ‘unur_ssr_new’ (*note SSR::)
‘cdfatmode = ’
⇒ *note ‘unur_ssr_set_cdfatmode’: funct:unur_ssr_set_cdfatmode.
‘pdfatmode = ’
⇒ *note ‘unur_ssr_set_pdfatmode’: funct:unur_ssr_set_pdfatmode.
‘usesqueeze [= ]’
⇒ *note ‘unur_ssr_set_usesqueeze’: funct:unur_ssr_set_usesqueeze.
‘verify [= ]’
⇒ *note ‘unur_ssr_set_verify’: funct:unur_ssr_set_verify.
• ‘method = tabl’ ⇒ ‘unur_tabl_new’ (*note TABL::)
‘areafraction = ’
⇒ *note ‘unur_tabl_set_areafraction’:
funct:unur_tabl_set_areafraction.
‘boundary = , | ()’
⇒ *note ‘unur_tabl_set_boundary’: funct:unur_tabl_set_boundary.
‘cpoints = [, ()] | ()’
⇒ *note ‘unur_tabl_set_cpoints’: funct:unur_tabl_set_cpoints.
‘darsfactor = ’
⇒ *note ‘unur_tabl_set_darsfactor’: funct:unur_tabl_set_darsfactor.
‘guidefactor = ’
⇒ *note ‘unur_tabl_set_guidefactor’: funct:unur_tabl_set_guidefactor.
‘max_intervals [= ]’
⇒ *note ‘unur_tabl_set_max_intervals’:
funct:unur_tabl_set_max_intervals.
‘max_sqhratio = ’
⇒ *note ‘unur_tabl_set_max_sqhratio’:
funct:unur_tabl_set_max_sqhratio.
‘nstp [= ]’
⇒ *note ‘unur_tabl_set_nstp’: funct:unur_tabl_set_nstp.
‘pedantic [= ]’
⇒ *note ‘unur_tabl_set_pedantic’: funct:unur_tabl_set_pedantic.
‘slopes = (), ’
⇒ *note ‘unur_tabl_set_slopes’: funct:unur_tabl_set_slopes.
‘usedars [= ]’
⇒ *note ‘unur_tabl_set_usedars’: funct:unur_tabl_set_usedars.
‘useear [= ]’
⇒ *note ‘unur_tabl_set_useear’: funct:unur_tabl_set_useear.
‘variant_ia [= ]’
⇒ *note ‘unur_tabl_set_variant_ia’: funct:unur_tabl_set_variant_ia.
‘variant_splitmode = ’
⇒ *note ‘unur_tabl_set_variant_splitmode’:
funct:unur_tabl_set_variant_splitmode.
‘verify [= ]’
⇒ *note ‘unur_tabl_set_verify’: funct:unur_tabl_set_verify.
• ‘method = tdr’ ⇒ ‘unur_tdr_new’ (*note TDR::)
‘c = ’
⇒ *note ‘unur_tdr_set_c’: funct:unur_tdr_set_c.
‘cpoints = [, ()] | ()’
⇒ *note ‘unur_tdr_set_cpoints’: funct:unur_tdr_set_cpoints.
‘darsfactor = ’
⇒ *note ‘unur_tdr_set_darsfactor’: funct:unur_tdr_set_darsfactor.
‘guidefactor = ’
⇒ *note ‘unur_tdr_set_guidefactor’: funct:unur_tdr_set_guidefactor.
‘max_intervals [= ]’
⇒ *note ‘unur_tdr_set_max_intervals’:
funct:unur_tdr_set_max_intervals.
‘max_sqhratio = ’
⇒ *note ‘unur_tdr_set_max_sqhratio’: funct:unur_tdr_set_max_sqhratio.
‘pedantic [= ]’
⇒ *note ‘unur_tdr_set_pedantic’: funct:unur_tdr_set_pedantic.
‘reinit_ncpoints [= ]’
⇒ *note ‘unur_tdr_set_reinit_ncpoints’:
funct:unur_tdr_set_reinit_ncpoints.
‘reinit_percentiles = [, ()] | ()’
⇒ *note ‘unur_tdr_set_reinit_percentiles’:
funct:unur_tdr_set_reinit_percentiles.
‘usecenter [= ]’
⇒ *note ‘unur_tdr_set_usecenter’: funct:unur_tdr_set_usecenter.
‘usedars [= ]’
⇒ *note ‘unur_tdr_set_usedars’: funct:unur_tdr_set_usedars.
‘usemode [= ]’
⇒ *note ‘unur_tdr_set_usemode’: funct:unur_tdr_set_usemode.
‘variant_gw’
⇒ *note ‘unur_tdr_set_variant_gw’: funct:unur_tdr_set_variant_gw.
‘variant_ia’
⇒ *note ‘unur_tdr_set_variant_ia’: funct:unur_tdr_set_variant_ia.
‘variant_ps’
⇒ *note ‘unur_tdr_set_variant_ps’: funct:unur_tdr_set_variant_ps.
‘verify [= ]’
⇒ *note ‘unur_tdr_set_verify’: funct:unur_tdr_set_verify.
• ‘method = utdr’ ⇒ ‘unur_utdr_new’ (*note UTDR::)
‘cpfactor = ’
⇒ *note ‘unur_utdr_set_cpfactor’: funct:unur_utdr_set_cpfactor.
‘deltafactor = ’
⇒ *note ‘unur_utdr_set_deltafactor’: funct:unur_utdr_set_deltafactor.
‘pdfatmode = ’
⇒ *note ‘unur_utdr_set_pdfatmode’: funct:unur_utdr_set_pdfatmode.
‘verify [= ]’
⇒ *note ‘unur_utdr_set_verify’: funct:unur_utdr_set_verify.
• ‘method = vempk’ ⇒ ‘unur_vempk_new’ (*note VEMPK::)
‘smoothing = ’
⇒ *note ‘unur_vempk_set_smoothing’: funct:unur_vempk_set_smoothing.
‘varcor [= ]’
⇒ *note ‘unur_vempk_set_varcor’: funct:unur_vempk_set_varcor.
• ‘method = vnrou’ ⇒ ‘unur_vnrou_new’ (*note VNROU::)
‘r = ’
⇒ *note ‘unur_vnrou_set_r’: funct:unur_vnrou_set_r.
‘v = ’
⇒ *note ‘unur_vnrou_set_v’: funct:unur_vnrou_set_v.
‘verify [= ]’
⇒ *note ‘unur_vnrou_set_verify’: funct:unur_vnrou_set_verify.
3.5 Uniform RNG String
======================
The value of the ‘urng’ key is passed to the PRNG interface (see *Note Overview:
(prng)Top. for details). However it only works when using the PRNG library is
enabled, see *note Installation:: for details. There are no other keys.
IMPORTANT: UNU.RAN creates a new uniform random number generator for the
generator object. The pointer to this uniform generator has to be read and
saved via a ‘unur_get_urng’ call in order to clear the memory _before_ the
UNU.RAN generator object is destroyed.
If this block is omitted the UNU.RAN default generator is used (which _must
not_ be destroyed).
4 Handling distribution objects
*******************************
Objects of type ‘UNUR_DISTR’ are used for handling distributions. All data
about a distribution are stored in this object. UNU.RAN provides functions that
return instances of such objects for standard distributions (*note Standard
distributions: Stddist.). It is then possible to change these distribution
objects by various set calls. Moreover, it is possible to build a distribution
object entirely from scratch. For this purpose there exists
‘unur_distr__new’ calls that return an empty object of this type for each
object type (eg. univariate contiuous) which can be filled with the appropriate
set calls.
UNU.RAN distinguishes between several types of distributions, each of which
has its own sets of possible parameters (for details see the corresponding
sections):
− continuous univariate distributions
− continuous univariate order statistics
− continuous empirical univariate distributions
− continuous multivariate distributions
− continuous empirical multivariate distributions
− matrix distributions
− discrete univariate distributions
Notice that there are essential data about a distribution, eg. the PDF, a
list of (shape, scale, location) parameters for the distribution, and the domain
of (the possibly truncated) distribution. And there exist parameters that
are/can be derived from these, eg. the mode of the distribution or the area
below the given PDF (which need not be normalized for many methods). UNU.RAN
keeps track of parameters which are known. Thus if one of the essential
parameters is changed all derived parameters are marked as unknown and must be
set again if these are required for the chosen generation method. Additionally
to set calls there are calls for updating derived parameters for objects
provided by the UNU.RAN library of standard distributions (one for each
parameter to avoid computational overhead since not all parameters are required
for all generator methods).
All parameters of distribution objects can be read by corresponding get
calls.
Every generator object has its own copy of a distribution object which is
accessible by a ‘unur_get_distr’ call. Thus the parameter for this distribution
can be read. However, *never* extract the distribution object out of a
generator object and run one of the set calls on it to modify the distribution.
(How should the poor generator object know what has happend?) Instead there
exist calls for each of the generator methods that change particular parameters
of the internal copy of the distribution object.
How To Use
..........
UNU.RAN collects all data required for a particular generation method in a
_distribution object_. There are two ways to get an instance of a distributions
object:
1. Build a distribtion from scratch, by means of the corresponding
‘unur_distr__new’ call, where ‘’ is the type of the
distribution as listed in the below subsections.
2. Use the corresponding ‘unur_distr__new’ call to get prebuild
distribution from the UNU.RAN library of standard distributions. Here
‘’ is the name of the standard distribution in *note Standard
distributions: Stddist.
In either cases the corresponding ‘unur_distr__set_’ calls to
set the necessary parameters ‘’ (case 1), or change the values of the
standard distribution in case 2 (if this makes sense for you). In the latter
case ‘’ is the type to which the standard distribution belongs to. These
‘set’ calls return ‘UNUR_SUCCESS’ when the correspondig parameter has been set
successfully. Otherwise an error code is returned.
The parameters of a distribution are divided into _essential_ and _derived_
parameters.
Notice, that there are some restrictions in setting parameters to avoid
possible confusions. Changing essential parameters marks derived parameters as
‘unknown’. Some of the parameters cannot be changed any more when already set;
some parameters block each others. In such a case a new instance of a
distribution object has to be build.
Additionally ‘unur_distr__upd_’ calls can be used for updating
derived parameters for objects provided by the UNU.RAN library of standard
distributions.
All parameters of a distribution object get be read by means of
‘unur_distr__get_’ calls.
Every distribution object be identified by its ‘name’ which is a string of
arbitrary characters provided by the user. For standard distribution it is
automatically set to ‘’ in the corresponding ‘new’ call. It can be
changed to any other string.
4.1 Functions for all kinds of distribution objects
===================================================
The calls in this section can be applied to all distribution objects.
− Destroy ‘free’ an instance of a generator object.
− Ask for the ‘type’ of a generator object.
− Ask for the ‘dimension’ of a generator object.
− Deal with the ‘name’ (identifier string) of a generator object.
Function reference
------------------
-- Function: void unur_distr_free (UNUR_DISTR* DISTRIBUTION)
Destroy the DISTRIBUTION object.
-- Function: int unur_distr_set_name (UNUR_DISTR* DISTRIBUTION, const CHAR*
NAME)
-- Function: const char* unur_distr_get_name (const UNUR_DISTR* DISTRIBUTION)
Set and get NAME of DISTRIBUTION. The NAME can be an arbitrary character
string. It can be used to identify generator objects for the user. It is
used by UNU.RAN when printing information of the distribution object into a
log files.
-- Function: int unur_distr_get_dim (const UNUR_DISTR* DISTRIBUTION)
Get number of components of a random vector (its dimension) the
DISTRIBUTION.
For univariate distributions it returns dimension ‘1’.
For matrix distributions it returns the number of components (i.e., number
of rows times number of columns). When the respective numbers of rows and
columns are needed use ‘unur_distr_matr_get_dim’ instead.
-- Function: unsigned int unur_distr_get_type (const UNUR_DISTR* DISTRIBUTION)
Get type of DISTRIBUTION. Possible types are
‘UNUR_DISTR_CONT’
univariate continuous distribution
‘UNUR_DISTR_CEMP’
empirical continuous univariate distribution (i.e. a sample)
‘UNUR_DISTR_CVEC’
continuous mulitvariate distribution
‘UNUR_DISTR_CVEMP’
empirical continuous multivariate distribution (i.e. a vector sample)
‘UNUR_DISTR_DISCR’
discrete univariate distribution
‘UNUR_DISTR_MATR’
matrix distribution
Alternatively the ‘unur_distr_is_’ calls can be used.
-- Function: int unur_distr_is_cont (const UNUR_DISTR* DISTRIBUTION)
‘TRUE’ if DISTRIBUTION is a continuous univariate distribution.
-- Function: int unur_distr_is_cvec (const UNUR_DISTR* DISTRIBUTION)
‘TRUE’ if DISTRIBUTION is a continuous multivariate distribution.
-- Function: int unur_distr_is_cemp (const UNUR_DISTR* DISTRIBUTION)
‘TRUE’ if DISTRIBUTION is an empirical continuous univariate distribution,
i.e. a sample.
-- Function: int unur_distr_is_cvemp (const UNUR_DISTR* DISTRIBUTION)
‘TRUE’ if DISTRIBUTION is an empirical continuous multivariate
distribution.
-- Function: int unur_distr_is_discr (const UNUR_DISTR* DISTRIBUTION)
‘TRUE’ if DISTRIBUTION is a discrete univariate distribution.
-- Function: int unur_distr_is_matr (const UNUR_DISTR* DISTRIBUTION)
‘TRUE’ if DISTRIBUTION is a matrix distribution.
-- Function: int unur_distr_set_extobj (UNUR_DISTR* DISTRIBUTION, const VOID*
EXTOBJ)
Store a pointer to an external object. This might be usefull if the PDF,
PMF, CDF or other functions used to implement a particular distribution a
parameter set that cannot be stored as doubles (e.g. pointers to some
structure that holds information of the distribution).
*Important:* When UNU.RAN copies this distribution object into the
generator object, then the address EXTOBJ that this pointer contains is
simply copied. Thus the generator holds an address of a non-private
object! Once the generator object has been created any change in the
external object might effect the generator object.
*Warning:* External objects must be used with care. Once the generator
object has been created or the distribution object has been copied you
_must not_ destroy this external object.
-- Function: const void* unur_distr_get_extobj (const UNUR_DISTR* DISTRIBUTION)
Get the pointer to the external object.
_Important:_ Changing this object must be done with with extreme care.
4.2 Continuous univariate distributions
=======================================
The calls in this section can be applied to continuous univariate distributions.
− Create a ‘new’ instance of a continuous univariate distribution.
− Handle and evaluate distribution function (CDF, ‘cdf’), probability density
function (PDF, ‘pdf’) and the derivative of the density function (‘dpdf’).
The following is important:
. ‘pdf’ need not be normalized, i.e., any integrable nonnegative
function can be used.
. ‘dpdf’ must the derivate of the function provided as ‘pdf’.
. ‘cdf’ must be a distribution function, i.e. it must be monotonically
increasing with range [0,1].
. If ‘cdf’ and ‘pdf’ are used together for a pariticular generation
method, then ‘pdf’ must be the derivate of the ‘cdf’, i.e., it must be
normalized.
− Handle and evaluate the logarithm of the probability density function
(logPDF, ‘logpdf’) and the derivative of the logarithm of the density
function (‘dlogpdf’).
Some methods use the logarithm of the density if available.
− Set (and change) parameters (‘pdfparams’) and the area below the graph
(‘pdfarea’) of the given density.
− Set the ‘mode’ (or pole) of the distribution.
− Set the ‘center’ of the distribution. It is used by some generation
methods to adjust the parameters of the generation algorithms to gain
better performance. It can be seens as the location of the “central part”
of the distribution.
− Some generation methods require the hazard rate (‘hr’) of the distribution
instead of its ‘pdf’.
− Alternatively, ‘cdf’, ‘pdf’, ‘dpdf’, and ‘hr’ can be provided as ‘str’ings
instead of function pointers.
− Set the ‘domain’ of the distribution. Notice that the library also can
handle truncated distributions, i.e., distributions that are derived from
(standard) distributions by simply restricting its domain to a subset.
However, there is a subtle difference between changing the domain of a
distribution object by a ‘unur_distr_cont_set_domain’ call and changing the
(truncated) domain for an existing generator object. The domain of the
distribution object is used to create the generator object with hats,
squeezes, tables, etc. Whereas truncating the domain of an existing
generator object need not necessarily require a recomputation of these
data. Thus by a ‘unur__chg_truncated’ call (if available) the
sampling region is restricted to the subset of the domain of the given
distribution object. However, generation methods that require a recreation
of the generator object when the domain is changed have a
‘unur__chg_domain’ call instead. For these calls there are of
course no restrictions on the given domain (i.e., it is possible to
increase the domain of the distribution) (*note Methods::, for details).
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_cont_new (void)
Create a new (empty) object for univariate continuous distribution.
Essential parameters
....................
-- Function: int unur_distr_cont_set_pdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* PDF)
-- Function: int unur_distr_cont_set_dpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* DPDF)
-- Function: int unur_distr_cont_set_cdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* CDF)
-- Function: int unur_distr_cont_set_invcdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* INVCDF)
Set respective pointer to the probability density function (PDF), the
derivative of the probability density function (dPDF), the cumulative
distribution function (CDF), and the inverse CDF of the DISTRIBUTION. Each
of these function pointers must be of type ‘double funct(double x, const
UNUR_DISTR *distr)’.
Due to the fact that some of the methods do not require a normalized PDF
the following is important:
− The given CDF must be the cumulative distribution function of the
(non-truncated) distribution. If a distribution from the UNU.RAN
library of standard distributions (*note Standard distributions:
Stddist.) is truncated, there is no need to change the CDF.
− If both the CDF and the PDF are used (for a method or for order
statistics), the PDF must be the derivative of the CDF. If a truncated
distribution for one of the standard distributions from the UNU.RAN
library of standard distributions is used, there is no need to change
the PDF.
− If the area below the PDF is required for a given distribution it must
be given by the ‘unur_distr_cont_set_pdfarea’ call. For a truncated
distribution this must be of course the integral of the PDF in the
given truncated domain. For distributions from the UNU.RAN library of
standard distributions this is done automatically by the
‘unur_distr_cont_upd_pdfarea’ call.
It is important to note that all these functions must return a result for
all values of X. Eg., if the domain of a given PDF is the interval [-1,1],
then the given function must return ‘0.0’ for all points outside this
interval. In case of an overflow the PDF should return ‘UNUR_INFINITY’.
It is not possible to change such a function. Once the PDF or CDF is set
it cannot be overwritten. This also holds when the logPDF is given or when
the PDF is given by the ‘unur_distr_cont_set_pdfstr’ or
‘unur_distr_cont_set_logpdfstr’ call. A new distribution object has to be
used instead.
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_pdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_dpdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_cdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_invcdf (const UNUR_DISTR*
DISTRIBUTION)
Get the respective pointer to the PDF, the derivative of the PDF, the CDF,
and the inverse CDF of the DISTRIBUTION. The pointer is of type ‘double
funct(double x, const UNUR_DISTR *distr)’. If the corresponding function
is not available for the distribution, the ‘NULL’ pointer is returned.
-- Function: double unur_distr_cont_eval_pdf (double X, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cont_eval_dpdf (double X, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cont_eval_cdf (double X, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cont_eval_invcdf (double U, const UNUR_DISTR*
DISTRIBUTION)
Evaluate the PDF, derivative of the PDF, the CDF, and the inverse CDF at X
and U,respectively. Notice that DISTRIBUTION must not be the ‘NULL’
pointer. If the corresponding function is not available for the
distribution, ‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_DATA’.
_IMPORTANT:_ In the case of a truncated standard distribution these calls
always return the respective values of the _untruncated_ distribution!
-- Function: int unur_distr_cont_set_logpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* LOGPDF)
-- Function: int unur_distr_cont_set_dlogpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* DLOGPDF)
-- Function: int unur_distr_cont_set_logcdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* LOGCDF)
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_logpdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_dlogpdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_logcdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cont_eval_logpdf (double X, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cont_eval_dlogpdf (double X, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cont_eval_logcdf (double X, const UNUR_DISTR*
DISTRIBUTION)
Analogous calls for the logarithm of the density distribution functions.
-- Function: int unur_distr_cont_set_pdfstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* PDFSTR)
This function provides an alternative way to set a PDF and its derivative
of the DISTRIBUTION. PDFSTR is a character string that contains the
formula for the PDF, see *note Function String: StringFunct, for details.
The derivative of the given PDF is computed automatically. See also the
remarks for the ‘unur_distr_cont_set_pdf’ call.
It is not possible to call this funtion twice or to call this function
after a ‘unur_distr_cont_set_pdf’ call.
-- Function: int unur_distr_cont_set_cdfstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* CDFSTR)
This function provides an alternative way to set a CDF; analogously to the
‘unur_distr_cont_set_pdfstr’ call. The PDF and its derivative of the given
CDF are computed automatically.
-- Function: char* unur_distr_cont_get_pdfstr (const UNUR_DISTR* DISTRIBUTION)
-- Function: char* unur_distr_cont_get_dpdfstr (const UNUR_DISTR* DISTRIBUTION)
-- Function: char* unur_distr_cont_get_cdfstr (const UNUR_DISTR* DISTRIBUTION)
Get pointer to respective string for PDF, derivate of PDF, and CDF of
DISTRIBUTION that is given as string (instead of a function pointer). This
call allocates memory to produce this string. It should be freed when it
is not used any more.
-- Function: int unur_distr_cont_set_pdfparams (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* PARAMS, int N_PARAMS)
Sets array of parameters for DISTRIBUTION. There is an upper limit for the
number of parameters ‘n_params’. It is given by the macro
‘UNUR_DISTR_MAXPARAMS’ in ‘unuran_config.h’. (It is set to 5 by default
but can be changed to any appropriate nonnegative number.) If N_PARAMS is
negative or exceeds this limit no parameters are copied into the
distribution object and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_NPARAMS’.
For standard distributions from the UNU.RAN library the parameters are
checked. Moreover, the domain is updated automatically unless it has been
changed before by a ‘unur_distr_cont_set_domain’ call. If the given
parameters are invalid for the standard distribution, then no parameters
are set and an error code is returned. Notice, that the given parameter
list for such a distribution is handled in the same way as in the
corresponding ‘new’ calls, i.e. optional parameters for the PDF that are
not present in the given list are (re-)set to their default values.
*Important:* If the parameters of a distribution from the UNU.RAN library
of standard distributions (*note Standard distributions: Stddist.) are
changed, then neither its mode nor the normalization constant are updated.
Please use the respective calls ‘unur_distr_cont_upd_mode’ and
‘unur_distr_cont_upd_pdfarea’. Moreover, if the domain has been changed by
a ‘unur_distr_cont_set_domain’ it is not automatically updated, either.
Updating the normalization constant is in particular very important, when
the CDF of the distribution is used.
-- Function: int unur_distr_cont_get_pdfparams (const UNUR_DISTR* DISTRIBUTION,
const DOUBLE** PARAMS)
Get number of parameters of the PDF and set pointer PARAMS to array of
parameters. If no parameters are stored in the object, an error code is
returned and ‘params’ is set to ‘NULL’.
_Important:_ Do *not* change the entries in PARAMS!
-- Function: int unur_distr_cont_set_pdfparams_vec (UNUR_DISTR* DISTRIBUTION,
int PAR, const DOUBLE* PARAM_VEC, int N_PARAM_VEC)
This function provides an interface for additional vector parameters for a
continuous DISTRIBUTION.
It sets the parameter with number PAR. PAR indicates directly which of the
parameters is set and must be a number between ‘0’ and
‘UNUR_DISTR_MAXPARAMS’-1 (the upper limit of possible parameters defined in
‘unuran_config.h’; it is set to 5 but can be changed to any appropriate
nonnegative number.)
The entries of a this parameter are given by the array PARAM_VEC of size
N_PARAM_VEC.
If PARAM_VEC is ‘NULL’ then the corresponding entry is cleared.
If an error occurs no parameters are copied into the parameter object
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_DATA’.
-- Function: int unur_distr_cont_get_pdfparams_vec (const UNUR_DISTR*
DISTRIBUTION, int PAR, const DOUBLE** PARAM_VECS)
Get parameter of the PDF with number PAR. The pointer to the parameter
array is stored in PARAM_VECS, its size is returned by the function. If
the requested parameter is not set, then an error code is returned and
‘params’ is set to ‘NULL’.
_Important:_ Do *not* change the entries in PARAM_VECS!
-- Function: int unur_distr_cont_set_logpdfstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* LOGPDFSTR)
-- Function: char* unur_distr_cont_get_logpdfstr (const UNUR_DISTR*
DISTRIBUTION)
-- Function: char* unur_distr_cont_get_dlogpdfstr (const UNUR_DISTR*
DISTRIBUTION)
-- Function: int unur_distr_cont_set_logcdfstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* LOGCDFSTR)
-- Function: char* unur_distr_cont_get_logcdfstr (const UNUR_DISTR*
DISTRIBUTION)
Analogous calls for the logarithm of the density and distribution
functions.
-- Function: int unur_distr_cont_set_domain (UNUR_DISTR* DISTRIBUTION, double
LEFT, double RIGHT)
Set the left and right borders of the domain of the distribution. This can
also be used to truncate an existing distribution. For setting the
boundary to +/- infinity use ‘+/- UNUR_INFINITY’. If RIGHT is not strictly
greater than LEFT no domain is set and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_SET’.
_Important:_ For some technical reasons it is assumed that the density is
unimodal and thus monotone on either side of the mode! This is used in the
case when the given mode is outside of the original domain. Then the mode
is set to the corresponding boundary of the new domain. If this result is
not the desired it must be changed by using a ‘unur_distr_cont_set_mode’
call (or a ‘unur_distr_cont_upd_mode’ call). The same holds for the center
of the distribution.
-- Function: int unur_distr_cont_get_domain (const UNUR_DISTR* DISTRIBUTION,
double* LEFT, double* RIGHT)
Get the left and right borders of the domain of the distribution. If the
domain is not set ‘+/- UNUR_INFINITY’ is assumed and returned. No error is
reported in this case.
-- Function: int unur_distr_cont_get_truncated (const UNUR_DISTR* DISTRIBUTION,
double* LEFT, double* RIGHT)
Get the left and right borders of the (truncated) domain of the
distribution. For non-truncated distribution this call is equivalent to
the ‘unur_distr_cont_get_domain’ call.
This call is only useful in connection with a ‘unur_get_distr’ call to get
the boundaries of the sampling region of a generator object.
-- Function: int unur_distr_cont_set_hr (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CONT* HAZARD)
Set pointer to the hazard rate (HR) of the DISTRIBUTION.
The _hazard rate_ (or failure rate) is a mathematical way of describing
aging. If the lifetime X is a random variable with density f(x) and CDF
F(x) the hazard rate h(x) is defined as h(x) = f(x) / (1-F(x)). In other
words, h(x) represents the (conditional) rate of failure of a unit that has
survived up to time x with probability 1-F(x). The key distribution is the
exponential distribution as it has constant hazard rate of value 1. Hazard
rates tending to infinity describe distributions with sub-exponential tails
whereas distributions with hazard rates tending to zero have heavier tails
than the exponential distribution.
It is important to note that all these functions must return a result for
all floats x. In case of an overflow the PDF should return
‘UNUR_INFINITY’.
*Important*: Do not simply use f(x) / (1-F(x)), since this is numerically
very unstable and results in numerical noise if F(x) is (very) close to 1.
Moreover, if the density f(x) is known a generation method that uses the
density is more appropriate.
It is not possible to change such a function. Once the HR is set it cannot
be overwritten. This also holds when the HR is given by the
‘unur_distr_cont_set_hrstr’ call. A new distribution object has to be used
instead.
-- Function: UNUR_FUNCT_CONT* unur_distr_cont_get_hr (const UNUR_DISTR*
DISTRIBUTION)
Get the pointer to the hazard rate of the DISTRIBUTION. The pointer is of
type ‘double funct(double x, const UNUR_DISTR *distr)’. If the
corresponding function is not available for the distribution, the ‘NULL’
pointer is returned.
-- Function: double unur_distr_cont_eval_hr (double X, const UNUR_DISTR*
DISTRIBUTION)
Evaluate the hazard rate at X. Notice that DISTRIBUTION must not be the
‘NULL’ pointer. If the corresponding function is not available for the
distribution, ‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_DATA’.
-- Function: int unur_distr_cont_set_hrstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* HRSTR)
This function provides an alternative way to set a hazard rate and its
derivative of the DISTRIBUTION. HRSTR is a character string that contains
the formula for the HR, see *note Function String: StringFunct, for
details. See also the remarks for the ‘unur_distr_cont_set_hr’ call.
It is not possible to call this funtion twice or to call this function
after a ‘unur_distr_cont_set_hr’ call.
-- Function: char* unur_distr_cont_get_hrstr (const UNUR_DISTR* DISTRIBUTION)
Get pointer to string for HR of DISTRIBUTION that is given via the string
interface. This call allocates memory to produce this string. It should
be freed when it is not used any more.
Derived parameters
..................
The following paramters *must* be set whenever one of the essential parameters
has been set or changed (and the parameter is required for the chosen method).
-- Function: int unur_distr_cont_set_mode (UNUR_DISTR* DISTRIBUTION, double
MODE)
Set mode of DISTRIBUTION. The MODE must be contained in the domain of
DISTRIBUTION. Otherwise the mode is not set and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_SET’. For distributions with unbounded density, this call
is used to set the pole of the PDF. Notice that the PDF should then return
‘UNUR_INFINITY’ at the pole. Notice that the mode is adjusted when the
domain is set, see the remark for the ‘unur_distr_cont_set_domain’ call.
-- Function: int unur_distr_cont_upd_mode (UNUR_DISTR* DISTRIBUTION)
Recompute the mode of the DISTRIBUTION. This call works properly for
distribution objects from the UNU.RAN library of standard distributions
when the corresponding function is available. Otherwise a (slow) numerical
mode finder based on Brent’s algorithm is used. If it failes ‘unur_errno’
is set to ‘UNUR_ERR_DISTR_DATA’.
-- Function: double unur_distr_cont_get_mode (UNUR_DISTR* DISTRIBUTION)
Get mode of DISTRIBUTION. If the mode is not marked as known,
‘unur_distr_cont_upd_mode’ is called to compute the mode. If this is not
successful ‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_GET’. (There is no difference between the case where no
routine for computing the mode is available and the case where no mode
exists for the distribution at all.)
-- Function: int unur_distr_cont_set_center (UNUR_DISTR* DISTRIBUTION, double
CENTER)
Set center of the DISTRIBUTION. The center is used by some methods to
shift the distribution in order to decrease numerical round-off error. If
not given explicitly a default is used.
_Important:_ This call does not check whether the center is contained in
the given domain.
Default: The mode, if set by a ‘unur_distr_cont_set_mode’ or
‘unur_distr_cont_upd_mode’ call; otherwise ‘0’.
-- Function: double unur_distr_cont_get_center (const UNUR_DISTR* DISTRIBUTION)
Get center of the DISTRIBUTION. It always returns some point as there
always exists a default for the center, see ‘unur_distr_cont_set_center’.
-- Function: int unur_distr_cont_set_pdfarea (UNUR_DISTR* DISTRIBUTION, double
AREA)
Set the area below the PDF. If ‘area’ is non-positive, no area is set and
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_SET’.
For a distribution object created by the UNU.RAN library of standard
distributions you always should use the ‘unur_distr_cont_upd_pdfarea’.
Otherwise there might be ambiguous side-effects.
-- Function: int unur_distr_cont_upd_pdfarea (UNUR_DISTR* DISTRIBUTION)
Recompute the area below the PDF of the distribution. It only works for
distribution objects from the UNU.RAN library of standard distributions
when the corresponding function is available. Otherwise ‘unur_errno’ is
set to ‘UNUR_ERR_DISTR_DATA’.
This call also sets the normalization constant such that the given PDF is
the derivative of a given CDF, i.e. the area is 1. However, for truncated
distributions the area is smaller than 1.
The call does not work for distributions from the UNU.RAN library of
standard distributions with truncated domain when the CDF is not available.
-- Function: double unur_distr_cont_get_pdfarea (UNUR_DISTR* DISTRIBUTION)
Get the area below the PDF of the distribution. If this area is not known,
‘unur_distr_cont_upd_pdfarea’ is called to compute it. If this is not
successful ‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_GET’.
4.3 Continuous univariate order statistics
==========================================
These are special cases of a continuous univariate distributions and thus they
have most of these parameters (with the exception that functions cannot be
changed). Additionally,
− there is a call to extract the underlying distribution,
− and a call to handle the ‘rank’ of the order statistics.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_corder_new (const UNUR_DISTR* DISTRIBUTION,
int N, int K)
Create an object for order statistics of sample size N and rank K.
DISTRIBUTION must be a pointer to a univariate continuous distribution.
The resulting generator object is of the same type as of a
‘unur_distr_cont_new’ call. (However, it cannot be used to make an order
statistics out of an order statistics.)
To have a PDF for the order statistics, the given distribution object must
contain a CDF and a PDF. Moreover, it is assumed that the given PDF is the
derivative of the given CDF. Otherwise the area below the PDF of the order
statistics is not computed correctly.
_Important:_ There is no warning when the computed area below the PDF of
the order statistics is wrong.
-- Function: const UNUR_DISTR* unur_distr_corder_get_distribution (const
UNUR_DISTR* DISTRIBUTION)
Get pointer to distribution object for underlying distribution.
Essential parameters
....................
-- Function: int unur_distr_corder_set_rank (UNUR_DISTR* DISTRIBUTION, int N,
int K)
Change sample size N and rank K of order statistics. In case of invalid
data, no parameters are changed. The area below the PDF can be set to that
of the underlying distribution by a ‘unur_distr_corder_upd_pdfarea’ call.
-- Function: int unur_distr_corder_get_rank (const UNUR_DISTR* DISTRIBUTION,
int* N, int* K)
Get sample size N and rank K of order statistics. In case of error an
error code is returned.
Additionally most of the set and get calls for continuous univariate
distributions work. The most important exceptions are that the PDF and CDF
cannot be changed and ‘unur_distr_cont_upd_mode’ uses in any way a (slow)
numerical method that might fail.
-- Function: UNUR_FUNCT_CONT* unur_distr_corder_get_pdf (UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_corder_get_dpdf (UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_FUNCT_CONT* unur_distr_corder_get_cdf (UNUR_DISTR*
DISTRIBUTION)
Get the respective pointer to the PDF, the derivative of the PDF and the
CDF of the distribution, respectively. The pointer is of type ‘double
funct(double x, UNUR_DISTR *distr)’. If the corresponding function is not
available for the distribution, the ‘NULL’ pointer is returned. See also
‘unur_distr_cont_get_pdf’. (Macro)
-- Function: double unur_distr_corder_eval_pdf (double X, UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_corder_eval_dpdf (double X, UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_corder_eval_cdf (double X, UNUR_DISTR*
DISTRIBUTION)
Evaluate the PDF, derivative of the PDF. and the CDF, respectively, at X.
Notice that DISTRIBUTION must not be the ‘NULL’ pointer. If the
corresponding function is not available for the distribution,
‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_DATA’. See also ‘unur_distr_cont_eval_pdf’. (Macro)
_IMPORTANT:_ In the case of a truncated standard distribution these calls
always return the respective values of the _untruncated_ distribution!
-- Function: int unur_distr_corder_set_pdfparams (UNUR_DISTR* DISTRIBUTION,
double* PARAMS, int N_PARAMS)
Set array of parameters for underlying distribution. See
‘unur_distr_cont_set_pdfparams’ for details. (Macro)
-- Function: int unur_distr_corder_get_pdfparams (UNUR_DISTR* DISTRIBUTION,
double** PARAMS)
Get number of parameters of the PDF of the underlying distribution and set
pointer PARAMS to array of parameters. See ‘unur_distr_cont_get_pdfparams’
for details. (Macro)
-- Function: int unur_distr_corder_set_domain (UNUR_DISTR* DISTRIBUTION, double
LEFT, double RIGHT)
Set the left and right borders of the domain of the distribution. See
‘unur_distr_cont_set_domain’ for details. (Macro)
-- Function: int unur_distr_corder_get_domain (UNUR_DISTR* DISTRIBUTION,
double* LEFT, double* RIGHT)
Get the left and right borders of the domain of the distribution. See
‘unur_distr_cont_get_domain’ for details. (Macro)
-- Function: int unur_distr_corder_get_truncated (UNUR_DISTR* DISTRIBUTION,
double* LEFT, double* RIGHT)
Get the left and right borders of the (truncated) domain of the
distribution. See ‘unur_distr_cont_get_truncated’ for details. (Macro)
Derived parameters
..................
The following paramters *must* be set whenever one of the essential parameters
has been set or changed (and the parameter is required for the chosen method).
-- Function: int unur_distr_corder_set_mode (UNUR_DISTR* DISTRIBUTION, double
MODE)
Set mode of distribution. See also ‘unur_distr_corder_set_mode’. (Macro)
-- Function: double unur_distr_corder_upd_mode (UNUR_DISTR* DISTRIBUTION)
Recompute the mode of the distribution numerically. Notice that this
routine is slow and might not work properly in every case. See also
‘unur_distr_cont_upd_mode’ for further details. (Macro)
-- Function: double unur_distr_corder_get_mode (UNUR_DISTR* DISTRIBUTION)
Get mode of distribution. See ‘unur_distr_cont_get_mode’ for details.
(Macro)
-- Function: int unur_distr_corder_set_pdfarea (UNUR_DISTR* DISTRIBUTION,
double AREA)
Set the area below the PDF. See ‘unur_distr_cont_set_pdfarea’ for details.
(Macro)
-- Function: double unur_distr_corder_upd_pdfarea (UNUR_DISTR* DISTRIBUTION)
Recompute the area below the PDF of the distribution. It only works for
order statistics for distribution objects from the UNU.RAN library of
standard distributions when the corresponding function is available.
‘unur_distr_cont_upd_pdfarea’ assumes that the PDF of the underlying
distribution is normalized, i.e. it is the derivative of its CDF.
Otherwise the computed area is wrong and there is *no* warning about this
failure. See ‘unur_distr_cont_upd_pdfarea’ for further details. (Macro)
-- Function: double unur_distr_corder_get_pdfarea (UNUR_DISTR* DISTRIBUTION)
Get the area below the PDF of the distribution. See
‘unur_distr_cont_get_pdfarea’ for details. (Macro)
4.4 Continuous empirical univariate distributions
=================================================
Empirical univariate distributions are derived from observed data. There are
two ways to create such a generator object:
1. By a list of _raw data_ by means of a ‘unur_distr_cemp_set_data’ call.
2. By a _histogram_ (i.e. preprocessed data) by means of a
‘unur_distr_cemp_set_hist’ call.
How these data are used to sample from the empirical distribution depends
from the chosen generation method.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_cemp_new (void)
Create a new (empty) object for empirical univariate continuous
distribution.
Essential parameters
....................
-- Function: int unur_distr_cemp_set_data (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* SAMPLE, int N_SAMPLE)
Set observed sample for empirical distribution.
-- Function: int unur_distr_cemp_read_data (UNUR_DISTR* DISTRIBUTION, const
CHAR* FILENAME)
Read data from file ‘filename’. It reads the first number from each line.
Numbers are parsed by means of the C standard routine ‘strtod’. Lines that
do not start with ‘+’, ‘-’, ‘.’, or a digit are ignored. (Beware of lines
starting with a blank!)
In case of an error (file cannot be opened, invalid string for double in
line) no data are copied into the distribution object and an error code is
returned.
-- Function: int unur_distr_cemp_get_data (const UNUR_DISTR* DISTRIBUTION,
const DOUBLE** SAMPLE)
Get number of samples and set pointer SAMPLE to array of observations. If
no sample has been given, an error code is returned and ‘sample’ is set to
‘NULL’.
_Important:_ Do *not* change the entries in SAMPLE!
-- Function: int unur_distr_cemp_set_hist (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* PROB, int N_PROB, double XMIN, double XMAX)
Set a histogram with bins of equal width. PROB is an array of length
N_PROB that contains the probabilities for the bins (in ascending order).
XMIN and XMAX give the lower and upper bound of the histogram,
respectively. The bins are assumed to have equal width.
_Remark:_ This is shortcut for calling ‘unur_distr_cemp_set_hist_prob’ and
‘unur_distr_cemp_set_hist_domain’. _Notice:_ All sampling methods either
use raw data or histogram. It is possible to set both types of data;
however, it is not checked whether the given histogran corresponds to
possibly given raw data.
-- Function: int unur_distr_cemp_set_hist_prob (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* PROB, int N_PROB)
Set probabilities of a histogram with N_PROB bins. Hence PROB must be an
array of length N_PROB that contains the probabilities for the bins in
ascending order. It is important also to set the location of the bins
either with a ‘unur_distr_cemp_set_hist_domain’ for bins of equal width or
‘unur_distr_cemp_set_hist_bins’ when the bins have different width.
_Notice:_ All sampling methods either use raw data or histogram. It is
possible to set both types of data; however, it is not checked whether the
given histogram corresponds to possibly given raw data.
-- Function: int unur_distr_cemp_set_hist_domain (UNUR_DISTR* DISTRIBUTION,
double XMIN, double XMAX)
Set a domain of a histogram with bins of equal width. XMIN and XMAX give
the lower and upper bound of the histogram, respectively.
-- Function: int unur_distr_cemp_set_hist_bins (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* BINS, int N_BINS)
Set location of bins of a histogram with N_BINS bins. Hence BINS must be
an array of length N_BINS. The domain of the DISTRIBUTION is automatically
set by this call and overrides any calls to
‘unur_distr_cemp_set_hist_domain’. _Important:_ The probabilities of the
bins of the DISTRIBUTION must be already be set by a
‘unur_distr_cemp_set_hist_prob’ (or a ‘unur_distr_cemp_set_hist’ call) and
the value of N_BINS must equal N_PROB‘+1’ from the corresponding value of
the respective call.
4.5 Continuous multivariate distributions
=========================================
The following calls handle multivariate distributions. However, the
requirements of particular generation methods is not as unique as for univariate
distributions. Moreover, random vector generation methods are still under
development. The below functions are a first attempt to handle this situation.
Notice that some of the parameters – when given carelessly – might contradict
to others. For example: Some methods require the marginal distribution and some
methods need a standardized form of the marginal distributions, where the actual
mean and variance is stored in the mean vector and the covariance matrix,
respectively.
We also have to mention that some methods might abuse some of the parameters.
Please read the discription of the chosen sampling method carfully.
The following kind of calls exists:
− Create a ‘new’ instance of a continuous multivariate distribution;
− Handle and evaluate probability density function (PDF, ‘pdf’) and the
gradient of the density function (‘dpdf’). The following is important:
. ‘pdf’ need not be normalized, i.e., any integrable nonnegative
function can be used.
. ‘dpdf’ must the derivate of the function provided as ‘pdf’.
− Handle and evaluate the logarithm of the probability density function
(logPDF, ‘logpdf’) and the gradient of the logarithm of the density
function (‘dlogpdf’).
Some methods use the logarithm of the density if available.
− Set (and change) parameters (‘pdfparams’) and the volume below the graph
(‘pdfvol’) of the given density.
− Set ‘mode’ and ‘mean’ of the distribution.
− Set the ‘center’ of the distribution. It is used by some generation
methods to adjust the parameters of the generation algorithms to gain
better performance. It can be seens as the location of the “central part”
of the distribution.
− Handle the ‘covar’iance matrix of the distribution and its ‘cholesky’ and
‘inv’verse matrices.
− Set the ‘rankcorr’elation matrix of the distribution.
− Deal with ‘marginal’ distributions.
− Set domain of the distribution.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_cvec_new (int DIM)
Create a new (empty) object for multivariate continuous distribution. DIM
is the number of components of the random vector (i.e. its dimension). It
is also possible to use dimension 1. Notice, however, that this is treated
as a distribution of random vectors with only one component and not as a
distribution of real numbers. For the latter ‘unur_distr_cont_new’ should
be used to create an object for a univariate distribution.
Essential parameters
....................
-- Function: int unur_distr_cvec_set_pdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CVEC* PDF)
Set respective pointer to the PDF of the DISTRIBUTION. This function must
be of type ‘double funct(const double *x, UNUR_DISTR *distr)’, where X must
be a pointer to a double array of appropriate size (i.e. of the same size
as given to the ‘unur_distr_cvec_new’ call).
It is not necessary that the given PDF is normalized, i.e. the integral
need not be 1. Nevertheless the volume below the PDF can be provided by a
‘unur_distr_cvec_set_pdfvol’ call.
It is not possible to change the PDF. Once the PDF is set it cannot be
overwritten. This also holds when the logPDF is given. A new distribution
object has to be used instead.
-- Function: int unur_distr_cvec_set_dpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_VFUNCT_CVEC* DPDF)
Set pointer to the gradient of the PDF. The type of this function must be
‘int funct(double *result, const double *x, UNUR_DISTR *distr)’, where
RESULT and X must be pointers to double arrays of appropriate size (i.e.
of the same size as given to the ‘unur_distr_cvec_new’ call). The gradient
of the PDF is stored in the array RESULT. The function should return an
error code in case of an error and must return ‘UNUR_SUCCESS’ otherwise.
The given function must be the gradient of the function given by a
‘unur_distr_cvec_set_pdf’ call.
It is not possible to change the gradient of the PDF. Once the dPDF is set
it cannot be overwritten. This also holds when the gradient of the logPDF
is given. A new distribution object has to be used instead.
-- Function: int unur_distr_cvec_set_pdpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCTD_CVEC* PDPDF)
Set pointer to partial derivatives of the PDF. The type of this function
must be ‘double funct(const double *x, int coord, UNUR_DISTR *distr)’,
where X must be a pointer to a double array of appropriate size (i.e. of
the same size as given to the ‘unur_distr_cvec_new’ call). COORD is the
coordinate for which the partial dervative should be computed.
Notice that COORD must be an integer from {0,...,dim-1}.
It is not possible to change the partial derivative of the PDF. Once the
pdPDF is set it cannot be overwritten. This also holds when the partial
derivative of the logPDF is given. A new distribution object has to be
used instead.
-- Function: UNUR_FUNCT_CVEC* unur_distr_cvec_get_pdf (const UNUR_DISTR*
DISTRIBUTION)
Get the pointer to the PDF of the DISTRIBUTION. The pointer is of type
‘double funct(const double *x, UNUR_DISTR *distr)’. If the corresponding
function is not available for the DISTRIBUTION, the ‘NULL’ pointer is
returned.
-- Function: UNUR_VFUNCT_CVEC* unur_distr_cvec_get_dpdf (const UNUR_DISTR*
DISTRIBUTION)
Get the pointer to the gradient of the PDF of the DISTRIBUTION. The
pointer is of type ‘int double funct(double *result, const double *x,
UNUR_DISTR *distr)’. If the corresponding function is not available for
the DISTRIBUTION, the ‘NULL’ pointer is returned.
-- Function: double unur_distr_cvec_eval_pdf (const DOUBLE* X, UNUR_DISTR*
DISTRIBUTION)
Evaluate the PDF of the DISTRIBUTION at X. X must be a pointer to a double
array of appropriate size (i.e. of the same size as given to the
‘unur_distr_cvec_new’ call) that contains the vector for which the function
has to be evaluated.
Notice that DISTRIBUTION must not be the ‘NULL’ pointer. If the
corresponding function is not available for the DISTRIBUTION,
‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_DATA’.
-- Function: int unur_distr_cvec_eval_dpdf (double* RESULT, const DOUBLE* X,
UNUR_DISTR* DISTRIBUTION)
Evaluate the gradient of the PDF of the DISTRIBUTION at X. The result is
stored in the double array RESULT. Both RESULT and X must be pointer to
double arrays of appropriate size (i.e. of the same size as given to the
‘unur_distr_cvec_new’ call).
Notice that DISTRIBUTION must not be the ‘NULL’ pointer. If the
corresponding function is not available for the DISTRIBUTION, an error code
is returned and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_DATA’ (RESULT is
left unmodified).
-- Function: double unur_distr_cvec_eval_pdpdf (const DOUBLE* X, int COORD,
UNUR_DISTR* DISTRIBUTION)
Evaluate the partial derivative of the PDF of the DISTRIBUTION at X for the
coordinate COORD. X must be a pointer to a double array of appropriate
size (i.e. of the same size as given to the ‘unur_distr_cvec_new’ call)
that contains the vector for which the function has to be evaluated.
Notice that COORD must be an integer from {0,...,dim-1}.
Notice that DISTRIBUTION must not be the ‘NULL’ pointer. If the
corresponding function is not available for the DISTRIBUTION,
‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_DATA’.
-- Function: int unur_distr_cvec_set_logpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_CVEC* LOGPDF)
-- Function: int unur_distr_cvec_set_dlogpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_VFUNCT_CVEC* DLOGPDF)
-- Function: int unur_distr_cvec_set_pdlogpdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCTD_CVEC* PDLOGPDF)
-- Function: UNUR_FUNCT_CVEC* unur_distr_cvec_get_logpdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: UNUR_VFUNCT_CVEC* unur_distr_cvec_get_dlogpdf (const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_cvec_eval_logpdf (const DOUBLE* X, UNUR_DISTR*
DISTRIBUTION)
-- Function: int unur_distr_cvec_eval_dlogpdf (double* RESULT, const DOUBLE* X,
UNUR_DISTR* DISTRIBUTION)
-- Function: double unur_distr_cvec_eval_pdlogpdf (const DOUBLE* X, int COORD,
UNUR_DISTR* DISTRIBUTION)
Analogous calls for the logarithm of the density function.
-- Function: int unur_distr_cvec_set_mean (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* MEAN)
Set mean vector for multivariate DISTRIBUTION. MEAN must be a pointer to
an array of size ‘dim’, where ‘dim’ is the dimension returned by
‘unur_distr_get_dim’. A ‘NULL’ pointer for MEAN is interpreted as the zero
vector (0,...,0).
*Important:* If the parameters of a distribution from the UNU.RAN library
of standard distributions (*note Standard distributions: Stddist.) are
changed, then neither its mode nor the normalization constant are updated.
Please use the respective calls ‘unur_distr_cvec_upd_mode’ and
‘unur_distr_cvec_upd_pdfvol’.
-- Function: const double* unur_distr_cvec_get_mean (const UNUR_DISTR*
DISTRIBUTION)
Get the mean vector of the DISTRIBUTION. The function returns a pointer to
an array of size ‘dim’. If the mean vector is not marked as known the
‘NULL’ pointer is returned and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_GET’.
_Important:_ Do *not* modify the array that holds the mean vector!
-- Function: int unur_distr_cvec_set_covar (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* COVAR)
Set covariance matrix for multivariate DISTRIBUTION. COVAR must be a
pointer to an array of size ‘dim’ x ‘dim’, where ‘dim’ is the dimension
returned by ‘unur_distr_get_dim’. The rows of the matrix have to be stored
consecutively in this array.
COVAR must be a variance-covariance matrix of the DISTRIBUTION, i.e. it
must be symmetric and positive definit and its diagonal entries (i.e. the
variance of the components of the random vector) must be strictly positive.
The Cholesky factor is computed (and stored) to verify the positive
definiteness condition. Notice that the inverse of the given covariance
matrix is automatically computed when it is requested by some routine.
Notice that the computation of this inverse matrix is unstable in case of
high correlations and/or high dimensions. Thus it might fail and methods
that require this inverse cannot be used. As an alternative the inverse of
the covariance matrix can be directly set by a
‘unur_distr_cvec_set_covar_inv’ call.
A ‘NULL’ pointer for COVAR is interpreted as the identity matrix.
_Important:_ This entry is abused in some methods which do not require the
covariance matrix. It is then used to perform some transformation to
obtain better performance.
_Important:_ In case of an error (e.g. because COVAR is not a valid
covariance matrix) an error code is returned. Moreover, the covariance
matrix is not set and is marked as unknown. A previously set covariance
matrix is then no longer available.
*Important:* If the parameters of a distribution from the UNU.RAN library
of standard distributions (*note Standard distributions: Stddist.) are
changed, then neither its mode nor the normalization constant are updated.
Please use the respective calls ‘unur_distr_cvec_upd_mode’ and
‘unur_distr_cvec_upd_pdfvol’. _Remark:_ UNU.RAN does not check whether the
an eventually set covariance matrix and a rank-correlation matrix do not
contradict each other.
-- Function: int unur_distr_cvec_set_covar_inv (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* COVAR_INV)
Set inverse of the covariance matrix for multivariate DISTRIBUTION.
COVAR_INV must be a pointer to an array of size ‘dim’ x ‘dim’, where ‘dim’
is the dimension returned by ‘unur_distr_get_dim’. The rows of the matrix
have to be stored consecutively in this array.
COVAR_INV must be symmetric and positive definit. Only the symmetry of the
matrix is checked.
A ‘NULL’ pointer for COVAR_INV is interpreted as the identity matrix.
_Important:_ In case of an error (because COVAR_INV is not symetric) an
error code is returned. Moreover, the inverse of the covariance matrix is
not set and is marked as unknown. A previously set inverse matrix is then
no longer available.
_Remark:_ UNU.RAN does not check whether the given matrix is positive
definit.
_Remark:_ UNU.RAN does not check whether the matrix COVAR_INV is the
inverse of the eventually set covariance matrix.
-- Function: const double* unur_distr_cvec_get_covar (const UNUR_DISTR*
DISTRIBUTION)
-- Function: const double* unur_distr_cvec_get_cholesky (const UNUR_DISTR*
DISTRIBUTION)
-- Function: const double* unur_distr_cvec_get_covar_inv (UNUR_DISTR*
DISTRIBUTION)
Get covariance matrix of DISTRIBUTION, its Cholesky factor, and its
inverse, respectively. The function returns a pointer to an array of size
‘dim’ x ‘dim’. The rows of the matrix are stored consecutively in this
array. If the requested matrix is not marked as known the ‘NULL’ pointer
is returned and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_GET’.
_Important:_ Do *not* modify the array that holds the covariance matrix!
_Remark:_ The inverse of the covariance matrix is computed if it is not
already stored.
-- Function: int unur_distr_cvec_set_rankcorr (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* RANKCORR)
Set rank-correlation matrix (Spearman’s correlation) for multivariate
DISTRIBUTION. RANKCORR must be a pointer to an array of size ‘dim’ x
‘dim’, where ‘dim’ is the dimension returned by ‘unur_distr_get_dim’. The
rows of the matrix have to be stored consecutively in this array.
RANKCORR must be a rank-correlation matrix of the DISTRIBUTION, i.e. it
must be symmetric and positive definite and its diagonal entries must be
equal to ‘1’.
The Cholesky factor is computed (and stored) to verify the positive
definiteness condition.
A ‘NULL’ pointer for RANKCORR is interpreted as the identity matrix.
_Important:_ In case of an error (e.g. because RANKCORR is not a valid
rank-correlation matrix) an error code is returned. Moreover, the
rank-correlation matrix is not set and is marked as unknown. A previously
set rank-correlation matrix is then no longer available.
_Remark:_ UNU.RAN does not check whether the an eventually set covariance
matrix and a rank-correlation matrix do not contradict each other.
-- Function: const double* unur_distr_cvec_get_rankcorr (const UNUR_DISTR*
DISTRIBUTION)
-- Function: const double* unur_distr_cvec_get_rk_cholesky (const UNUR_DISTR*
DISTRIBUTION)
Get rank-correlation matrix and its cholesky factor, respectively, of
DISTRIBUTION. The function returns a pointer to an array of size ‘dim’ x
‘dim’. The rows of the matrix are stored consecutively in this array. If
the requested matrix is not marked as known the ‘NULL’ pointer is returned
and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_GET’.
_Important:_ Do *not* modify the array that holds the rank-correlation
matrix!
-- Function: int unur_distr_cvec_set_marginals (UNUR_DISTR* DISTRIBUTION,
UNUR_DISTR* MARGINAL)
Sets marginal distributions of the given DISTRIBUTION to the same MARGINAL
distribution object. The MARGINAL distribution must be an instance of a
continuous univariate distribution object. Notice that the marginal
distribution is copied into the DISTRIBUTION object.
-- Function: int unur_distr_cvec_set_marginal_array (UNUR_DISTR* DISTRIBUTION,
UNUR_DISTR** MARGINALS)
Analogously to the above ‘unur_distr_cvec_set_marginals’ call. However,
now an array MARGINALS of the pointers to each of the marginal
distributions must be given. It *must* be an array of size ‘dim’, where
‘dim’ is the dimension returned by ‘unur_distr_get_dim’. _Notice_: Local
copies for each of the entries are stored in the DISTRIBUTION object. If
some of these entries are identical (i.e. contain the same pointer), then
for each of these a new copy is made.
-- Function: int unur_distr_cvec_set_marginal_list (UNUR_DISTR* DISTRIBUTION,
...)
Similar to the above ‘unur_distr_cvec_set_marginal_array’ call. However,
now the pointers to the particular marginal distributions can be given as
parameter and does not require an array of pointers. Additionally the
given distribution objects are immediately destroyed. Thus calls like
‘unur_distr_normal’ can be used as arguments. (With
‘unur_distr_cvec_set_marginal_array’ the result of such call has to be
stored in a pointer since it has to be freed afterwarts to avoid memory
leaks!)
The number of pointers to in the list of function arguments *must* be equal
to the dimension of the DISTRIBUTION, i.e. the dimension returned by
‘unur_distr_get_dim’. If one of the given pointer to marginal
distributions is the ‘NULL’ pointer then the marginal distributions of
DISTRIBUTION are not set (or previous settings are not changed) and an
error code is returned.
*Important:* All distribution objects given in the argument list are
destroyed!
-- Function: const UNUR_DISTR* unur_distr_cvec_get_marginal (const UNUR_DISTR*
DISTRIBUTION, int N)
Get pointer to the N-th marginal distribution object from the given
multivariate DISTRIBUTION. If this does not exist, ‘NULL’ is returned.
The marginal distributions are enumerated from ‘1’ to ‘dim’, where ‘dim’ is
the dimension returned by ‘unur_distr_get_dim’.
-- Function: int unur_distr_cvec_set_pdfparams (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* PARAMS, int N_PARAMS)
Sets array of parameters for DISTRIBUTION. There is an upper limit for the
number of parameters ‘n_params’. It is given by the macro
‘UNUR_DISTR_MAXPARAMS’ in ‘unuran_config.h’. (It is set to 5 by default
but can be changed to any appropriate nonnegative number.) If N_PARAMS is
negative or exceeds this limit no parameters are copied into the
distribution object and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_NPARAMS’.
For standard distributions from the UNU.RAN library the parameters are
checked. Moreover, the domain is updated automatically. If the given
parameters are invalid for the standard distribution, then no parameters
are set and an error code is returned. Notice that the given parameter
list for such a distribution is handled in the same way as in the
corresponding ‘new’ calls, i.e. optional parameters for the PDF that are
not present in the given list are (re-)set to their default values.
*Important:* If the parameters of a distribution from the UNU.RAN library
of standard distributions (*note Standard distributions: Stddist.) are
changed, then neither its mode nor the normalization constant are updated.
Please use the respective calls ‘unur_distr_cvec_upd_mode’ and
‘unur_distr_cvec_upd_pdfvol’.
-- Function: int unur_distr_cvec_get_pdfparams (const UNUR_DISTR* DISTRIBUTION,
const DOUBLE** PARAMS)
Get number of parameters of the PDF and set pointer PARAMS to array of
parameters. If no parameters are stored in the object, an error code is
returned and ‘params’ is set to ‘NULL’.
_Important:_ Do *not* change the entries in PARAMS!
-- Function: int unur_distr_cvec_set_pdfparams_vec (UNUR_DISTR* DISTRIBUTION,
int PAR, const DOUBLE* PARAM_VEC, int N_PARAMS)
This function provides an interface for additional vector parameters for a
multivariate DISTRIBUTION besides mean vector and covariance matrix which
have their own calls.
It sets the parameter with number PAR. PAR indicates directly which of the
parameters is set and must be a number between ‘0’ and
‘UNUR_DISTR_MAXPARAMS’-1 (the upper limit of possible parameters defined in
‘unuran_config.h’; it is set to 5 but can be changed to any appropriate
nonnegative number.)
The entries of a this parameter are given by the array PARAM_VEC of size
N_PARAMS. Notice that using this interface an An (n x m)-matrix has to be
stored in an array of length N_PARAMS = n times m; where the rows of the
matrix are stored consecutively in this array.
Due to great variety of possible parameters for a multivariate DISTRIBUTION
there is no simpler interface.
If PARAM_VEC is ‘NULL’ then the corresponding entry is cleared.
*Important:* If the parameters of a distribution from the UNU.RAN library
of standard distributions (*note Standard distributions: Stddist.) are
changed, then neither its mode nor the normalization constant are updated.
Please use the respective calls ‘unur_distr_cvec_upd_mode’ and
‘unur_distr_cvec_upd_pdfvol’. If an error occurs no parameters are copied
into the parameter object ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_DATA’.
-- Function: int unur_distr_cvec_get_pdfparams_vec (const UNUR_DISTR*
DISTRIBUTION, int PAR, const DOUBLE** PARAM_VECS)
Get parameter of the PDF with number PAR. The pointer to the parameter
array is stored in PARAM_VECS, its size is returned by the function. If
the requested parameter is not set, then an error code is returned and
‘params’ is set to ‘NULL’.
_Important:_ Do *not* change the entries in PARAM_VECS!
-- Function: int unur_distr_cvec_set_domain_rect (UNUR_DISTR* DISTRIBUTION,
const DOUBLE* LOWERLEFT, const DOUBLE* UPPERRIGHT)
Set rectangular domain for DISTRIBUTION with LOWERLEFT and UPPERRIGHT
vertices. Both must be pointer to an array of the size returned by
‘unur_distr_get_dim’. A ‘NULL’ pointer is interpreted as the zero vector
(0,...,0). For setting a coordinate of the boundary to +/- infinity use
‘+/- UNUR_INFINITY’. The LOWERLEFT vertex must be strictly smaller than
UPPERRIGHT in each component. Otherwise no domain is set and ‘unur_errno’
is set to ‘UNUR_ERR_DISTR_SET’.
By default the domain of a distribution is unbounded. Thus one can use
this call to truncate an existing distribution.
_Important:_ Changing the domain of DISTRIBUTION marks derived parameters
like the mode or the center as unknown and must be set _after_ changing the
domain. This is important for the already set (or default) value for the
center does not fall into the given domain. Notice that calls of the PDF
and derived functions return ‘0.’ when the parameter is not contained in
the domain.
-- Function: int unur_distr_cvec_is_indomain (const DOUBLE* X, const
UNUR_DISTR* DISTRIBUTION)
Check whether X falls into the domain of DISTRIBUTION.
Derived parameters
..................
The following paramters *must* be set whenever one of the essential parameters
has been set or changed (and the parameter is required for the chosen method).
-- Function: int unur_distr_cvec_set_mode (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* MODE)
Set mode of the DISTRIBUTION. MODE must be a pointer to an array of the
size returned by ‘unur_distr_get_dim’. A ‘NULL’ pointer for MODE is
interpreted as the zero vector (0,...,0).
-- Function: int unur_distr_cvec_upd_mode (UNUR_DISTR* DISTRIBUTION)
Recompute the mode of the DISTRIBUTION. This call works properly for
distribution objects from the UNU.RAN library of standard distributions
when the corresponding function is available. If it failes ‘unur_errno’ is
set to ‘UNUR_ERR_DISTR_DATA’.
-- Function: const double* unur_distr_cvec_get_mode (UNUR_DISTR* DISTRIBUTION)
Get mode of the DISTRIBUTION. The function returns a pointer to an array
of the size returned by ‘unur_distr_get_dim’. If the mode is not marked as
known the ‘NULL’ pointer is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_GET’. (There is no difference between the case where no
routine for computing the mode is available and the case where no mode
exists for the DISTRIBUTION at all.)
_Important:_ Do *not* modify the array that holds the mode!
-- Function: int unur_distr_cvec_set_center (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* CENTER)
Set center of the DISTRIBUTION. CENTER must be a pointer to an array of
the size returned by ‘unur_distr_get_dim’. A ‘NULL’ pointer for CENTER is
interpreted as the zero vector (0,...,0).
The center is used by some methods to shift the distribution in order to
decrease numerical round-off error. If not given explicitly a default is
used. Moreover, it is used as starting point for several numerical search
algorithm (e.g. for the mode). Then CENTER must be a pointer where the
call to the PDF returns a non-zero value. In particular CENTER must
contained in the domain of the distribution.
Default: The mode, if given by a ‘unur_distr_cvec_set_mode’ call; else the
mean, if given by a ‘unur_distr_cvec_set_mean’ call; otherwise the null
vector (0,...,0).
-- Function: const double* unur_distr_cvec_get_center (UNUR_DISTR*
DISTRIBUTION)
Get center of the DISTRIBUTION. The function returns a pointer to an array
of the size returned by ‘unur_distr_get_dim’. It always returns some point
as there always exists a default for the center, see
‘unur_distr_cvec_set_center’. _Important:_ Do *not* modify the array that
holds the center!
-- Function: int unur_distr_cvec_set_pdfvol (UNUR_DISTR* DISTRIBUTION, double
VOLUME)
Set the volume below the PDF. If VOL is non-positive, no volume is set and
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_SET’.
-- Function: int unur_distr_cvec_upd_pdfvol (UNUR_DISTR* DISTRIBUTION)
Recompute the volume below the PDF of the distribution. It only works for
distribution objects from the UNU.RAN library of standard distributions
when the corresponding function is available. Otherwise ‘unur_errno’ is
set to ‘UNUR_ERR_DISTR_DATA’.
This call also sets the normalization constant such that the given PDF is
the derivative of a given CDF, i.e. the volume is 1.
-- Function: double unur_distr_cvec_get_pdfvol (UNUR_DISTR* DISTRIBUTION)
Get the volume below the PDF of the DISTRIBUTION. If this volume is not
known,
‘unur_distr_cont_upd_pdfarea’ is called to compute it. If this is not
successful ‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_GET’.
4.6 Continuous univariate full conditional distribution
=======================================================
Full conditional distribution for a given continuous multivariate distributiion.
The condition is a position vector and either a variable that is variated or a
vector that indicates the direction on which the random vector can variate.
There is a subtle difference between using direction vector and using the
K-th variable. When a direction vector is given the PDF of the conditional
distribution is defined by f(t) = PDF(pos + t * dir). When a variable is
selected the full conditional distribution with all other variables fixed is
used.
This is a special case of a continuous univariate distribution and thus they
have most of these parameters (with the exception that functions cannot be
changed). Additionally,
− there is a call to extract the underlying multivariate distribution,
− and a call to handle the variables that are fixed and the direction for
changing the random vector.
This distibution type is primarily used for evaluation the conditional
distribution and its derivative (as required for, e.g., the Gibbs sampler). The
density is not normalized (i.e. does not integrate to one). Mode and area are
not available and it does not make sense to use any call to set or change
parameters except the ones given below.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_condi_new (const UNUR_DISTR* DISTRIBUTION,
const DOUBLE* POS, const DOUBLE* DIR, int K)
Create an object for full conditional distribution for the given
DISTRIBUTION. The condition is given by a position vector POS and either
the K-th variable that is variated or the vector DIR that contains the
direction on which the random vector can variate.
DISTRIBUTION must be a pointer to a multivariate continuous distribution.
POS must be a pointer to an array of size ‘dim’, where ‘dim’ is the
dimension of the underlying distribution object. DIR must be a pointer to
an array if size ‘dim’ or ‘NULL’. K must be in the range ‘0, ..., dim-1’.
If the K-th variable is used, DIR must be set to ‘NULL’.
_Notice:_ There is a subtle difference between using direction vector DIR
and using the K-th variable. When DIR is given, the current position POS
is mapped into 0 of the conditional distribution and the derivative is
taken from the function PDF(POS+t*DIR) w.r.t. t. On the other hand, when
the coordinate K is used (i.e., when DIR is set to ‘NULL’), the full
conditional distribution of the distribution is considered (as used for the
Gibbs sampler). In particular, the current point is just projected into
the one-dimensional subspace without mapping it into the point 0.
_Notice:_ If a coordinate K is used, then the K-th partial derivative is
used if it as available. Otherwise the gradient is computed and the K-th
component is returned.
The resulting generator object is of the same type as of a
‘unur_distr_cont_new’ call.
-- Function: int unur_distr_condi_set_condition (struct UNUR_DISTR*
DISTRIBUTION, const DOUBLE* POS, const DOUBLE* DIR, int K)
Set/change condition for conditional DISTRIBUTION. Change values of fixed
variables to POS and use direction DIR or K-th variable of conditional
DISTRIBUTION.
POS must be a pointer to an array of size ‘dim’, where ‘dim’ is the
dimension of the underlying distribution object. DIR must be a pointer to
an array if size ‘dim’ or ‘NULL’. K must be in the range ‘0, ..., dim-1’.
If the K-th variable is used, DIR must be set to ‘NULL’.
_Notice:_ There is a subtle difference between using direction vector DIR
and using the K-th variable. When DIR is given, the current position POS
is mapped into 0 of the conditional distribution and the derivative is
taken from the function PDF(POS+t*DIR) w.r.t. t. On the other hand, when
the coordinate K is used (i.e., when DIR is set to ‘NULL’), the full
conditional distribution of the distribution is considered (as used for the
Gibbs sampler). In particular, the current point is just projected into
the one-dimensional subspace without mapping it into the point 0.
-- Function: int unur_distr_condi_get_condition (struct UNUR_DISTR*
DISTRIBUTION, const DOUBLE** POS, const DOUBLE** DIR, int* K)
Get condition for conditional DISTRIBUTION. The values for the fixed
variables are stored in POS, which must be a pointer to an array of size
‘dim’. The condition is stored in DIR and K, respectively.
_Important:_ Do *not* change the entries in POS and DIR!
-- Function: const UNUR_DISTR* unur_distr_condi_get_distribution (const
UNUR_DISTR* DISTRIBUTION)
Get pointer to distribution object for underlying distribution.
4.7 Continuous empirical multivariate distributions
===================================================
Empirical multivariate distributions are just lists of vectors (with the same
dimension). Thus there are only calls to insert these data. How these data are
used to sample from the empirical distribution depends from the chosen
generation method.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_cvemp_new (int DIM)
Create a new (empty) object for an empirical multivariate continuous
distribution. DIM is the number of components of the random vector (i.e.
its dimension). It must be at least 2; otherwise ‘unur_distr_cemp_new’
should be used to create an object for an empirical univariate
distribution.
Essential parameters
....................
-- Function: int unur_distr_cvemp_set_data (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* SAMPLE, int N_SAMPLE)
Set observed sample for empirical DISTRIBUTION. SAMPLE is an array of
doubles of size ‘dim’ x N_SAMPLE, where ‘dim’ is the dimension of the
DISTRIBUTION returned by ‘unur_distr_get_dim’. The data points must be
stored consecutively in SAMPLE, i.e., data points (x1, y1), (x2, y2), ...
are given as an array {x1, y1, x2, y2, ...}.
-- Function: int unur_distr_cvemp_read_data (UNUR_DISTR* DISTRIBUTION, const
CHAR* FILENAME)
Read data from file ‘filename’. It reads the first ‘dim’ numbers from each
line, where ‘dim’ is the dimension of the DISTRIBUTION returned by
‘unur_distr_get_dim’. Numbers are parsed by means of the C standard
routine ‘strtod’. Lines that do not start with ‘+’, ‘-’, ‘.’, or a digit
are ignored. (Beware of lines starting with a blank!)
In case of an error (file cannot be opened, too few entries in a line,
invalid string for double in line) no data are copied into the distribution
object and an error code is returned.
-- Function: int unur_distr_cvemp_get_data (const UNUR_DISTR* DISTRIBUTION,
const DOUBLE** SAMPLE)
Get number of samples and set pointer SAMPLE to array of observations. If
no sample has been given, an error code is returned and SAMPLE is set to
‘NULL’. If successful SAMPLE points to an array of length ‘dim’ x
‘n_sample’, where ‘dim’ is the dimension of the distribution returned by
‘unur_distr_get_dim’ and ‘n_sample’ the return value of the function.
_Important:_ Do *not* modify the array SAMPLE.
4.8 MATRix distributions
========================
Distributions for random matrices. Notice that UNU.RAN uses arrays of ‘double’s
to handle matrices. The rows of the matrix are stored consecutively.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_matr_new (int N_ROWS, int N_COLS)
Create a new (empty) object for a matrix distribution. N_ROWS and N_COLS
are the respective numbers of rows and columns of the random matrix (i.e.
its dimensions). It is also possible to have only one number or rows
and/or columns. Notice, however, that this is treated as a distribution of
random matrices with only one row or column or component and not as a
distribution of vectors or real numbers. For the latter
‘unur_distr_cont_new’ or ‘unur_distr_cvec_new’ should be used to create an
object for a univariate distribution and a multivariate (vector)
distribution, respectively.
Essential parameters
....................
-- Function: int unur_distr_matr_get_dim (const UNUR_DISTR* DISTRIBUTION, int*
N_ROWS, int* N_COLS)
Get number of rows and columns of random matrix (its dimension). It
returns the total number of components. If successfull ‘UNUR_SUCCESS’ is
returned.
4.9 Discrete univariate distributions
=====================================
The calls in this section can be applied to discrete univariate distributions.
− Create a ‘new’ instance of a discrete univariate distribution.
− Handle and evaluate distribution function (CDF, ‘cdf’) and probability mass
function (PMF, ‘pmf’). The following is important:
. ‘pmf’ need not be normalized, i.e., any summable nonnegative function
on the set of intergers can be used.
. ‘cdf’ must be a distribution function, i.e. it must be monotonically
increasing with range [0,1].
. If ‘cdf’ and ‘pdf’ are used together for a pariticular generation
method, then ‘pmf’ must be normalized, i.e. it must sum to 1.
− Alternatively, ‘cdf’ and ‘pdf’ can be provided as ‘str’ings instead of
function pointers.
− Some generation methods require a (finite) probability vector (PV, ‘pv’),
i.e. an array of ‘double’s. It can be automatically computed if the ‘pmf’
is given but ‘pv’ is not.
− Set (and change) parameters (‘pmfparams’) and the total sum (‘pmfsum’) of
the given PMF or PV.
− Set the ‘mode’ of the distribution.
− Set the ‘domain’ of the distribution.
Function reference
------------------
-- Function: UNUR_DISTR* unur_distr_discr_new (void)
Create a new (empty) object for a univariate discrete distribution.
Essential parameters
....................
There are two interfaces for discrete univariate distributions: Either provide a
(finite) probability vector (PV). Or provide a probability mass function (PMF).
For the latter case there are also a couple of derived parameters that are not
required when a PV is given.
It is not possible to set both a PMF and a PV directly. However, the PV can
be computed from the PMF (or the CDF if no PMF is available) by means of a
‘unur_distr_discr_make_pv’ call. If both the PV and the PMF are given in the
distribution object it depends on the generation method which of these is used.
-- Function: int unur_distr_discr_set_pv (UNUR_DISTR* DISTRIBUTION, const
DOUBLE* PV, int N_PV)
Set finite probability vector (PV) for the DISTRIBUTION. It is not
necessary that the entries in the given PV sum to 1. N_PV must be
positive. However, there is no testing whether all entries in PV are
non-negative.
If no domain has been set, then the left boundary is set to ‘0’, by
default. If N_PV is too large, e.g. because left boundary + N_PV exceeds
the range of integers, then the call fails.
Notice that it is not possible to set both a PV and a PMF or CDF. If the
PMF or CDF is set first one cannot set the PV. If the PMF or CDF is set
first after a PV is set, the latter is removed (and recomputed using
‘unur_distr_discr_make_pv’ when required).
-- Function: int unur_distr_discr_make_pv (UNUR_DISTR* DISTRIBUTION)
Compute a PV when a PMF or CDF is given. However, when the domain is not
given or is too large and the sum over the PMF is given then the (right)
tail of the DISTRIBUTION is chopped off such that the probability for the
tail region is less than 1.e-8. If the sum over the PMF is not given a PV
of maximal length is computed.
The maximal size of the created PV is bounded by the macro
‘UNUR_MAX_AUTO_PV’ that is defined in ‘unuran_config.h’.
If successful, the length of the generated PV is returned. If the sum over
the PMF on the chopped tail is not neglible small (i.e. greater than 1.e-8
or unknown) than the negative of the length of the PV is returned and
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_SET’.
Notice that the left boundary of the PV is set to ‘0’ by default when a
discrete distribution object is created from scratch.
If computing a PV fails for some reasons, an error code is returned and
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_SET’.
-- Function: int unur_distr_discr_get_pv (const UNUR_DISTR* DISTRIBUTION, const
DOUBLE** PV)
Get length of PV of the DISTRIBUTION and set pointer PV to array of
probabilities. If no PV is given, an error code is returned and PV is set
to ‘NULL’.
(It does not call ‘unur_distr_discr_make_pv’ !)
-- Function: int unur_distr_discr_set_pmf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_DISCR* PMF)
-- Function: int unur_distr_discr_set_cdf (UNUR_DISTR* DISTRIBUTION,
UNUR_FUNCT_DISCR* CDF)
Set respective pointer to the PMF and the CDF of the DISTRIBUTION. These
functions must be of type ‘double funct(int k, const UNUR_DISTR *distr)’.
It is important to note that all these functions must return a result for
all integers K. E.g., if the domain of a given PMF is the interval
{1,2,3,...,100}, than the given function must return ‘0.0’ for all points
outside this interval.
The default domain for the PMF or CDF is [‘0’, ‘INT_MAX’]. The domain can
be changed using a ‘unur_distr_discr_set_domain’ call.
It is not possible to change such a function. Once the PMF or CDF is set
it cannot be overwritten. A new distribution object has to be used
instead.
Notice that it is not possible to set both a PV and a PMF or CDF. If the
PMF or CDF is set first one cannot set the PV. If the PMF or CDF is set
first after a PV is set, the latter is removed (and recomputed using
‘unur_distr_discr_make_pv’ when required).
-- Function: int unur_distr_discr_set_invcdf (UNUR_DISTR* DISTRIBUTION,
UNUR_IFUNCT_DISCR* INVCDF)
Set inverse CDF of the DISTRIBUTION. INVCDF must be a pointer must be of
type ‘int funct(double x, const UNUR_DISTR *distr)’, i.e., it should return
a ‘double’.
-- Function: double unur_distr_discr_eval_pv (int K, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_discr_eval_pmf (int K, const UNUR_DISTR*
DISTRIBUTION)
-- Function: double unur_distr_discr_eval_cdf (int K, const UNUR_DISTR*
DISTRIBUTION)
Evaluate the PV, PMF, and the CDF, respectively, at k. Notice that
DISTRIBUTION must not be the ‘NULL’ pointer. If no PV is set for the
DISTRIBUTION, then ‘unur_distr_discr_eval_pv’ behaves like
‘unur_distr_discr_eval_pmf’. If the corresponding function is not
available for the DISTRIBUTION, ‘UNUR_INFINITY’ is returned and
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_DATA’.
_IMPORTANT:_ In the case of a truncated standard distribution these calls
always return the respective values of the _untruncated_ distribution!
-- Function: int unur_distr_discr_eval_invcdf (double U, const UNUR_DISTR*
DISTRIBUTION)
Evaluate the inverse CDF at U. Notice that DISTRIBUTION must not be the
‘NULL’ pointer. If the corresponding function is not available for the
distribution, ‘INT_MAX’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_DATA’.
_IMPORTANT:_ In the case of a truncated standard distribution these calls
always return the respective values of the _untruncated_ distribution!
-- Function: int unur_distr_discr_set_pmfstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* PMFSTR)
This function provides an alternative way to set a PMF of the DISTRIBUTION.
PMFSTR is a character string that contains the formula for the PMF, see
*note Function String: StringFunct, for details. See also the remarks for
the ‘unur_distr_discr_set_pmf’ call.
It is not possible to call this funtion twice or to call this function
after a ‘unur_distr_discr_set_pmf’ call.
-- Function: int unur_distr_discr_set_cdfstr (UNUR_DISTR* DISTRIBUTION, const
CHAR* CDFSTR)
This function provides an alternative way to set a CDF; analogously to the
‘unur_distr_discr_set_pmfstr’ call.
-- Function: char* unur_distr_discr_get_pmfstr (const UNUR_DISTR* DISTRIBUTION)
-- Function: char* unur_distr_discr_get_cdfstr (const UNUR_DISTR* DISTRIBUTION)
Get pointer to respective string for PMF and CDF of DISTRIBUTION that is
given via the string interface. This call allocates memory to produce this
string. It should be freed when it is not used any more.
-- Function: int unur_distr_discr_set_pmfparams (UNUR_DISTR* DISTRIBUTION,
const DOUBLE* PARAMS, int N_PARAMS)
Set array of parameters for DISTRIBUTION. There is an upper limit for the
number of parameters N_PARAMS. It is given by the macro
‘UNUR_DISTR_MAXPARAMS’ in ‘unuran_config.h’. (It is set to 5 but can be
changed to any appropriate nonnegative number.) If N_PARAMS is negative or
exceeds this limit no parameters are copied into the DISTRIBUTION object
and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_NPARAMS’.
For standard distributions from the UNU.RAN library the parameters are
checked. Moreover, the domain is updated automatically unless it has been
changed before by a ‘unur_distr_discr_set_domain’ call. If the given
parameters are invalid for the standard distribution, then no parameters
are set and an error code is returned. Notice that the given parameter
list for such a distribution is handled in the same way as in the
corresponding ‘new’ calls, i.e. optional parameters for the PDF that are
not present in the given list are (re-)set to their default values.
_Important:_ Integer parameter must be given as ‘double’s.
-- Function: int unur_distr_discr_get_pmfparams (const UNUR_DISTR*
DISTRIBUTION, const DOUBLE** PARAMS)
Get number of parameters of the PMF and set pointer PARAMS to array of
parameters. If no parameters are stored in the object, an error code is
returned and ‘params’ is set to ‘NULL’.
-- Function: int unur_distr_discr_set_domain (UNUR_DISTR* DISTRIBUTION, int
LEFT, int RIGHT)
Set the left and right borders of the domain of the DISTRIBUTION. This can
also be used to truncate an existing distribution. For setting the
boundary to +/- infinity use ‘INT_MIN’ and ‘INT_MAX’, respectively. If
RIGHT is not strictly greater than LEFT no domain is set and ‘unur_errno’
is set to ‘UNUR_ERR_DISTR_SET’. It is allowed to use this call to increase
the domain. If the PV of the discrete distribution is used, than the right
boudary is ignored (and internally set to LEFT + size of PV - 1). Notice
that ‘INT_MIN’ and ‘INT_MAX’ are interpreted as (minus/plus) infinity.
Default: [‘0’, ‘INT_MAX’].
-- Function: int unur_distr_discr_get_domain (const UNUR_DISTR* DISTRIBUTION,
int* LEFT, int* RIGHT)
Get the left and right borders of the domain of the DISTRIBUTION. If the
domain is not set explicitly the interval [‘INT_MIN’, ‘INT_MAX’] is assumed
and returned. When a PV is given then the domain is set automatically to
[‘0’,size of PV - 1].
Derived parameters
..................
The following paramters *must* be set whenever one of the essential parameters
has been set or changed (and the parameter is required for the chosen method).
-- Function: int unur_distr_discr_set_mode (UNUR_DISTR* DISTRIBUTION, int MODE)
Set mode of DISTRIBUTION.
-- Function: int unur_distr_discr_upd_mode (UNUR_DISTR* DISTRIBUTION)
Recompute the mode of the DISTRIBUTION. This call works properly for
distribution objects from the UNU.RAN library of standard distributions
when the corresponding function is available. Otherwise a (slow) numerical
mode finder is used. It only works properly for unimodal probability mass
functions. If it failes ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_DATA’.
-- Function: int unur_distr_discr_get_mode (UNUR_DISTR* DISTRIBUTION)
Get mode of DISTRIBUTION. If the mode is not marked as known,
‘unur_distr_discr_upd_mode’ is called to compute the mode. If this is not
successful ‘INT_MAX’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_GET’. (There is no difference between the case where no
routine for computing the mode is available and the case where no mode
exists for the distribution at all.)
-- Function: int unur_distr_discr_set_pmfsum (UNUR_DISTR* DISTRIBUTION, double
SUM)
Set the sum over the PMF. If ‘sum’ is non-positive, no sum is set and
‘unur_errno’ is set to ‘UNUR_ERR_DISTR_SET’.
For a distribution object created by the UNU.RAN library of standard
distributions you always should use the ‘unur_distr_discr_upd_pmfsum’.
Otherwise there might be ambiguous side-effects.
-- Function: int unur_distr_discr_upd_pmfsum (UNUR_DISTR* DISTRIBUTION)
Recompute the sum over the PMF of the DISTRIBUTION. In most cases the
normalization constant is recomputed and thus the sum is 1. This call
works for distribution objects from the UNU.RAN library of standard
distributions when the corresponding function is available. When a PV, a
PMF with finite domain, or a CDF is given, a simple generic function which
uses a naive summation loop is used. If this computation is not possible,
an error code is returned and ‘unur_errno’ is set to ‘UNUR_ERR_DISTR_DATA’.
The call does not work for distributions from the UNU.RAN library of
standard distributions with truncated domain when the CDF is not available.
-- Function: double unur_distr_discr_get_pmfsum (UNUR_DISTR* DISTRIBUTION)
Get the sum over the PMF of the DISTRIBUTION. If this sum is not known,
‘unur_distr_discr_upd_pmfsum’ is called to compute it. If this is not
successful ‘UNUR_INFINITY’ is returned and ‘unur_errno’ is set to
‘UNUR_ERR_DISTR_GET’.
5 Methods for generating non-uniform random variates
****************************************************
Sampling from a particular distribution with UNU.RAN requires the following
steps:
1. Create a distribution object (*note Handling distribution objects:
Distribution_objects.).
2. Select a method and create a parameter object.
3. Initizialize the generator object using ‘unur_init’. _Important_:
Initialization of the generator object might fail. ‘unur_init’ returns a
‘NULL’ pointer then, which *must* not be used for sampling.
4. Draw a sample from the generator object using the corresponding sampling
function (depending on the type of distribution: univariate continuous,
univariate discrete, multivariate continuous, and random matrix).
5. It is possible for a generator object to change the parameters and the
domain of the underlying distribution. This must be done by extracting
this object by means of a ‘unur_get_distr’ call and changing the
distribution using the correspondig set calls, see *note Handling
distribution objects: Distribution_objects. The generator object *must*
then be reinitialized by means of the ‘unur_reinit’ call.
_Important_: Currently not all methods allow reinitialization, see the
description of the particular method (keyword Reinit).
_Important_: Reinitialization of the generator object might fail. Thus one
*must* check the return code of the ‘unur_reinit’ call.
_Important_: When reinitialization fails then sampling routines always
return ‘UNUR_INFINITY’ (for continuous distributions) or ‘0’ (for discrete
distributions), respectively. However, it is still possible to change the
underlying distribution and try to reinitialize again.
5.1 Routines for all generator objects
======================================
Routines for all generator objects.
Function reference
------------------
-- Function: UNUR_GEN* unur_init (UNUR_PAR* PARAMETERS)
Initialize a generator object. All necessary information must be stored in
the parameter object.
*Important:* If an error has occurred a ‘NULL’ pointer is return. This
must not be used for the sampling routines (this causes a segmentation
fault).
*Always* check whether the call was successful or not!
_Important:_ This call destroys the PARAMETER object automatically. Thus
it is not necessary/allowed to free it.
-- Function: int unur_reinit (UNUR_GEN* GENERATOR)
Update an existing generator object after the underlying distribution has
been modified (using ‘unur_get_distr’ together with corresponding set
calls. It *must* be executed before sampling using this generator object
is continued as otherwise it produces an invalid sample or might even cause
a segmentation fault.
_Important_: Currently not all methods allow reinitialization, see the
description of the particular method (keyword Reinit).
_Important_: Reinitialization of the generator object might fail. Thus one
*must* check the return code:
‘UNUR_SUCCESS (0x0u)’
success (no error)
‘UNUR_ERR_NO_REINIT’
reinit routine not implemented.
other values
some error has occured while trying to reinitialize the generator
object.
_Important_: When reinitialization fails then sampling routines always
return ‘UNUR_INFINITY’ (for continuous distributions) or ‘0’ (for discrete
distributions), respectively. However, it is still possible to change the
underlying distribution and try to reinitialize again.
_Important_: When one tries to run ‘unur_reinit’, but reinitialization is
not implemented, then the generator object cannot be used any more and must
be destroyed and a new one has to be built from scratch.
-- Function: int unur_sample_discr (UNUR_GEN* GENERATOR)
-- Function: double unur_sample_cont (UNUR_GEN* GENERATOR)
-- Function: int unur_sample_vec (UNUR_GEN* GENERATOR, double* VECTOR)
-- Function: int unur_sample_matr (UNUR_GEN* GENERATOR, double* MATRIX)
Sample from generator object. The three routines depend on the type of the
generator object (discrete or continuous univariate distribution,
multivariate distribution, or random matrix).
_Notice:_ UNU.RAN uses arrays of ‘double’s to handle matrices. There the
rows of the matrix are stored consecutively.
_Notice:_ The routines ‘unur_sample_vec’ and ‘unur_sample_matr’ return
‘UNUR_SUCCESS’ if generation was successful and some error code otherwise.
*Important:* These routines do *not* check whether GENERATOR is an invalid
‘NULL’ pointer.
-- Function: double unur_quantile (UNUR_GEN* GENERATOR, double U)
Compute the U quantile of a continuous distribution using a GENERATOR
object that implements an (approximate) inversion methods.
The following methods are currently available:
• HINV, *note HINV::.
• NINV, *note NINV::.
• PINV, *note PINV::.
• CSTD, *note CSTD::.
This requires that GENERATOR implements an inversion method.
• DGT, *note DGT::.
The return value is (of course) type casted to ‘double’.
*Important:* This routine does *not* check whether GENERATOR is an invalid
‘NULL’ pointer.
In case of an error UNUR_INFINITY or INT_MAX (depending on the type of
GENERATOR) is returned.
-- Function: void unur_free (UNUR_GEN* GENERATOR)
Destroy (free) the given generator object.
-- Function: const char* unur_gen_info (UNUR_GEN* GENERATOR, int HELP)
Get a string with informations about the given GENERATOR. These
informations allow some fine tuning of the generation method. If HELP is
‘TRUE’, some hints on setting parameters are given.
This function is intented for using in interactive environments (like R).
If an error occurs, then ‘NULL’ is returned.
-- Function: int unur_get_dimension (const UNUR_GEN* GENERATOR)
Get the number of dimension of a (multivariate) distribution. For a
univariate distribution ‘1’ is return.
-- Function: const char* unur_get_genid (const UNUR_GEN* GENERATOR)
Get identifier string for generator.
-- Function: unsigned int unur_get_method (const UNUR_GEN* GENERATOR)
Get identifier for generating method. These identifiers are declared in
‘src/methods/unur_metthods.h’.
-- Function: int unur_gen_is_inversion (const UNUR_GEN* GEN)
Return ‘TRUE’ if the generator object implements an inversion method, and
‘FALSE’ otherwise.
-- Function: UNUR_DISTR* unur_get_distr (const UNUR_GEN* GENERATOR)
Get pointer to distribution object from generator object. This function
can be used to change the parameters of the distribution and reinitialize
the generator object. Notice that currently *not all* generating methods
have a reinitialize routine. This function should be used with extreme
care. Changing the distribution is changed and using the generator object
without reinitializing might cause wrong samples or segmentation faults.
Moreover, if the corresponding generator object is freed, the pointer must
not be used.
*Important:* The returned distribution object must not be freed. If the
distribution object is changed then one *must* run ‘unur_reinit’ !
-- Function: int unur_set_use_distr_privatecopy (UNUR_PAR* PARAMETERS, int
USE_PRIVATECOPY)
Set flag whether the generator object should make a private copy of the
given distribution object or just stores the pointer to this distribution
object. Values for USE_PRIVATECOPY:
‘TRUE’
make a private copy (default)
‘FALSE’
do not make a private copy and store pointer to given (external)
distribution object.
By default, generator objects keep their own private copy of the given
distribution object. Thus the generator object can be handled
independently from other UNU.RAN objects (with uniform random number
generators as the only exception). When the generator object is
initialized the given distribution object is cloned and stored.
However, in some rare situations it can be useful when only the pointer to
the given distribution object is stored without making a private copy. A
possible example is when only one random variate has to be drawn from the
distribution. This behavior can be achieved when USE_LOCALCOPY is set to
‘FALSE’.
*Warning!* Using a pointer to the external distribution object instead of
a private copy must be done with *extreme care*! When the distrubtion
object is changed or freed then the generator object does not work any
more, might case a segmentation fault, or (even worse) produces garbage.
On the other hand, when the generator object is initialized or used to draw
a random sampling the distribution object may be changed.
_Notice:_ The prototypes of all ‘unur__new’ calls use a ‘const’
qualifier for the distribution argument. However, if USE_PRIVATECOPY is
set to ‘FALSE’ this qualifier is discarded and the distribution might be
changed.
*Important!* If USE_LOCALCOPY is set to ‘FALSE’ and the corresponding
distribution object is changed then one must run ‘unur_reinit’ on the
generator object. (Notice that currently not all generation methods
support reinitialization.)
Default: USE_PRIVATECOPY is ‘TRUE’.
5.2 AUTO – Select method automatically
======================================
AUTO selects a an appropriate method for the given distribution object
automatically. There are no parameters for this method, yet. But it is planned
to give some parameter to describe the task for which the random variate
generator is used for and thus make the choice of the generating method more
appropriate. Notice that the required sampling routine for the generator object
depends on the type of the given distribution object.
The chosen method also depends on the sample size for which the generator
object will be used. If only a few random variates the order of magnitude of
the sample size should be set via a ‘unur_auto_set_logss’ call.
IMPORTANT: This is an experimental version and the method chosen may change
in future releases of UNU.RAN.
For an example see *note As short as possible: Example_0.
How To Use
..........
Create a generator object for the given distribution object.
Function reference
------------------
-- Function: UNUR_PAR* unur_auto_new (const UNUR_DISTR* DISTRIBUTION)
Get default parameters for generator.
-- Function: int unur_auto_set_logss (UNUR_PAR* PARAMETERS, int LOGSS)
Set the order of magnitude for the size of the sample that will be
generated by the generator, i.e., the the common logarithm of the sample
size.
Default is 10.
Notice: This feature will be used in future releases of UNU.RAN only.
5.3 Methods for continuous univariate distributions
===================================================
Overview of methods
-------------------
Methods for continuous univariate distributions
sample with ‘unur_sample_cont’
method PDF dPDF CDF mode area other
AROU x x [x] T-concave
ARS x x T-concave
CEXT wrapper for external generator
CSTD build-in standard distribution
HINV [x] [x] x
HRB bounded hazard rate
HRD decreasing hazard rate
HRI increasing hazard rate
ITDR x x x monotone with pole
NINV [x] x
NROU x [x]
PINV x [x] [~]
SROU x x x T-concave
SSR x x x T-concave
TABL x x [~] all local extrema
TDR x x T-concave
UTDR x x ~ T-concave
Example
-------
/* ------------------------------------------------------------- */
/* File: example_cont.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
/* Example how to sample from a continuous univariate */
/* distribution. */
/* */
/* We build a distribution object from scratch and sample. */
/* ------------------------------------------------------------- */
/* Define the PDF and dPDF of our distribution. */
/* */
/* Our distribution has the PDF */
/* */
/* / 1 - x*x if |x| <= 1 */
/* f(x) = < */
/* \ 0 otherwise */
/* */
/* The PDF of our distribution: */
double mypdf( double x, const UNUR_DISTR *distr )
/* The second argument (`distr') can be used for parameters */
/* for the PDF. (We do not use parameters in our example.) */
{
if (fabs(x) >= 1.)
return 0.;
else
return (1.-x*x);
} /* end of mypdf() */
/* The derivative of the PDF of our distribution: */
double mydpdf( double x, const UNUR_DISTR *distr )
{
if (fabs(x) >= 1.)
return 0.;
else
return (-2.*x);
} /* end of mydpdf() */
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare the three UNURAN objects. */
UNUR_DISTR *distr; /* distribution object */
UNUR_PAR *par; /* parameter object */
UNUR_GEN *gen; /* generator object */
/* Create a new distribution object from scratch. */
/* Get empty distribution object for a continuous distribution */
distr = unur_distr_cont_new();
/* Fill the distribution object -- the provided information */
/* must fulfill the requirements of the method choosen below. */
unur_distr_cont_set_pdf(distr, mypdf); /* PDF */
unur_distr_cont_set_dpdf(distr, mydpdf); /* its derivative */
unur_distr_cont_set_mode(distr, 0.); /* mode */
unur_distr_cont_set_domain(distr, -1., 1.); /* domain */
/* Choose a method: TDR. */
par = unur_tdr_new(distr);
/* Set some parameters of the method TDR. */
unur_tdr_set_variant_gw(par);
unur_tdr_set_max_sqhratio(par, 0.90);
unur_tdr_set_c(par, -0.5);
unur_tdr_set_max_intervals(par, 100);
unur_tdr_set_cpoints(par, 10, NULL);
/* Create the generator object. */
gen = unur_init(par);
/* Notice that this call has also destroyed the parameter */
/* object `par' as a side effect. */
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* It is possible to reuse the distribution object to create */
/* another generator object. If you do not need it any more, */
/* it should be destroyed to free memory. */
unur_distr_free(distr);
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
Example (String API)
--------------------
/* ------------------------------------------------------------- */
/* File: example_cont_str.c */
/* ------------------------------------------------------------- */
/* String API. */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include
/* ------------------------------------------------------------- */
/* Example how to sample from a continuous univariate */
/* distribution. */
/* We use a generic distribution object and sample. */
/* */
/* The PDF of our distribution is given by */
/* */
/* / 1 - x*x if |x| <= 1 */
/* f(x) = < */
/* \ 0 otherwise */
/* */
/* ------------------------------------------------------------- */
int main(void)
{
int i; /* loop variable */
double x; /* will hold the random number */
/* Declare UNURAN generator object. */
UNUR_GEN *gen; /* generator object */
/* Create the generator object. */
/* Use a generic continuous distribution. */
/* Choose a method: TDR. */
gen = unur_str2gen(
"distr = cont; pdf=\"1-x*x\"; domain=(-1,1); mode=0. & \
method=tdr; variant_gw; max_sqhratio=0.90; c=-0.5; \
max_intervals=100; cpoints=10");
/* It is important to check if the creation of the generator */
/* object was successful. Otherwise `gen' is the NULL pointer */
/* and would cause a segmentation fault if used for sampling. */
if (gen == NULL) {
fprintf(stderr, "ERROR: cannot create generator object\n");
exit (EXIT_FAILURE);
}
/* Now you can use the generator object `gen' to sample from */
/* the distribution. Eg.: */
for (i=0; i<10; i++) {
x = unur_sample_cont(gen);
printf("%f\n",x);
}
/* When you do not need the generator object any more, you */
/* can destroy it. */
unur_free(gen);
exit (EXIT_SUCCESS);
} /* end of main() */
/* ------------------------------------------------------------- */
5.3.1 AROU – Automatic Ratio-Of-Uniforms method
-----------------------------------------------
Required:
T-concave PDF, dPDF
Optional:
mode
Speed:
Set-up: slow, Sampling: fast
Reinit:
not implemented
Reference:
[LJa00]
AROU is a variant of the ratio-of-uniforms method that uses the fact that the
transformed region is convex for many distributions. It works for all T-concave
distributions with T(x) = -1/sqrt(x).
It is possible to use this method for correlation induction by setting an
auxiliary uniform random number generator via the ‘unur_set_urng_aux’ call.
(Notice that this must be done after a possible ‘unur_set_urng’ call.) When an
auxiliary generator is used then the number of used uniform random numbers that
is used up for one generated random variate is constant and equal to 1.
There exists a test mode that verifies whether the conditions for the method
are satisfied or not while sampling. It can be switched on by calling
‘unur_arou_set_verify’ and ‘unur_arou_chg_verify’, respectively. Notice however
that sampling is (much) slower then.
For densities with modes not close to 0 it is suggested to set either the
mode or the center of the distribution by the ‘unur_distr_cont_set_mode’ or
‘unur_distr_cont_set_center’ call. The latter is the approximate location of
the mode or the mean of the distribution. This location provides some
information about the main part of the PDF and is used to avoid numerical
problems.
Function reference
------------------
-- Function: UNUR_PAR* unur_arou_new (const UNUR_DISTR* DISTRIBUTION)
Get default parameters for generator.
-- Function: int unur_arou_set_usedars (UNUR_PAR* PARAMETERS, int USEDARS)
If USEDARS is set to ‘TRUE’, “derandomized adaptive rejection sampling”
(DARS) is used in setup. Segments where the area between hat and squeeze
is too large compared to the average area between hat and squeeze over all
intervals are split. This procedure is repeated until the ratio between
area below squeeze and area below hat exceeds the bound given by
‘unur_arou_set_max_sqhratio’ call or the maximum number of segments is
reached. Moreover, it also aborts when no more segments can be found for
splitting.
Segments are split such that the angle of the segments are halved
(corresponds to arc-mean rule of method TDR (*note TDR::)).
Default is ‘TRUE’.
-- Function: int unur_arou_set_darsfactor (UNUR_PAR* PARAMETERS, double FACTOR)
Set factor for “derandomized adaptive rejection sampling”. This factor is
used to determine the segments that are “too large”, that is, all segments
where the area between squeeze and hat is larger than FACTOR times the
average area over all intervals between squeeze and hat. Notice that all
segments are split when FACTOR is set to ‘0.’, and that there is no
splitting at all when FACTOR is set to ‘UNUR_INFINITY’.
Default is ‘0.99’. There is no need to change this parameter.
-- Function: int unur_arou_set_max_sqhratio (UNUR_PAR* PARAMETERS, double
MAX_RATIO)
Set upper bound for the ratio (area inside squeeze) / (area inside
envelope). It must be a number between 0 and 1. When the ratio exceeds
the given number no further construction points are inserted via adaptive
rejection sampling. Use ‘0’ if no construction points should be added
after the setup. Use ‘1’ if adding new construction points should not be
stopped until the maximum number of construction points is reached.
Default is ‘0.99’.
-- Function: double unur_arou_get_sqhratio (const UNUR_GEN* GENERATOR)
Get the current ratio (area inside squeeze) / (area inside envelope) for
the generator. (In case of an error ‘UNUR_INFINITY’ is returned.)
-- Function: double unur_arou_get_hatarea (const UNUR_GEN* GENERATOR)
Get the area below the hat for the generator. (In case of an error
‘UNUR_INFINITY’ is returned.)
-- Function: double unur_arou_get_squeezearea (const UNUR_GEN* GENERATOR)
Get the area below the squeeze for the generator. (In case of an error
‘UNUR_INFINITY’ is returned.)
-- Function: int unur_arou_set_max_segments (UNUR_PAR* PARAMETERS, int
MAX_SEGS)
Set maximum number of segements. No construction points are added _after_
the setup when the number of segments succeeds MAX_SEGS.
Default is ‘100’.
-- Function: int unur_arou_set_cpoints (UNUR_PAR* PARAMETERS, int N_STP, const
DOUBLE* STP)
Set construction points for enveloping polygon. If STP is ‘NULL’, then a
heuristical rule of thumb is used to get N_STP construction points. This
is the default behavior when this routine is not called. The (default)
number of construction points is ‘30’, then.
-- Function: int unur_arou_set_usecenter (UNUR_PAR* PARAMETERS, int USECENTER)
Use the center as construction point. Default is ‘TRUE’.
-- Function: int unur_arou_set_guidefactor (UNUR_PAR* PARAMETERS, double
FACTOR)
Set factor for relative size of the guide table for indexed search (see
also method DGT *note DGT::). It must be greater than or equal to ‘0’.
When set to ‘0’, then sequential search is used.
Default is ‘2’.
-- Function: int unur_arou_set_verify (UNUR_PAR* PARAMETERS, int VERIFY)
-- Function: int unur_arou_chg_verify (UNUR_GEN* GENERATOR, int VERIFY)
Turn verifying of algorithm while sampling on/off. If the condition
squeeze(x) <= PDF(x) <= hat(x) is violated for some x then ‘unur_errno’ is
set to ‘UNUR_ERR_GEN_CONDITION’. However notice that this might happen due
to round-off errors for a few values of x (less than 1%).
Default is ‘FALSE’.
-- Function: int unur_arou_set_pedantic (UNUR_PAR* PARAMETERS, int PEDANTIC)
Sometimes it might happen that ‘unur_init’ has been executed successfully.
But when additional construction points are added by adaptive rejection
sampling, the algorithm detects that the PDF is not T-concave.
With PEDANTIC being ‘TRUE’, the sampling routine is then exchanged by a
routine that simply returns ‘UNUR_INFINITY’. Otherwise the new point is
not added to the list of construction points. At least the hat function
remains T-concave.
Setting PEDANTIC to ‘FALSE’ allows sampling from a distribution which is
“almost” T-concave and small errors are tolerated. However it might happen
that the hat function cannot be improved significantly. When the hat
function that has been constructed by the ‘unur_init’ call is extremely
large then it might happen that the generation times are extremely high
(even hours are possible in extremely rare cases).
Default is ‘FALSE’.
5.3.2 ARS – Adaptive Rejection Sampling
---------------------------------------
Required:
concave logPDF, derivative of logPDF
Optional:
mode
Speed:
Set-up: fast, Sampling: slow
Reinit:
supported
Reference:
[GWa92] [HLD04: Cha.4]
ARS is an acceptance/rejection method that uses the concavity of the
log-density function to construct hat function and squeezes automatically. It
is very similar to method TDR (*note TDR::) with variant GW, parameter ‘c = 0’,
and DARS switched off. Moreover, method ARS requires the logPDF and its
derivative dlogPDF to run. On the other hand, it is designed to draw only a
(very) small samples and it is much more robust against densities with very
large or small areas below the PDF as it occurs, for example, in conditional
distributions of (high dimensional) multivariate distributions. Additionally,
it can be re-initialized when the underlying distribution has been modified.
Thus it is well suited for Gibbs sampling.
Notice, that method ARS is a restricted version of TDR. If the full
functionally of Transformed Density Rejection is needed use method *note TDR::.
How To Use
..........
Method ARS is designed for distributions with log-concave densities. To use
this method you need a distribution object with the logarithm of the PDF and its
derivative given.
The number of construction points as well as a set of such points can be
provided using ‘unur_ars_set_cpoints’. Notice that addition construction points
are added by means of adaptive rejection sampling until the maximal number of
intervals given by ‘unur_ars_set_max_intervals’ is reached.
A generated distribution object can be reinitialized using the ‘unur_reinit’
call. When ‘unur_reinit’ is called construction points for the new generator
are necessary. There are two options: Either the same construction points as
for the initial generator (given by a ‘unur_ars_set_cpoints’ call) are used
(this is the default), or percentiles of the old hat function can be used. This
can be set or changed using ‘unur_ars_set_reinit_percentiles’ and
‘unur_ars_chg_reinit_percentiles’. This feature is usefull when the underlying
distribution object is only moderately changed. (An example is Gibbs sampling
with small correlations.)
There exists a test mode that verifies whether the conditions for the method
are satisfied or not. It can be switched on by calling ‘unur_ars_set_verify’
and ‘unur_ars_chg_verify’, respectively. Notice however that sampling is (much)
slower then.
Method ARS aborts after a given number of iterations and return UNUR_INFINITY
to prevent (almost) infinite loops. This might happen when the starting hat is
much too large and it is not possible to insert new construction points due to
severe numerical errors or (more likely) the given PDF is not log-concave. This
maximum number of iterations can be set by means of a ‘unur_ars_set_max_iter’
call.
Function reference
------------------
-- Function: UNUR_PAR* unur_ars_new (const UNUR_DISTR* DISTRIBUTION)
Get default parameters for generator.
-- Function: int unur_ars_set_max_intervals (UNUR_PAR* PARAMETERS, int MAX_IVS)
Set maximum number of intervals. No construction points are added after
the setup when the number of intervals suceeds MAX_IVS. It is increased
automatically to twice the number of construction points if this is larger.
Default is ‘200’.
-- Function: int unur_ars_set_cpoints (UNUR_PAR* PARAMETERS, int N_CPOINTS,
const DOUBLE* CPOINTS)
Set construction points for the hat function. If CPOINTS is ‘NULL’ then a
heuristic rule of thumb is used to get N_CPOINTS construction points. This
is the default behavior. N_CPOINTS should be at least ‘2’, otherwise
defaults are used.
The default number of construction points is 2.
-- Function: int unur_ars_set_reinit_percentiles (UNUR_PAR* PARAMETERS, int
N_PERCENTILES, const DOUBLE* PERCENTILES)
-- Function: int unur_ars_chg_reinit_percentiles (UNUR_GEN* GENERATOR, int
N_PERCENTILES, const DOUBLE* PERCENTILES)
By default, when the GENERATOR object is reinitialized, it used the same
construction points as for the initialization procedure. Often the
underlying distribution object has been changed only moderately. For
example, the full conditional distribution of a multivariate distribution.
In this case it might be more appropriate to use percentilesm of the hat
function for the last (unchanged) distribution. PERCENTILES must then be a
pointer to an ordered array of numbers between ‘0.01’ and ‘0.99’. If
PERCENTILES is ‘NULL’, then a heuristic rule of thumb is used to get
N_PERCENTILES values for these percentiles. Notice that N_PERCENTILES must
be at least ‘2’, otherwise defaults are used. (Then the first and third
quartiles are used by default.)
-- Function: int unur_ars_set_reinit_ncpoints (UNUR_PAR* PARAMETERS, int
NCPOINTS)
-- Function: int unur_ars_chg_reinit_ncpoints (UNUR_GEN* GENERATOR, int
NCPOINTS)
When reinit fails with the given construction points or the percentiles of
the old hat function, another trial is undertaken with NCPOINTS
construction points. NCPOINTS must be at least ‘10’.
Default: ‘30’
-- Function: int unur_ars_set_max_iter (UNUR_PAR* PARAMETERS, int MAX_ITER)
The rejection loop stops after MAX_ITER iterations and return
UNUR_INFINITY.
Default: ‘10000’
-- Function: int unur_ars_set_verify (UNUR_PAR* PARAMETERS, int VERIFY)
-- Function: int unur_ars_chg_verify (UNUR_GEN* GENERATOR, int VERIFY)
Turn verifying of algorithm while sampling on/off. If the condition
squeeze(x) <= PDF(x) <= hat(x) is violated for some x then ‘unur_errno’ is
set to ‘UNUR_ERR_GEN_CONDITION’. However notice that this might happen due
to round-off errors for a few values of x (less than 1%).
Default is ‘FALSE’.
-- Function: int unur_ars_set_pedantic (UNUR_PAR* PARAMETERS, int PEDANTIC)
Sometimes it might happen that ‘unur_init’ has been executed successfully.
But when additional construction points are added by adaptive rejection
sampling, the algorithm detects that the PDF is not log-concave.
With PEDANTIC being ‘TRUE’, the sampling routine is exchanged by a routine
that simply returns ‘UNUR_INFINITY’. Otherwise the new point is not added
to the list of construction points. At least the hat function remains
log-concave.
Setting PEDANTIC to ‘FALSE’ allows sampling from a distribution which is
“almost” log-concave and small errors are tolerated. However it might
happen that the hat function cannot be improved significantly. When the
hat functions that has been constructed by the ‘unur_init’ call is
extremely large then it might happen that the generation times are
extremely high (even hours are possible in extremely rare cases).
Default is ‘FALSE’.
-- Function: double unur_ars_get_loghatarea (const UNUR_GEN* GENERATOR)
Get the logarithm of area below the hat for the generator. (In case of an
error ‘UNUR_INFINITY’ is returned.)
-- Function: double unur_ars_eval_invcdfhat (const UNUR_GEN* GENERATOR, double
U)
Evaluate the inverse of the CDF of the hat distribution at U.
If U is out of the domain [0,1] then ‘unur_errno’ is set to
‘UNUR_ERR_DOMAIN’ and the respective bound of the domain of the
distribution are returned (which is ‘-UNUR_INFINITY’ or ‘UNUR_INFINITY’ in
the case of unbounded domains).
5.3.3 CEXT – wrapper for Continuous EXTernal generators
-------------------------------------------------------
Required:
routine for sampling continuous random variates
Speed:
depends on external generator
Reinit:
supported
Method CEXT is a wrapper for external generators for continuous univariate
distributions. It allows the usage of external random variate generators within
the UNU.RAN framework.
How To Use
..........
The following steps are required to use some external generator within the
UNU.RAN framework (some of these are optional):
1. Make an empty generator object using a ‘unur_cext_new’ call. The argument
DISTRIBUTION is optional and can be replaced by ‘NULL’. However, it is
required if you want to pass parameters of the generated distribution to
the external generator or for running some validation tests provided by
UNU.RAN.
2. Create an initialization routine of type ‘int (*init)(UNUR_GEN *gen)’ and
plug it into the generator object using the ‘unur_cext_set_init’ call.
Notice that the INIT routine must return ‘UNUR_SUCCESS’ when it has been
executed successfully and ‘UNUR_FAILURE’ otherwise. It is possible to get
the size of and the pointer to the array of parameters of the underlying
distribution object by the respective calls ‘unur_cext_get_ndistrparams’
and ‘unur_cext_get_distrparams’. Parameters for the external generator
that are computed in the INIT routine can be stored in a single array or
structure which is available by the ‘unur_cext_get_params’ call.
Using an INIT routine is optional and can be omitted.
3. Create a sampling routine of type ‘double (*sample)(UNUR_GEN *gen)’ and
plug it into the generator object using the ‘unur_cext_set_sample’ call.
Uniform random numbers are provided by the ‘unur_sample_urng’ call. Do not
use your own implementation of a uniform random number generator directly.
If you want to use your own random number generator we recommend to use the
UNU.RAN interface (see *note Using uniform random number generators:
URNG.).
The array or structure that contains parameters for the external generator
that are computed in the INIT routine are available using the
‘unur_cext_get_params’ call.
Using a SAMPLE routine is of course obligatory.
It is possible to change the parameters and the domain of the chosen
distribution and run ‘unur_reinit’ to reinitialize the generator object. The
INIT routine is then called again.
Here is a short example that demonstrates the application of this method by
means of the exponential distribution:
/* ------------------------------------------------------------- */
/* File: example_cext.c */
/* ------------------------------------------------------------- */
/* Include UNURAN header file. */
#include