-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathRandom.hpp
127 lines (115 loc) · 3.73 KB
/
Random.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
120
121
122
123
124
125
126
127
//
// Random.hpp
// Maw Kit
//
// Created by Lluís Ulzurrun de Asanza Sàez on 18/02/16.
//
//
#ifndef Random_hpp
#define Random_hpp
#include <iterator>
#include <random>
#include <type_traits>
#include <vector>
namespace MK {
/**
* `Random` namespace features utilities to get random numbers.
*/
namespace Random {
/**
* Returns a random iterator between given `start` and `end` iterators,
* using given generator `g` to compute randomness.
*
* @param start First iterator that can be selected.
* @param end Last iterator, it cannot be selected.
* @param g Generator of randomness.
*
* @return Random iterator between given `start` and `end` iterators.
*/
template <typename Iter, typename RandomGenerator>
Iter Choose( Iter start, Iter end, RandomGenerator &g )
{
std::uniform_int_distribution<> dis( 0, static_cast<int>(
std::distance( start, end ) - 1 ) );
std::advance( start, dis( g ) );
return start;
}
/**
* Returns a random iterator between given `start` and `end` iterators,
* using uniform probability.
*
* @param start First iterator that can be selected.
* @param end Last iterator, it cannot be selected.
*
* @return Random iterator between given `start` and `end` iterators.
*/
template <typename Iter> Iter Choose( Iter start, Iter end )
{
static std::random_device rd;
static std::mt19937 gen( rd() );
return Choose( start, end, gen );
}
/**
* Returns a random value in given vector.
*
* @param vector Vector containing value to be returned.
*
* @return Random value in given vector.
*/
template <class VectorValue>
VectorValue Choose( const std::vector<VectorValue> &vector )
{
return *Choose( vector.begin(), vector.end() );
}
/**
* Returns a floating point number in range \f$\left[\mbox{min},\mbox{max}
* \right)\f$.
*
* @param min Minimum value (included) in the range.
* @param max Maximum value (**not included**) in the range.
*
* @return Floating point number in range \f$\left[\mbox{min},\mbox{max}
* \right)\f$.
*/
template <typename Number, typename = typename std::enable_if<std::is_arithmetic<Number>::value, Number>::type>
const double FloatingPointNumberInRange( const Number min, const Number max )
{
return static_cast<double>( std::rand() ) / RAND_MAX * ( max - min ) + min;
}
/**
* Returns an integer number in closed range \f$\left[\mbox{min},\mbox{max}
* \right]\f$.
*
* @param min Minimum value (included) in the range.
* @param max Maximum value (included) in the range.
*
* @return Integer number in closed range \f$\left[\mbox{min},\mbox{max}
* \right]\f$.
*/
template <typename IntegerNumber,
typename = typename std::enable_if<std::is_integral<IntegerNumber>::value, IntegerNumber>::type>
const IntegerNumber IntegerNumberInRange( const IntegerNumber min, const IntegerNumber max )
{
return static_cast<IntegerNumber>(
static_cast<double>( std::rand() ) / RAND_MAX * ( max - min + 1 ) + min );
}
/**
* Given a probability (floating point number between zero and one, both
* included) returns a random boolean value which will be `true`
* \f$\mbox{number}\times100\%\f$ of times this method is called and `false`
* the other \f$\left(1-\mbox{number}\right)\times100\%\f$.
*
* @param number Probability of returning `true`.
*
* @return Randomly `true` or `false` taking into account given `true`
* probability.
*/
template <typename FPNumberBetweenZeroAndOne,
typename = typename std::enable_if<std::is_arithmetic<FPNumberBetweenZeroAndOne>::value, FPNumberBetweenZeroAndOne>::type>
const bool TakeChance( const FPNumberBetweenZeroAndOne number )
{
return FloatingPointNumberInRange( 0, 1 ) <= number;
}
}; // namespace Random
}; // namespace MK
#endif /* Random_hpp */