32 #include "eng3d/rand.hpp"
40 std::vector<T> _items;
41 std::vector<float> alias;
42 std::vector<float> prob;
49 assert(!items.empty() && !probabilities.empty());
51 const auto total = std::accumulate(probabilities.begin(), probabilities.end(), 0.f);
53 const auto scale = probabilities.size() / total;
54 for(
auto& p : probabilities) p *= scale;
57 std::vector<std::pair<float, size_t>> small;
58 small.reserve(probabilities.size());
59 std::vector<std::pair<float, size_t>> big;
60 big.reserve(probabilities.size());
61 for(
size_t i = 0; i < probabilities.size(); i++) {
62 if(probabilities[i] < 1.0f) small.emplace_back(probabilities[i], i);
63 else big.emplace_back(probabilities[i], i);
67 alias.resize(probabilities.size(), 0);
68 prob.resize(probabilities.size(), 0);
69 while(!small.empty() && !big.empty()) {
70 const auto& [less_prob, less_index] = small.back();
71 const auto& [greater_prob, greater_index] = big.back();
73 prob[less_index] = less_prob;
74 alias[less_index] = greater_index;
76 auto final_prob = (greater_prob + less_prob) - 1;
77 if(final_prob < 1.f) small.emplace_back(greater_prob, greater_index);
78 else big.emplace_back(greater_prob, greater_index);
81 for(
const auto& [_, index] : big)
85 for(
const auto& [_, index] : small)
93 auto index = _rand() % _items.size();
94 auto r =
static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
95 if(prob[index] < r) index = alias[index];
Uses the Aiias method to generate a lookup table of with different probabilties.
~DiscreteDistribution()=default
DiscreteDistribution(std::vector< T > items, std::vector< float > probabilities)
T get_item()
Get a random item with a certian probabilty, thread safe.
Thread safe random number generator.