C++11 linear_congruential_engine random number generator

The C++11 random linear_congruential_engine produce a random sequence of unsigned integer.The declaration of the linear_congruential_engine template is shown below.

Link : C++11 random number generator

template<class UIntType , UIntType a , UIntType c , UIntType m >
 class linear_congruential_engine;

This engine uses the transition algorithm,

(a*xi + c) mod m ;

and the generation algorithm ,

GA(xi) = xi+1;

to produce the random number.The ‘xi‘ is the state of the engine.Some points to note,

i)If ‘m’ is 0, the ‘modular m’ used is numeric_limits::max() plus 1.

ii)If ‘m’ is not 0,the rule ‘a < m‘ and ‘c < m‘ shall hold,otherwise you will get an error.

linear_congruential_engine<unsigned , 1200 , 0 , 1000> lce1;  //error! a<m

linear_congruential_engine<unsigned , 1200 , 1400 , 1350> lce2;  //error! c<m

linear_congruential_engine<unsigned , 1200 , 0 , 1350> lice;  //Work fine! a< , c<m
 

All the types and member functions of the linear_congruential_engine template is shown below.


Types and characteristic

typedef UIntType result_type;

static constexpr result_type multiplier = a;

static constexpr result_type increment = c; 

static constexpr result_type modulus = m;

static constexpr result_type min() { return c == 0u ? 1u: 0u; }

static constexpr result_type max() { return m - 1u; } 

static constexpr result_type default_seed = 1u; 

The min() and max() gives the smallest and largest number the engine can generate.

linear_congruential_engine<unsigned int , 57484 , 0 , 93203293 > lceMinMax ;

cout<< lceMinMax.min() << endl ;

cout<< lceMinMax.max() << endl ; 

Output ,

1
93203292

We can say the parameter ‘m’ determines the range within which the random numbers are generated.



Constructors

//Default constructor
explicit linear_congruential_engine(result_type s = default_seed); 

//Constructor accepting a seed
template<class Sseq> explicit linear_congruential_engine(Sseq& q);

A code example is given below.

linear_congruential_engine<unsigned int , 16807 , 0 , 2147483> lce1 ; //default constructor called

linear_congruential_engine<unsigned int , 16807 , 0 , 2147483> lce2(34) ; //calls the overloaded constructor accepting the seed.

Generating function

The C++11 linear_congruential_engine has two generating functions.By generating functions we mean the function that generate a random sequence.

result_type operator()( ); //Generate random sequence

void discard(unsigned long long z);//Jumpth to the 'z' state of the engine

operator()

To get the random sequence using the engine we will use the ‘operator()‘ function.

linear_congruential_engine<unsigned int , 193703 , 0 , 83474882> lce ;

for(auto i=0 ; i<5 ; i++ )
{
cout<< lce() << ” ” ; //Use the operator() function to generate the random sequence
}

Output in code::blocks,

193703   40630191   11062549   48708007   55066989   53598543

Since the operator() is called five times we obtain five random numbers.


discard(unsigned long long z)

Every engine random number is associated with it’s state.The state determine which number is generated,if you can reproduce the same sate you will get the same random number.The ‘discard’ function help to jump the sate of the engine to the state after the ‘n’ state from the current state.Explaining the concept of ‘discard’ function verbally is rather arduous,so consider the code example.(Note every objects of the engine has the same initial state).

 linear_congruential_engine<unsigned int , 193703 , 0 , 83474882> lcee , lcee1 ; //lcee and lcee1 has the same initial state,so they give the same output
for(auto i=0 ; i<6 ; i++ )
{
cout<< lcee() << ” ” ;
}

cout<< “\n\n” ;

cout<< lcee1() << ” ” ; //first state engine output
cout<< lcee1() << endl ; //second state engine output

lcee1.discard( 2 ); ///jump the state of the engine to the 5th state

cout<< lcee1() << ” ” ; //5th state engine output
cout<< lcee1() << endl ; //6th state engine output

Output in code::blocks,

193703   40630191   11062549   48708007   55066989   53598543
193703   40630191
55066989   53598543

Since the state before calling the ‘discard’ is the 2nd state,after calling it two state is avoided,which means ‘current state(2) +2=4’ ,the 3rd and 4th state is jumped and the 5th state is executed.


Seed generating functions

void seed(result_type s = default_seed);

template<class Sseq> void seed(Sseq& q); //a templatized version of the above function

The seed function allows you to set the seed of the engine.Using this function you can either set the state to the initial state to obtain the same random sequence Or you can provide a new seed to interrupt the state of the engine and generate a wholly new sequence.

linear_congruential_engine<unsigned int , 16807 , 0 , 2147483> lce1 ;

for(int i=0 ; i<4 ; i++)
{
cout<< lce1( ) << ” ” ;
}

cout<< “\n\n” ;
lce.seed( ); //set the sate to the initial state

for(auto i=0 ; i<4 ; i++)
{
cout<< lce1( ) << ” ” ;
}

Output in code::blocks,

16807   1154976   582795   365602
 
16807   1154976   582795   365602

If the state is not set to it’s initial state,the generated sequence will be different.