The classes MPFRUniform, MPFRExponential, and MPFRNormal, provide a efficient methods of computing random deviates and returning the results in the form of MPFR numbers. These classes (together with MPFRRandom) are header-only implementations which do not depend on the rest of RandomLib. In order to use these headers, you can copy them into the directory tree where you are developing an MPFR application (make sure they stay within a directory called RandomLib) and include them with e.g.,
(There are 3 additional classes included in RandomLib: MPFRExponentialL, MPFRNormalK, and MPFRNormalR. But these are included for illustrative purposes only and therefore they are marked as deprecated in the documentation.)
For high precision, the time per sample for MPFRUniform, MPFRExponential, and MPFRNormal is proportional to the precision where the constant of proportionality is governed by generating the required number of random bits and copying these into the result. Thus, using these methods, the generation of random numbers in MPFR is amongst the cheapest of operations (cheaper, for example, than multiplication). The timing data is giving in the tables below.
This table gives the time required to generate a random sample from an exponential distribution:
Key to methods for sampling from the exponential distribution:
(2) ExactExponential, with bits = 32;
(3) MPFRExponential, with bits = 32, which uses the same algorithm as ExactExponential;
(4) MPFRExponentialL, which uses the same algorithm as ExponentialDistribution (taking the log of a uniform deviate).
This table gives the time required to generate a random sample from an normal distribution:
Key to methods for sampling from the normal distribution:
(2) ExactNormal, with bits = 32;
(3) MPFRNormal, with bits = 32, which uses the same algorithm as ExactNormal;
(3') MPFRNormalK, with bits = 32, which uses the Kahn algorithm;
(4) MPFRNormalR, which uses the same algorithm as NormalDistribution (the ratio method);
(4') MPFR's grandom, which uses the polar method.
The von Neumann methods work in two phases. (1) Some number of uniform random numbers are consumed to form the initial digits of the random sample. (2) Additional digits are copied directly from the random number generator to the random sample. It is convenient to be able to interrupt the process after phase (1) and the MPFRRandom class holds this intermediate object. The utility of MPFRRandom is seen by considering Kahn's algorithm for normal sampling: pick y and z from the exponential distribution until (y − 1)2 < 2z and then return y. If y and z are returned as MPFRRandom objects then only sufficient digits need to be generated to determine the acceptance test. If the test passes, then digits only need to be added to y (and not to z). Since the implementation of MPFRNormalK for details. MPFRUniform is a thin wrapper for MPFRRandom which returns samples in [0,1).
The classes MPFRRandom, MPFRUniform, MPFRExponential, MPFRNormal, and MPFRNormalK all take a template parameter bits (default value 32) which gives the number of bits in each "digit" of the MPFRRandom object. This must evenly divide GMP_LIMB_BITS. For portability you should not set this to 64. Typically 32 will provide the best efficiency. Smaller values are useful for debugging, for studying algorithmic complexity (see Knuth and Yao, 1976), or if random bits are expensive (e.g., they are being generated by a hardware generator).
Here is an example of using MPFRNormal:
Typical output from this program is:
Sample from the unit normal distribution at precision 240 -5.6692556912807683301494494874784943926662835210924611284269456310097367350e-2 8.5362069032310026750031502283620341952982028910093176612208572465159728631e-1 ... Sample ranges from the normal distribution at precision 20 [0,1] -> 7.2809029e-1 [-2.25,-2.28125] -> -2.2580643 ...