|
9 | 9 | ******
|
10 | 10 |
|
11 | 11 | The ``flc_random`` module contains advanced pseudo-random number generation
|
12 |
| -from the `<random>`_ C++ header. Currently |
13 |
| -random number generation is hardwired to the ``std::mt19937_64`` 64-bit |
14 |
| -Mersenne Twister by Matsumoto and Nishimura. |
| 12 | +from the `<random>`_ C++ header. |
15 | 13 |
|
16 | 14 | The C++11 way of generating random numbers takes some getting used to. Rather
|
17 | 15 | than having a single global function that returns a random real number in the
|
18 | 16 | range :math:`[0,1)`, C++11 has independent *engine* objects that generate
|
19 | 17 | streams of random bits. Different *distribution* objects convert those bits
|
20 | 18 | into samples of a distribution.
|
21 | 19 |
|
| 20 | +Although C++11 defines a dizzying variety of random number engines, |
| 21 | +``flc_random`` wraps just two: the 32- and 64-bit `Mersenne Twister` |
| 22 | +algorithms. The 32-bit version (``MersenneEngine4``) is currently the only |
| 23 | +engine type that can be used with distributions and algorithms. |
| 24 | + |
22 | 25 | Flibcpp wraps distribution objects as independent subroutines. Each subroutine
|
23 | 26 | accepts the constructor parameters of the distribution, the random engine, and
|
24 | 27 | a target Fortran array to be filled with random numbers.
|
25 | 28 |
|
26 | 29 | Generating an array with 10 normally-distributed reals with a mean of 8 and a
|
27 | 30 | standard deviation of 2 is done as such::
|
28 | 31 |
|
29 |
| - use flc_random, only : Engine, normal_distribution |
| 32 | + use flc_random, only : Engine => MersenneEngine4, normal_distribution |
30 | 33 | real(C_DOUBLE), dimension(20) :: arr
|
31 | 34 | type(Engine) :: rng
|
32 | 35 |
|
33 | 36 | rng = Engine()
|
34 | 37 | call normal_distribution(8.0d0, 2.0d0, rng, arr)
|
| 38 | + call rng%release() |
35 | 39 |
|
36 | 40 | .. _<random> : https://en.cppreference.com/w/cpp/numeric/random
|
| 41 | +.. _Mersenne Twister : https://en.wikipedia.org/wiki/Mersenne_Twister |
| 42 | + |
| 43 | +Engines |
| 44 | +======= |
| 45 | + |
| 46 | +The two Mersenne twister engines in ``flc_random`` return different-sized |
| 47 | +integers per call: |
| 48 | + |
| 49 | + - ``MersenneEngine4``: each invocation returns a 32-bit ``integer(4)`` |
| 50 | + - ``MersenneEngine8``: each invocation returns a 64-bit ``integer(8)`` |
| 51 | + |
| 52 | +Engines can be constructed using one of two interface functions: the |
| 53 | +argument-free ``MersenneEngine4()`` uses the default seed, and the engine takes |
| 54 | +a single argument ``MersenneEngine4(1234567)`` with the seed. Alternatively, |
| 55 | +the seed can be set (or reset) using the ``seed()`` type-bound procedure. |
37 | 56 |
|
38 |
| -Engine |
39 |
| -====== |
| 57 | +Generally, engines are used with distributions (described below). However, if |
| 58 | +necessary, individual randomly generated values can be obtained by calling |
| 59 | +the ``next()`` type-bound procedure. |
40 | 60 |
|
41 |
| -The ``Engine`` is a derived type that wraps the Mersenne Twister PRNG engine. |
42 |
| -Its interface is:: |
| 61 | +.. warning:: C++ generates *unsigned* integers with entropy in every bit. This |
| 62 | + means that the integers obtained from ``engine%next()``, reinterpreted as |
| 63 | + signed Fortran integers, may be negative. |
43 | 64 |
|
44 |
| - type, public :: Engine |
45 |
| - contains |
46 |
| - procedure :: seed => swigf_Engine_seed |
47 |
| - procedure :: discard => swigf_Engine_discard |
48 |
| - procedure :: release => delete_Engine |
49 |
| - end type Engine |
50 |
| - interface Engine |
51 |
| - module procedure new_Engine |
52 |
| - end interface |
| 65 | +In most cases, the default distribution-compatible ``MersenneEngine4`` should |
| 66 | +be used, since the distributions described below require it. |
53 | 67 |
|
54 | 68 | Distributions
|
55 | 69 | =============
|
56 | 70 |
|
57 | 71 | Distributions produce numerical values from the random bitstream provided by
|
58 |
| -the Engine. |
| 72 | +an RNG engine. |
59 | 73 |
|
60 | 74 | normal_distribution
|
61 | 75 | -------------------
|
|
0 commit comments