Random number state

Typically, you don’t need to think much about the state used; in the simple example we do

#include <iostream>
#include <dust/random/random.hpp>

int main() {
  using rng_state_type = dust::random::generator<double>;
  auto state = dust::random::seed<rng_state_type>(42);
  for (int i = 0; i < 5; ++i) {
    std::cout << dust::random::random_real<double>(state) << std::endl;
  }
}

This pattern will typically be sufficient - use dust::random::generator to select an appropriate algorithm for your floating point type, and use auto to save it. This will select dust::random::xoshiro256plus for double and dust::random::xoshiro128plus for float

Core state class

Every random number state is built on the same core class

template<typename T, size_t N, scrambler X>
class xoshiro_state

Basic struct to hold random number state for a single stream

Template Parameters:
  • T – The integer type (uint32_t or uint64_t)

  • N – The number of integers included in the state (2, 4, or 8)

  • X – The scrambler type

Public Types

using int_type = T

Type alias used to find the integer type.

Public Functions

__host__ __device__ inline int_type &operator[](size_t i)

Accessor method, used to both get and set the underlying state.

Public Members

int_type state[N]

Array of state.

bool deterministic = false

This flag indicates that the distributions should return the deterministic expectation of the draw, and not use any random numbers

Public Static Functions

__host__ __device__ static inline constexpr size_t size()

Static method, returning the number of integers per state.

Every random number state uses one of the three scrambler options, described based on the mathematical operations they perform when creating the final integer from the generator

enum class dust::random::scrambler

Values:

enumerator starstar

Two multiplications.

enumerator plusplus

Two additions.

enumerator plus

One addition.

Random number generation algorithms

We then define 12 user-usable types, each representing a different algorithm:

32-bit generators, suitable for generating float values

using dust::random::xoshiro128starstar = xoshiro_state<uint32_t, 4, scrambler::starstar>
using dust::random::xoshiro128plusplus = xoshiro_state<uint32_t, 4, scrambler::plusplus>
using dust::random::xoshiro128plus = xoshiro_state<uint32_t, 4, scrambler::plus>

64 bit generators, suitable for generating either double or float values, but differing in the size of the internal state:

128 bits:

using dust::random::xoroshiro128starstar = xoshiro_state<uint64_t, 2, scrambler::starstar>
using dust::random::xoroshiro128plusplus = xoshiro_state<uint64_t, 2, scrambler::plusplus>
using dust::random::xoroshiro128plus = xoshiro_state<uint64_t, 2, scrambler::plus>

256 bits:

using dust::random::xoshiro256starstar = xoshiro_state<uint64_t, 4, scrambler::starstar>
using dust::random::xoshiro256plusplus = xoshiro_state<uint64_t, 4, scrambler::plusplus>
using dust::random::xoshiro256plus = xoshiro_state<uint64_t, 4, scrambler::plus>

512 bits:

using dust::random::xoshiro512starstar = xoshiro_state<uint64_t, 8, scrambler::starstar>
using dust::random::xoshiro512plusplus = xoshiro_state<uint64_t, 8, scrambler::plusplus>
using dust::random::xoshiro512plus = xoshiro_state<uint64_t, 8, scrambler::plus>

Example

#include <iostream>
#include <dust/random/random.hpp>

int main() {
  using rng_state_type = dust::random::xoroshiro128plusplus;
  std::cout << "Using " << rng_state_type::size() << " " <<
    std::numeric_limits<rng_state_type::int_type>::digits <<
    " bit unsigned integers" << std::endl;

  auto state = dust::random::seed<rng_state_type>(42);
  std::cout << std::hex << state[0] << " " << state[1] << std::endl;
}
Using 2 64 bit unsigned integers
bdd732262feb6e95 57e1faba65107204