.. 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