66 lines
1.5 KiB
C++
66 lines
1.5 KiB
C++
#pragma once
|
|
|
|
#include <psemek/random/uniform_int.hpp>
|
|
#include <psemek/random/uniform_real.hpp>
|
|
|
|
#include <psemek/geom/constants.hpp>
|
|
#include <psemek/geom/box.hpp>
|
|
|
|
#include <type_traits>
|
|
#include <stdexcept>
|
|
|
|
namespace psemek::random
|
|
{
|
|
|
|
template <typename T>
|
|
using uniform_distribution = std::conditional_t<std::is_floating_point_v<T>, uniform_real_distribution<T>, uniform_int_distribution<T>>;
|
|
|
|
template <typename T, typename RNG>
|
|
T uniform(RNG && rng, geom::interval<T> const & range)
|
|
{
|
|
return uniform_distribution<T>{range}(rng);
|
|
}
|
|
|
|
template <typename T, typename RNG>
|
|
T uniform(RNG && rng, T min, T max)
|
|
{
|
|
return uniform<T>(rng, {min, max});
|
|
}
|
|
|
|
template <typename T, typename RNG>
|
|
T uniform(RNG && rng)
|
|
{
|
|
if constexpr (std::is_same_v<T, bool>)
|
|
{
|
|
return uniform<char>(rng, 0, 1) == 1;
|
|
}
|
|
else
|
|
{
|
|
return uniform<T>(rng, T{0}, T{1});
|
|
}
|
|
}
|
|
|
|
template <typename T, std::size_t N, typename RNG>
|
|
geom::point<T, N> uniform(RNG && rng, geom::box<T, N> const & box)
|
|
{
|
|
geom::point<T, N> result;
|
|
for (std::size_t i = 0; i < N; ++i)
|
|
result[i] = uniform<T>(rng, box[i]);
|
|
return result;
|
|
}
|
|
|
|
template <typename T, typename RNG>
|
|
T uniform_angle(RNG && rng)
|
|
{
|
|
return uniform(rng, T{0}, T{2 * geom::pi});
|
|
}
|
|
|
|
template <typename RNG, typename Container>
|
|
auto & uniform_from(RNG && rng, Container & container)
|
|
{
|
|
if (container.empty())
|
|
throw std::runtime_error("cannot sample from empty container");
|
|
return container[uniform<std::size_t>(rng, 0, container.size() - 1)];
|
|
}
|
|
|
|
}
|