Newer
Older

Christian Godenschwager
committed
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file Random.h
//! \ingroup core
//! \author Florian Schornbaum <florian.schornbaum@fau.de>
//
//======================================================================================================================
#pragma once
#include "core/DataTypes.h"
#include "core/debug/Debug.h"

Christian Godenschwager
committed
#include <limits>
namespace walberla {
namespace math {
namespace internal {
std::mt19937 & getGenerator(); // std::mt19937_64

Christian Godenschwager
committed
}
void seedRandomGenerator( const std::mt19937::result_type & seed ); // std::mt19937_64

Christian Godenschwager
committed
//**********************************************************************************************************************
/*!
* \brief Returns a random integral number of type INT in the range [min,max] (max included!)
*/
//**********************************************************************************************************************
template< typename INT >
INT intRandom( const INT min, const INT max, std::mt19937 & generator )

Christian Godenschwager
committed
{
static_assert_int_t< INT >();
static_assert(sizeof(INT) > sizeof(char), "cannot use char");

Christian Godenschwager
committed
WALBERLA_ASSERT_LESS_EQUAL( min, max );
std::uniform_int_distribution< INT > distribution( min, max );

Christian Godenschwager
committed
INT value;
#ifdef _OPENMP
#pragma omp critical (random)
#endif
{ value = distribution( generator ); }
return value;
}
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
template<>
inline char intRandom<char>( const char min, const char max, std::mt19937 & generator )
{
static_assert_int_t< char >();
WALBERLA_ASSERT_LESS_EQUAL( min, max );
std::uniform_int_distribution< int16_t > distribution( min, max );
char value;
#ifdef _OPENMP
#pragma omp critical (random)
#endif
{ value = static_cast<char>( distribution( generator ) ); }
return value;
}
template<>
inline unsigned char intRandom<unsigned char>( const unsigned char min, const unsigned char max, std::mt19937 & generator )
{
static_assert_int_t< unsigned char >();
WALBERLA_ASSERT_LESS_EQUAL( min, max );
std::uniform_int_distribution< int16_t > distribution( min, max );
unsigned char value;
#ifdef _OPENMP
#pragma omp critical (random)
#endif
{ value = static_cast<unsigned char>( distribution( generator ) ); }
return value;
}
template<>
inline signed char intRandom<signed char>( const signed char min, const signed char max, std::mt19937 & generator )
{
static_assert_int_t< signed char >();
WALBERLA_ASSERT_LESS_EQUAL( min, max );
std::uniform_int_distribution< int16_t > distribution( min, max );
signed char value;
#ifdef _OPENMP
#pragma omp critical (random)
#endif
{ value = static_cast<signed char>( distribution( generator ) ); }
return value;
}

Christian Godenschwager
committed
template< typename INT >
INT intRandom( const INT min )
{
return intRandom( min, std::numeric_limits<INT>::max(), internal::getGenerator() );
}
template< typename INT >
INT intRandom( const INT min, const INT max )
{
return intRandom( min, max, internal::getGenerator() );
}
template< typename INT >
INT intRandom()
{
return intRandom( std::numeric_limits<INT>::min(), std::numeric_limits<INT>::max() );
}

Christian Godenschwager
committed
template< typename INT >
class IntRandom
{
public:
IntRandom( const std::mt19937::result_type & seed = std::mt19937::result_type() ) { generator_.seed( seed ); }

Christian Godenschwager
committed
INT operator()( const INT min = std::numeric_limits<INT>::min(), const INT max = std::numeric_limits<INT>::max() )
{
return intRandom( min, max, generator_ );
}
private:

Christian Godenschwager
committed
};
//**********************************************************************************************************************
/*!
* \brief Returns a random floating point number of type REAL in the range [min,max) (max excluded!)
*/
//**********************************************************************************************************************
template< typename REAL >
REAL realRandom( const REAL min = REAL(0), const REAL max = REAL(1), std::mt19937 & generator = internal::getGenerator() )

Christian Godenschwager
committed
{
static_assert( std::numeric_limits<REAL>::is_specialized && !std::numeric_limits<REAL>::is_integer, "Floating point type required/expected!" );
WALBERLA_ASSERT_LESS( min, max );
std::uniform_real_distribution< REAL > distribution( min, max );

Christian Godenschwager
committed
REAL value;
#ifdef _OPENMP
#pragma omp critical (random)
#endif
{ value = distribution( generator ); }
return value;
}
template< typename REAL >
class RealRandom
{
public:
RealRandom( const std::mt19937::result_type & seed = std::mt19937::result_type() ) { generator_.seed( seed ); }

Christian Godenschwager
committed
REAL operator()( const REAL min = REAL(0), const REAL max = REAL(1) )
{
return realRandom( min, max, generator_ );
}
private:

Christian Godenschwager
committed
};
inline bool boolRandom() { ///< Randomly returns 'true' or 'false'
return realRandom<real_t>() >= real_t(0.5);
}
class BoolRandom
{
public:
BoolRandom( const std::mt19937::result_type & seed = std::mt19937::result_type() ) { generator_.seed( seed ); }

Christian Godenschwager
committed
bool operator()() { return boolRandom(); }
private:

Christian Godenschwager
committed
};
} // namespace math
} // namespace walberla