C++11 subtract with carry engine random number generator

The C++11 subtract with carry engine(or subtract_with_carry_engine) produces unsigned random numbers.This engine also produces pseudorandom numbers like the linear_congruential_engine.

Link :C++11 random number generator

C++11 subtract with carry engine

The declaration of the class is shown below.

template<class UIntType, size_t w, size_t s, size_t r>
class subtract_with_carry_engine;

The following relations shall hold:
0u < s ,
s < r ,
0 < w , and
w <= numeric_limits<UIntType>::digits

 
If any of the values passed as the template arguments during the object’s declaration does not agree with the above relation you will get an error.

**An algorithm of the engine is shown below,if you are only interested in the usage of the engine and not interested in how the algorithm works you can skip the next section.

Algorithm

To grasp the concept of the algorithm used by this engine,first of all consider a state of the engine as ei.This state will consist of a sequence Xi of ‘r’ integer values such that 0 < Xi < 2w,but note the subscript applied to X are to be taken modulo ‘r’.An instance of such sequence of xi state is shown below,

xi=Xi-r , … , Xi-s , … , Xi-1

i≥0 and it gives the state of the engine.

And the algorithm which produces the random number is shown below.

y= ( Xi-s – Xi-r – c ) mod 2w.

c=1 if (Xi-s – Xi-r – c) > 1 else c is 0.

The ‘y’ value is the random number outputted by the engine.

The next section shown the types and member functions of the subtract_with_carry_engine class.


Types and characteristic

typedef UIntType result_type;

static constexpr size_t word_size = w;

static constexpr size_t short_lag = s;

static constexpr size_t long_lag = r;

static constexpr result_type min() { return 0; } 

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

static constexpr result_type default_seed = 19780503u; 

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

subtract_with_carry_engine< unsigned int , 4 , 100 , 300> swce ;

cout<< swce.min() << endl
<< swce.max();

Output,

0
15

Since the smallest number of unsigned type is 0, min() returns 0 and since the maximum value is always less than 24,the next maximum value is 15 so max() returns 15.



Constructors

The C++11 subtract_with_carry_engine has two constructors.

explicit subtract_with_carry_engine(result_type value = default_seed);

template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);

The first constructor will set the value to the default_seed value if no argument is passed to the constructor.It also act as the default constructor.

The second constructor is liable to be called only if the seed value passed is other than result_type,for instance if result_type is int type but if floating point value is passed as seed then the second constructor is called.

subtract_with_carry_engine<unsigned int , 4 , 100 , 300 > swce ; //calls the first constructor

subtract_with_carry_engine<unsigned int , 4 , 100 , 300> swce1(4.56) ; //calls the second constructor

Generating function

The generating function generates the random sequence.

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

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

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

subtract_with_carry_engine<unsigned int , 4 , 100 , 300 > swce ;

cout<< swce() << ” ” << swce() ;

Output in Code::blocks,

13   6

discard(unsigned long long z)

The discard() function helps to skip some state of the engine thereby avoiding the random numbers generated by the engine in those state.The parameter ‘z’ determine how many state is skip by the engine ,if ‘z’ is 3 then the three states of engine is skip from the current state.And the following state of the engine is taken.Consider the code example below.

Note every engine object will produce the same random numbers as long as they are in the same state and the initial state of the engine is always same.

subtract_with_carry_engine<unsigned int , 4 , 100 , 300 > swce ,
  swce1 ; //swce and swce1 have the same state so they will generate same random sequence

for(auto i=0 ; i<6 ; i++)
{
cout<< swce() << ” “;
}

cout<< swce1() << ” ” ; //1st state output same as the first state output of swce 
cout<< swce() << endl ; //2nd state output same as the 2nd state output of swce

swce1.discard(3) ; //skip 3rd ,4th and 5th state

cout<< swce1() ; //6th state output same as the 6th state output of swce

Output

6 13 5 7 2 2

6 13
2



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() functions allows you to divert the state of the engine from the normal consecutive state to some other sate and thus resulting in the generation of some random numbers different from the normal state.You can also use this function to set the state to the initial state of the engine.

subtract_with_carry_engine<unsigned int , 20 , 300 , 500 > swce ;

cout<< swce4( ) << ” ” << swce4( ) << ” ” << swce4( ) << endl ;

swce4.seed() ; //set the state to it’s initial state

cout<< swce4( ) << ” ” << swce4( ) << ” ” << swce4( ) << endl ;

Output in code::blocks,

184421   989740   702902
184421   989740   702902

You can also call the first seed() function if you want to avoid the generation of the same random sequence by passing the different argument every time you run the program.


operator== and operator!= functions

These two functions will test the state of the engine.The function operator== returns true if the engine will generate the same sequence in the future,in other word it returns true if the current state of the engines are same.The operator!= compares if the two engines have different state.

subtract_with_carry_engine<unsigned int , 20 , 300 , 500 > swce , swce1 ;

cout<< (swce==swce1) << endl ;

cout< swce() << ” ” << swce() << endl ;
cout< swc1() << ” ” << swce1() << endl ;

swce.seed(23) ; //change the state of the engine
swce1.seed(78) ; //change the state of the engine

cout<< (swce==swce1) << endl ;

cout< swce() << ” ” << swce() << endl ;
cout< swc1() << ” ” << swce1() << endl ;

Output in Code::blocks,

1
989740   702902
989740   702902
0
124691   465465
554630   683266

The initial state of swce and swce1 are the same so swce==swce1 gives 1(true) and the sequence generated is also the same.But,after calling seed() on swce and swce1 their states are changed,so ‘swce==swce1’ give 0(false) and also the generated sequence is different.


operator<< and operator>> functions

Using the operator<< we can significantly save the sate of the engine.The state saved can be reused later to produce exactly the same random sequence.

The engine’s state saved is obtained using the operator>> function.If bad input is encountered while acquiring the state,the state of the engine remains unchanged but the call to setstate(ios::failbit) is triggered which may throw ios::failure exception.