ImFusion SDK 4.3
Random Number Generation

Convenient random number generation that offers automatic seeding and works with standard distributions (boost distributions are the default, but a distribution of choice can be used). More...

+ Collaboration diagram for Random Number Generation:

Detailed Description

Convenient random number generation that offers automatic seeding and works with standard distributions (boost distributions are the default, but a distribution of choice can be used).

The ImFusion::Random namespace provides a generator class which uses the Pcg64Engine class, which is based on the PCG library. The engine is by default automatically seeded, but can also accept a seed when necessary (for example, in reproducible tests). A global generator (singleton) is offered: this generator is thread-safe and default-seeded. Access to the global generator is possible via the global function Random::globalGenerator.

Using the Random generator

An instance of the generator class (or the global one) offers a number of convenient member-functions. getUniformInteger and getUniformReal generate uniformly-distributed integers and real numbers respectively. getNormal generates normally-distributed random numbers.

Random::Generator gen;
gen.getUniformInteger(1, 6); // returns an int between 1 and 6
gen.getUniformReal(0.0, 5.4); // returns a double between 0.0 and 5.4 (calls getUniformReal)
gen.getUniformInteger(1.0, 2.0); // won't compile
gen.getUniformReal(2, 8); // won't compile
gen.getUniformReal(nextReal(0.0), 1.0); // using nextReal to exclude 0.0 from the interval

If you need to use another distribution than the uniform one, call getVariate and specify the return type and the distribution class to use.

Random::Generator gen;
gen.getVariate<int, std::binomial_distribution>(5, 0.7); // returns a random int using std::binomial_distribution with parameters t=5 and p=0.7

Next are the pick and choose functions, which allow to pick a random element (uniformly) in a range.

Random::Generator gen;
gen.pick({1, 3, 5}); // equivalent to 1 + 2 * gen.getUniformInteger(0, 2)
std::vector<int> intValues{1, 2, 4, 9, 16, 25};
auto it = gen.choose(intValues); // returns a random iterator between intValues.begin() and intValues.end() (end excluded)
int chosen = *it; // chosen will be set to one of the values inside intValues
int picked = gen.pick(intValues); // equivalent to the above

You can also pick multiple elements at the same time using pickN. Note that this is different from calling pick N times, since pickN will not return duplicates.

Random::Generator gen;
gen.pickN(3, {2, 3, 5, 7, 11, 13, 17, 19}); // returns a vector of 3 elements contained in the list

Next are the "fill..." functions, which mirror the getUniform... and getVariate functions but write to a range instead of returning a value. fillVariate can be used by specifying a distribution class. The type of elements in the range should match the distribution's output type.

Random::Generator gen;
std::vector<float> floatValues(8);
gen.fillUniformReal(floatValues, nextReal(-1.0), previousReal(1.0)); // fills floatValues with random values between -1 and 1, both excluded
gen.fillVariate<std::gamma_distribution>(floatValues.begin(), floatValues.begin()+4, 1, 2) // replaces the first 4 values of floatValues with random ones using std::gamma_distribution with parameters alpha=1 and beta=2

Next, shuffle and partition are just shorthands for std::shuffle and std::stable_partition. The former shuffles the elements in a range, the latter places a number of the range's elements at the beginning of the range.

std::vector<double> values{1.0, 1.1, 1.4, 1.6, 1.8, 2.0};
Random::Generator gen;
gen.shuffle(values); // shuffles values
gen.partition(2, values); // puts two of the values, randomly chosen, at the beginning
std::vector<double> chosen(values.begin(), values.begin()+2);
std::vector<double> picked = gen.pickN(2, values); // equivalent to the above

Using the global generator

All of the above functionality is provided also via a global instance of a Random::Generator. This instance can be retrieved and used as follows:

Random::Generator& globalGen = Random::globalGenerator();
globalGen.getUniformInteger(0, 10); // returns uniform integer between 0 and 10 via the global generator.
Generator & globalGenerator()
Returns a thread-safe default-seeded generator (singleton)

Note that this global generator is thread safe. Although convenient, usage of global objects such as this generator shall be avoided in favor of local objects.

Auto-seeding and using a generator

When you call the globalGenerator function in the Random namespace, you use a default-constructed global generator. Default-constructed generators are automatically seeded using several different sources of entropy and mixing them together. See the documentation of the Pcg64Engine for more information.

You can also seed the generator yourself on construction. The seed type is Generator::Seed (or uint64_t since the engine is a PCG 64-bit)

Random::Generator gen(5);
int diceRoll = gen.getUniformInteger(1, 6); // will generate the same result every time the application runs (but a random one nonetheless)

Generator::reseed can also be used if you want to provide a new seed without instantiating another generator. If no argument is given, the seed is produced using the same sources of entropy described above. Note that instead of using the same seed multiple times for reproducible processes, you may want to keep a default-constructed main generator instance and copy-construct a new instance to be used in the reproducible process. Copy-construction and copy-assignment guarantee the same output for the copy and the original.

Random::Generator mainGen;
for (int i = 0; i < 10; ++i) {
Random::Generator copiedGen(mainGen);
int diceRoll = copiedGen.getUniform(1, 6); // will generate the same result in all ten iterations
}

Namespaces

namespace  ImFusion
 Namespace of the ImFusion SDK.
 
namespace  ImFusion::Random
 Random number generation with convenience functions
 

Classes

class  Generator
 Convenience class for generating random numbers from various distributions. More...
 
class  Pcg64Engine
 Wrapper class for a 64-bit PCG engine. More...
 

Free functions

GeneratorglobalGenerator ()
 Returns a thread-safe default-seeded generator (singleton)
 
template<typename T>
nextReal (T n)
 Returns the next number representable by T.
 
template<typename T>
previousReal (T n)
 Returns the previous number representable by T.
 

Function Documentation

◆ nextReal()

template<typename T>
T nextReal ( T n)

#include <ImFusion/Core/Random.h>

Returns the next number representable by T.

Used for example to transform a semi-open interval [a, b) into a closed one [a, b]. One use case could be to make sure the lower bound of getUniformReal cannot be returned (because it would cause a division by zero, for example).

◆ previousReal()

template<typename T>
T previousReal ( T n)

#include <ImFusion/Core/Random.h>

Returns the previous number representable by T.

Used for example to transform a closed interval [a, b] into a semi-open one [a, b). One use case could be to make sure the upper bound of getUniformReal cannot be returned (because it would cause a division by zero, for example).

Search Tab / S to search, Esc to close