.. default-domain:: chpl
.. module:: Random
:synopsis: Support for pseudorandom number generation
Random
======
**Usage**
.. code-block:: chapel
use Random;
**Submodules**
.. toctree::
:maxdepth: 1
:glob:
Random/*
Support for pseudorandom number generation
This module defines an abstraction for a stream of pseudorandom numbers,
:class:`~RandomStreamInterface`. Use :proc:`makeRandomStream` to
create such an stream. Each stream supports methods to get the next
random number in the stream (:proc:`~RandomStreamInterface.getNext`),
to fast-forward to a specific value in the stream
(:proc:`~RandomStreamInterface.skipToNth` and
:proc:`~RandomStreamInterface.getNth`), to iterate over random values
possibly in parallel (:proc:`~RandomStreamInterface.iterate`), or to
fill an array with random numbers in parallel
(:proc:`~RandomStreamInterface.fillRandom`).
The module also provides several standalone convenience functions that can be
used without manually creating a :class:`RandomStreamInterface` object.
* :proc:`fillRandom` fills an array with random numbers in parallel
* :proc:`shuffle` randomly re-arranges the elements of an array
* :proc:`permutation` creates a random permutation and stores it in an
array.
In these and other methods, generated integer values are uniformly
distributed from `min(T)` to `max(T)`, where `T` is the integral type and the
boundaries are included. Generated floating point values are uniformly
distributed in [0.0, 1.0] with the caveat that it currently depends on the
RNG whether the boundary values 0.0 and 1.0 can be produced.
Use :proc:`makeRandomStream` or the constructor for a specific RNG
implementation to get a RandomStream. See the documentation for
each RNG implementation for more information:
* :mod:`PCGRandom`
* :mod:`NPBRandom`
.. note::
Right now, :class:`~NPBRandom.NPBRandomStream` and
:class:`~PCGRandom.RandomStream` are available (where
:class:`~PCGRandom.RandomStream` implements the PCG algorithm). In the
future, we expect that `PCGRandomStream` will be available as another name
for the PCG RNG stream. At that point, `RandomStream` will change to a
type alias for the default RNG. The function :proc:`makeRandomStream` is
available to avoid compatibility problems from this naming change.
Programs that need to specifically request PCG should do so with
:proc:`makeRandomStream` until the name `PCGRandomStream` is available..
.. note::
The RandomStream API (:class:`RandomStreamInterface`) is expected to
change.
.. enum:: enum RNG { PCG = 1, NPB = 2 }
Select between different supported RNG algorithms.
See :mod:`PCGRandom` and :mod:`NPBRandom` for details on
these algorithms.
.. data:: param defaultRNG = RNG.PCG
The default RNG. The current default is PCG - see :mod:`PCGRandom`.
.. function:: proc fillRandom(arr: [], seed: int(64) = SeedGenerator.oddCurrentTime, param algorithm = defaultRNG)
Fill an array of numeric elements with pseudorandom values in parallel using
a new stream implementing :class:`RandomStreamInterface` created
specifically for this call. The first `arr.size` values from the stream
will be assigned to the array's elements in row-major order. The
parallelization strategy is determined by the array.
.. note::
:mod:`NPBRandom` only supports `real(64)`, `imag(64)`, and `complex(128)`
numeric types. :mod:`PCGRandom` supports all primitive numeric types.
:arg arr: The array to be filled, where T is a primitive numeric type
:type arr: `[] T`
:arg seed: The seed to use for the PRNG. Defaults to
`oddCurrentTime` from :type:`RandomSupport.SeedGenerator`.
:type seed: `int(64)`
:arg algorithm: A param indicating which algorithm to use. Defaults to PCG.
:type algorithm: :type:`RNG`
.. function:: proc shuffle(arr: [], seed: int(64) = SeedGenerator.oddCurrentTime, param algorithm = RNG.PCG)
Shuffle the elements of an array into a random order.
:arg arr: a 1-D non-strided array
:arg seed: the seed to use when shuffling. Defaults to
`oddCurrentTime` from :type:`RandomSupport.SeedGenerator`.
:arg algorithm: A param indicating which algorithm to use. Defaults to PCG.
:type algorithm: :type:`RNG`
.. function:: proc permutation(arr: [], seed: int(64) = SeedGenerator.oddCurrentTime, param algorithm = RNG.PCG)
Produce a random permutation, storing it in a 1-D array.
The resulting array will include each value from low..high
exactly once, where low and high refer to the array's domain.
:arg arr: a 1-D non-strided array
:arg seed: the seed to use when creating the permutation. Defaults to
`oddCurrentTime` from :type:`RandomSupport.SeedGenerator`.
:arg algorithm: A param indicating which algorithm to use. Defaults to PCG.
:type algorithm: :type:`RNG`
.. function:: proc makeRandomStream(seed: int(64) = SeedGenerator.oddCurrentTime, param parSafe: bool = true, type eltType = real(64), param algorithm = defaultRNG)
Constructs a new stream of random numbers using the specified seed
and parallel safety. Ensures that the seed value meets the PRNG's
constraints.
.. note::
The :mod:`NPBRandom` RNG will halt if provided an even seed.
:mod:`PCGRandom` has no restrictions on the provided seed value.
:arg seed: The seed to use for the PRNG. Defaults to `oddCurrentTime` from
:type:`RandomSupport.SeedGenerator`.
:type seed: `int(64)`
:arg parSafe: The parallel safety setting. Defaults to `true`.
:type parSafe: `bool`
:arg eltType: The element type to be generated. Defaults to `real(64)`.
:type eltType: `type`
:arg algorithm: A param indicating which algorithm to use. Defaults to PCG.
:type algorithm: :type:`RNG`
.. class:: RandomStreamInterface
Models a stream of pseudorandom numbers. This class is defined for
documentation purposes and should not be instantiated. See
:mod:`PCGRandom` and :mod:`NPBRandom` for RNGs that can be
instantiated. To create a random stream, use :proc:`makeRandomStream`.
.. note::
This RandomStreamInterface is expected to change.
.. note::
At present, different implementations of this interface can vary in
whether or not they can generate 0.0 and/or 1.0. (e.g. They can be
generated by :mod:`PCGRandom` but not by :mod:`NPBRandom`).
.. note::
We plan to support general serial and parallel iterator methods on
:class:`RandomStreamInterface`; however, providing the full suite of
iterators is not possible with our current parallel iterator framework.
Specifically, if :class:`RandomStreamInterface` is a follower in a
zippered iteration context, there is no way for it to update the total
number of random numbers generated in a safe/sane/coordinated way. We are
exploring a revised leader-follower iterator framework that would support
this idiom (and other cursor-based ones). With Chapel's recent support
for standalone parallel iterators, one could define a standalone parallel
iterator for :class:`RandomStreamInterface`, but this effort has not yet
been taken on.
.. note::
The :class:`RandomStreamInterface` is included here only for documentation
and does not help with compilation in any way. In the future, we hope to
turn it into an interface.
.. attribute:: type eltType = real(64)
Specifies the type of value generated by the RandomStream.
Not all RandomStream implementations support all types.
.. attribute:: param parSafe: bool = true
Indicates whether or not the RandomStream needs to be
parallel-safe by default. If multiple tasks interact with it in
an uncoordinated fashion, this must be set to `true`. If it will
only be called from a single task, or if only one task will call
into it at a time, setting to `false` will reduce overhead related
to ensuring mutual exclusion.
.. attribute:: const seed: int(64)
The seed value for the PRNG. There may be constraints upon
legal values depending on the specific RNG.
.. method:: proc getNext(): eltType
Returns the next value in the random stream.
:returns: The next value in the random stream as type :type:`eltType`.
.. method:: proc skipToNth(n: integral)
Advances/rewinds the stream to the `n`-th value in the sequence.
The first value is with n=1.
:arg n: The position in the stream to skip to. Must be > 0.
:type n: `integral`
.. method:: proc getNth(n: integral): eltType
Advance/rewind the stream to the `n`-th value and return it
(advancing the stream by one). This is equivalent to
:proc:`skipToNth()` followed by :proc:`getNext()`.
:arg n: The position in the stream to skip to. Must be > 0.
:type n: `integral`
:returns: The `n`-th value in the random stream as type :type:`eltType`.
.. method:: proc fillRandom(arr: [] eltType)
Fill the argument array with pseudorandom values. This method is
identical to the standalone :proc:`fillRandom` procedure,
except that it consumes random values from the
:class:`RandomStreamInterface` object on which it's invoked rather
than creating a new stream for the purpose of the call.
:arg arr: The array to be filled
:type arr: [] :type:`eltType`
.. method:: proc iterate(D: domain, type resultType = eltType)
Returns an iterable expression for generating `D.numIndices` random
numbers. The RNG state will be immediately advanced by `D.numIndices`
before the iterable expression yields any values.
The returned iterable expression is useful in parallel contexts,
including standalone and zippered iteration. The domain will determine
the parallelization strategy.
:arg D: a domain
:arg resultType: the type of number to yield
:return: an iterable expression yielding random `resultType` values