Gromacs  2025-dev-20241003-bd59e46
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
List of all members | Public Types | Public Member Functions | Static Public Member Functions
gmx::ThreeFry2x64General< rounds, internalCounterBits > Class Template Reference

#include <gromacs/random/threefry.h>

Description

template<unsigned int rounds, unsigned int internalCounterBits>
class gmx::ThreeFry2x64General< rounds, internalCounterBits >

General implementation class for ThreeFry counter-based random engines.

This class is used to implement several different ThreeFry2x64 random engines differing in the number of rounds executed in and the number of bits reserved for the internal counter. It is compatible with C++11 random engines, and can be used e.g. with all random distributions from the standard library.

ThreeFry is a counter-based rather than state-based random engine. This means that we seed it with a "key", after which we can get the N:th random number in a sequence (specified by a counter) directly. This means we are guaranteed the same sequence of numbers even when running in parallel if using e.g. step and atom index as counters.

However, it is also useful to be able to use it as a normal random engine, for instance if you need more than 2 64-bit random values for a specific counter value, not to mention where you just need good normal random numbers. To achieve this, this implementation uses John Salmon's idea of reserving a couple of the highest bits in the user-provided counter for an internal counter. For instance, if reserving 3 bits, this means you get a stream of 8 iterations (each with 2 random values) after every restart. If you call the engine after these bits have been exhausted, it will throw an exception to make sure you don't get overlapping streams by mistake. Reserving 3 bits also means you can only use 64-3=61 bits of the highest word when restarting (i.e., setting) the counters.

This version also supports using internalCounterBits=0. In this case the random engine will be able to return a single counter round, i.e. 2 64-bit values for ThreeFry2x64, after which an exception is thrown. In this case no high bits are reserved, which means the class implements the raw ThreeFry2x64 random function.

Template Parameters
roundsThe number of encryption iterations used when generating. This can in principle be any value, but 20 rounds has been shown to pass all BigCrush random tests, and with 13 rounds only one fails. This is a very stringent test, and the standard Mersenne Twister engine fails two, so 13 rounds should be a perfectly fine balance in most cases.
internalCounterBitsNumber of high bits in the user-provided counter reserved for the internal counter. The number of values the engine can return after each restart will be words*2^internalCounterBits.

Public Types

typedef uint64_t result_type
 Integer type for output.
 
typedef std::array
< result_type, 2 > 
counter_type
 Use array for counter & key states so it is allocated on the stack.
 

Public Member Functions

 ThreeFry2x64General (uint64_t key0=0, RandomDomain domain=RandomDomain::Other)
 Construct random engine with 2x64 key values. More...
 
 ThreeFry2x64General (uint64_t key0, uint64_t key1)
 Construct random engine from 2x64-bit unsigned integers. More...
 
void seed (uint64_t key0=0, RandomDomain domain=RandomDomain::Other)
 Seed 2x64 random engine with two 64-bit key values. More...
 
void seed (uint64_t key0, uint64_t key1)
 Seed random engine from 2x64-bit unsigned integers. More...
 
void restart (uint64_t ctr0=0, uint64_t ctr1=0)
 Restart 2x64 random engine counter from 2 64-bit values. More...
 
result_type operator() ()
 Generate the next random number. More...
 
void discard (uint64_t n)
 Skip next n random numbers. More...
 
bool operator== (const ThreeFry2x64General< rounds, internalCounterBits > &x) const
 Return true if two ThreeFry2x64 engines are identical. More...
 
bool operator!= (const ThreeFry2x64General< rounds, internalCounterBits > &x) const
 Return true of two ThreeFry2x64 engines are not identical. More...
 

Static Public Member Functions

static constexpr result_type min ()
 Smallest value that can be returned from random engine.
 
static constexpr result_type max ()
 Largest value that can be returned from random engine.
 

Constructor & Destructor Documentation

template<unsigned int rounds, unsigned int internalCounterBits>
gmx::ThreeFry2x64General< rounds, internalCounterBits >::ThreeFry2x64General ( uint64_t  key0 = 0,
RandomDomain  domain = RandomDomain::Other 
)
inline

Construct random engine with 2x64 key values.

This constructor takes two values, and should only be used with the 2x64 implementations.

Parameters
key0Random seed in the form of a 64-bit unsigned value.
domainRandom domain. This is used to guarantee that different applications of a random engine inside the code get different streams of random numbers, without requiring the user to provide lots of random seeds. Pick a value from the RandomDomain class, or RandomDomain::Other if it is not important. In the latter case you might want to use gmx::DefaultRandomEngine instead.
Note
The random domain is really another 64-bit seed value.
Exceptions
InternalErrorif the high bits needed to encode the number of counter bits are nonzero.
template<unsigned int rounds, unsigned int internalCounterBits>
gmx::ThreeFry2x64General< rounds, internalCounterBits >::ThreeFry2x64General ( uint64_t  key0,
uint64_t  key1 
)
inline

Construct random engine from 2x64-bit unsigned integers.

This constructor assigns the raw 128 bit key data from unsigned integers. It is meant for the case when you want full control over the key, for instance to compare with reference values of the ThreeFry function during testing.

Parameters
key0First word of key/random seed.
key1Second word of key/random seed.
Exceptions
InternalErrorif the high bits needed to encode the number of counter bits are nonzero. To test arbitrary values, use 0 internal counter bits.

Member Function Documentation

template<unsigned int rounds, unsigned int internalCounterBits>
void gmx::ThreeFry2x64General< rounds, internalCounterBits >::discard ( uint64_t  n)
inline

Skip next n random numbers.

Moves the internal random stream for the give key/counter value n positions forward. The count is based on the number of random values returned, such that skipping 5 values gives exactly the same result as drawing 5 values that are ignored.

Parameters
nNumber of values to jump forward.
Exceptions
InternalErrorif the internal counter space is exhausted.
template<unsigned int rounds, unsigned int internalCounterBits>
bool gmx::ThreeFry2x64General< rounds, internalCounterBits >::operator!= ( const ThreeFry2x64General< rounds, internalCounterBits > &  x) const
inline

Return true of two ThreeFry2x64 engines are not identical.

Parameters
xInstance to compare with.

This routine should return true if the two engines will generate different random streams when drawing.

template<unsigned int rounds, unsigned int internalCounterBits>
result_type gmx::ThreeFry2x64General< rounds, internalCounterBits >::operator() ( )
inline

Generate the next random number.

This will return the next stored 64-bit value if one is available, and otherwise generate a new block, update the internal counters, and return the first value while storing the others.

Exceptions
InternalErrorif the internal counter space is exhausted.
template<unsigned int rounds, unsigned int internalCounterBits>
bool gmx::ThreeFry2x64General< rounds, internalCounterBits >::operator== ( const ThreeFry2x64General< rounds, internalCounterBits > &  x) const
inline

Return true if two ThreeFry2x64 engines are identical.

Parameters
xInstance to compare with.

This routine should return true if the two engines will generate identical random streams when drawing.

template<unsigned int rounds, unsigned int internalCounterBits>
void gmx::ThreeFry2x64General< rounds, internalCounterBits >::restart ( uint64_t  ctr0 = 0,
uint64_t  ctr1 = 0 
)
inline

Restart 2x64 random engine counter from 2 64-bit values.

Parameters
ctr0First word of new counter, in the form of 64-bit unsigned values.
ctr1Second word of new counter

Restarting the engine with a new counter is extremely fast with ThreeFry64, and basically just consists of storing the counter value, so you should use this liberally in your innermost loops to restart the engine with e.g. the current step and atom index as counter values.

Exceptions
InternalErrorif any of the highest bits that are reserved for the internal part of the counter are set. The number of reserved bits is to the last template parameter to the class.
template<unsigned int rounds, unsigned int internalCounterBits>
void gmx::ThreeFry2x64General< rounds, internalCounterBits >::seed ( uint64_t  key0 = 0,
RandomDomain  domain = RandomDomain::Other 
)
inline

Seed 2x64 random engine with two 64-bit key values.

Parameters
key0First word of random seed, in the form of 64-bit unsigned values.
domainRandom domain. This is used to guarantee that different applications of a random engine inside the code get different streams of random numbers, without requiring the user to provide lots of random seeds. Pick a value from the RandomDomain class, or RandomDomain::Other if it is not important. In the latter case you might want to use gmx::DefaultRandomEngine instead.
Note
The random domain is really another 64-bit seed value.

Re-initialized the seed similar to the counter constructor. Same rules apply: The highest few bits of the last word are reserved to encode the number of internal counter bits, but to save the user the trouble of making sure these are zero when using e.g. a random device, we just ignore them.

template<unsigned int rounds, unsigned int internalCounterBits>
void gmx::ThreeFry2x64General< rounds, internalCounterBits >::seed ( uint64_t  key0,
uint64_t  key1 
)
inline

Seed random engine from 2x64-bit unsigned integers.

This assigns the raw 128 bit key data from unsigned integers. It is meant for the case when you want full control over the key, for instance to compare with reference values of the ThreeFry function during testing.

Parameters
key0First word of key/random seed.
key1Second word of key/random seed.
Exceptions
InternalErrorif the high bits needed to encode the number of counter bits are nonzero. To test arbitrary values, use 0 internal counter bits.

The documentation for this class was generated from the following file: