Last active
November 14, 2016 14:59
-
-
Save elbeno/b6dfd9d32ab209d36ac97434e9894dda to your computer and use it in GitHub Desktop.
Uniform distributions with chrono durations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <array> | |
#include <chrono> | |
#include <functional> | |
#include <iostream> | |
#include <iterator> | |
#include <limits> | |
#include <random> | |
#include <type_traits> | |
using namespace std; | |
template <typename A, typename B = A, | |
typename C = std::common_type_t<A, B>, | |
typename D = std::uniform_int_distribution<C>> | |
inline auto make_uniform_distribution(const A& a, | |
const B& b = std::numeric_limits<B>::max()) | |
-> std::enable_if_t<std::is_integral<C>::value, D> | |
{ | |
return D(a, b); | |
} | |
template <typename A, typename B = A, | |
typename C = std::common_type_t<A, B>, | |
typename D = std::uniform_real_distribution<C>> | |
inline auto make_uniform_distribution(const A& a, | |
const B& b = B{1}) | |
-> std::enable_if_t<std::is_floating_point<C>::value, D> | |
{ | |
return D(a, b); | |
} | |
template <typename T> | |
struct is_duration : std::false_type {}; | |
template <typename Rep, typename Period> | |
struct is_duration<std::chrono::duration<Rep, Period>> : std::true_type {}; | |
template <typename Duration = std::chrono::system_clock::duration, | |
typename = std::enable_if_t<is_duration<Duration>::value>> | |
class uniform_duration_distribution | |
{ | |
public: | |
using result_type = Duration; | |
explicit uniform_duration_distribution( | |
const Duration& a = Duration::zero(), | |
const Duration& b = Duration::max()) | |
: m_a(a), m_b(b) | |
{} | |
void reset() {} | |
template <typename Generator> | |
result_type operator()(Generator& g) | |
{ | |
auto d = make_uniform_distribution(m_a.count(), m_b.count()); | |
return result_type(d(g)); | |
} | |
result_type a() const { return m_a; } | |
result_type b() const { return m_b; } | |
result_type min() const { return m_a; } | |
result_type max() const { return m_b; } | |
private: | |
result_type m_a; | |
result_type m_b; | |
}; | |
template <typename A, typename B = A, | |
typename C = std::common_type_t<A, B>, | |
typename D = uniform_duration_distribution<C>> | |
inline auto make_uniform_distribution(const A& a, | |
const B& b = B::max()) -> D | |
{ | |
return D(a, b); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
std::array<int, std::mt19937::state_size> seed_data; | |
std::random_device r; | |
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r)); | |
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); | |
std::mt19937 gen(seq); | |
using namespace std::literals::chrono_literals; | |
auto d1 = make_uniform_distribution(0); | |
auto d2 = make_uniform_distribution(0.0); | |
auto d3 = make_uniform_distribution(0s, 5s); | |
cout << d1(gen) << endl; | |
cout << d2(gen) << endl; | |
cout << d3(gen).count() << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment