C++11 piecewise linear distribution random number generator

The C++11 piecewise linear distribution(or piecewise_linear_distribution) produces floating point random values ‘x’ using a specific probability density function-the function is provided at the end of this post.
Link :C++ random number generator
 
C++11 piecewise linear distribution

The piecewise_linear_distribution template class declaration is shown below.

template<class RealType = double>
  class piecewise_linear_distribution;

The default type of the distribution is ‘double’ type ,so the default constructed object always produce double type random numbers.

All the distribution’s types and member function is given below.


Types

typedef IntType result_type;

typedef unspecified param_type;

The param_type is as structure whose definition is compiler dependent,that is also why it’s type is mentioned as unspecified.



Constructors and reset function

piecewise_linear_distribution();

template<class InputIteratorB, class InputIteratorW>
piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);

template<class UnaryOperation>
piecewise_linear_distribution(initializer_list&lt;RealType&gt; bl, UnaryOperation fw); 

template<class UnaryOperation>
piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);

explicit piecewise_linear_distribution(const param_type& parm);

void reset( );

You can see that the piecewise_linear_distribution have five constructors:
 
a)The first constructor is the default constructor.
 
b)The second constructor accept three arguments:firstB and lastB iterator pointing to the first and one past the last element of the same container and the firstW iterator pointing to another different container.The container can be vector or an array or any equivalent type.And note the third iterator must point to container having at least the same number of elements as the container pointed by the first iterator.
 
c)The third constructor accept initializer_list and a function.The initializer_list type must be real type and the function must return a double type or any type convertible to double type.
 
d)The fourth constructor accept 4 arguments.Refer to the first three arguments type from the above declaration and the fourth argument is a function which return a double type or a type convertible to double type.
 
e)The fifth constructor accept param_type object.

The program below shows how to call all the constructors.

double func(double arg)
{
return arg;
}

int main( )
{
piecewise_linear_distribution< > pcd; //calls the default constructor

vector<int> vec={ 0 , 2 , 1 } , vec1={ 12 , 3 , 14 };

piecewise_linear_distribution< > pld1( vec.begin( ) , vec.end() , vec1.begin( ) ); //calls the second constructor

initializer_list< double > il={ 4.5 , 0.2 , 0.123 };
piecewise_linear_distribution< > pld2( il , func ); //calls the third constructor

piecewise_linear_distribution<float > pld3( 18 , 0 , 300 , func ); //calls the 4th constructor

piecewise_linear_distribution<float >::param_type pt;

piecewise_linear_distribution<float > pld4(pt) ; //calls the 5th constructor

piecewise_linear_distribution< > pld5(pt) ; //error! pt is ‘float’ type but pld5 is ‘double’ type

return 0;
}

The reset() function reset the state of the distribution.It does nothing in discrete_distribution so you can neglect it.


Generating functions

template<class URNG>
result_type operator( )(URNG& g);

template<class URNG>
result_type operator( )(URNG& g, const param_type& parm); 

The generating functions give you an access to the random number sequence.

the first operator() function

The first overloaded operator() accept URNG(Uniform Random Number Generator) or engine.

piecewise_linear_distribution< > pld ;

mersenne_twister_engine<unsigned int , 32 , 624 , 397 , 31 ,
  0x9908b0dfUL, 11 ,
  0xffffffffUL, 7 ,
  0x9d2c5680UL, 15 ,
  0xefc60000UL, 18 , 1812433253UL > mte ;

cout<< pld( mte ) << ” ” << pld( mte ) ;

Output in Code::blocks,

0.835009   0.135477

the second operator( ) function

The second overloaded operator( ) function accept URNG and param_type object.

initializer_list< double > il={ 4.5 , 0.2 , 0.123 };

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

piecewise_linear_distribution< >::param_type pt( il , func );

piecewise_linear_distribution< >pld ;

cout<< pld( lce , pt ) << ” ” << pld( lce , pt ) ;

Output in Code::blocks,

-2.82485   -4.17875



Property functions

vector<result_type> intervals( ) const;

vector<result_type> densities( ) const;

param_type param() const; 

void param(const param_type& parm); 

result_type min( ) const;

result_type max( ) const; 
vector<result_type> intervals( ) const;

This function returns vector of result_type.The content of the returned vector will depend on which constructor is called during the object creation:
 
a)If default constructor is called the return vector consists of only two elements 0 and 1.
Nbsp;
b)If the second constructor is called the return vector content is same as the content of the container whose iterators pointing to the first and one past the last element is passed as the first and second argument.Simply if ‘vec.begin()’ and ‘vec.end()’ -vec is any vector object- are passed as the first and second iterator then ‘vec’ content is returned.
 
c)If the third constructor is called.The returned vector will have the element as the initializer_list content.
 
d)If the fourth constructor is called then the content is
bk=xmin+k · δ , k=0 , 1, 2 … n,
 
0 < δ= (xmax − xmin ) /n, xmax is the third argument and xmin is the fourth argument and ‘n’ is the first argument passed to the constructor.

e)If the fifth constructor is called,the param_type object may call any of the four constructors describe above then the content of the returned vector will hold true as described for each of the constructor called.

piecewise_linear_distribution< > pld ;

vector<double> vec={0 , 0 };

vec=pld.intervals( );

cout<< vec[0] << ” ” vec[1] << “\n\n” ;

vector< double > vec1={ 1.2 , 0.34 , 1.45 , .010 } , vec3={ 0 , 0 , 0 , 0};

vector< double > vecRet{ 0 , 0 , 0 , 1};

piecewise_linear_distribution< >::param_type pt( vec1.begin( ) , vec1.end( ) , vec3.begin( ) );

piecewise_linear_distribution< > pld1( pt ) ;

vecRet=pcd1.intervals( );

for(auto elem:vecRet )
{
cout<< elem << ” ” ;
}

Output,

0   1
1.2   0.34   1.45   .010

The ‘pt’ accepted ‘vec.begin()’ and ‘vec.end()’ as the first and second iterator so the returned vector vecRet content is same as the content of ‘vec’.

densities( ) const; function

This function returns a vector of double type.The returned vector stores the probability densities of the random number generated by the distribution.The nth element of the vector will correspond to the probabilities of the nth generated random number.

vector<int> vec={ 9 , 0.7 , 1.23 } , vec1={ 9 , 0.7 , 1.23 };

vector<int> vecret={ 0 , 0 , 0};

piecewise_linear_distribution< > pld(vec.begin() , vec.end() , vec1.begin() ) ;

vecRet=pld.densities( ) ;

cout<< vecRet[0] << ” ” << vecRet[1] << ” ” vecRet[2] ;

Output,

1.54772   0.120378   0.211522

param( )

This function returns the param_type object.

piecewise_linear_distribution< >pld ;

piecewise_linear_distribution< >::param_type pt ;

pt=pcd.param( ) ;
param(param_type)

Using this function we can change the parameter of the distribution to the parameter of the param_type object by passing the param_type object.

initializer_list< double > il ={ 0.12 , 30.23 } ,
  il1={ 90 , 100 };

vector<double > vec1={0 , 0} ,
vec2={ 0 , 0}

piecewise_linear_distribution< > pcd(il) ;

vec1=pcd.interval( );

cout<< vec1[0] << ” ” << vec1[1] << endl;

piecewise_linear_distribution< >::param_type pt(il1 , func) ; //func is same as func from the constructor section code.

pcd.param( pt );

vec2=pcd.intervals( );

cout<< vec1[0] << ” ” << vec1[1] ;

Output ,

0.12   30.23
90   100

Calling param(pt) changes the parameter of the pcd to pt parameter values.

min() function

The min() returns the smallest value the distribution can generate,which is the value 0.

piecewise_linear_distribution< > pld ;

cout<< pcd.min( ) ;

Output ,

0

max() function

The max() returns the largest value the distribution can generate.

piecewise_linear_distribution< > pld( 90 , 0 , 500 , func );

cout<< pld.max( ) ; 

Output ,

500