Skip to content

Instantly share code, notes, and snippets.

@elbeno
Last active November 14, 2016 14:59
Show Gist options
  • Save elbeno/b6dfd9d32ab209d36ac97434e9894dda to your computer and use it in GitHub Desktop.
Save elbeno/b6dfd9d32ab209d36ac97434e9894dda to your computer and use it in GitHub Desktop.
Uniform distributions with chrono durations
#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