Faker C++
Toggle main menu visibility
Loading...
Searching...
No Matches
helper.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <numeric>
4
#include <random>
5
#include <vector>
6
7
#include "
generator.h
"
8
#include "
number.h
"
9
10
namespace
faker::helper
11
{
12
template
<
typename
T>
13
concept
input_range_with_faster_size_compute_than_linear_rng
=
14
std::ranges::input_range<T> && (std::ranges::sized_range<T> || std::ranges::forward_range<T>);
15
16
template
<input_range_with_faster_size_compute_than_linear_rng Range>
17
decltype
(
auto
)
randomElement
(Range&& range)
18
{
19
if
(std::ranges::empty(range))
20
{
21
throw
std::invalid_argument{
"Range [start, end) is empty."
};
22
}
23
24
const
auto
size = std::ranges::distance(range);
25
26
const
auto
index =
number::integer
(size - 1);
27
28
return
(*std::ranges::next(range.begin(), index));
29
}
30
31
template
<std::ranges::input_range Range>
32
auto
randomElement
(Range&& range)
33
{
34
auto
const
end = range.end();
35
auto
itr = range.begin();
36
37
if
(itr == end)
38
{
39
throw
std::invalid_argument{
"Range [start, end) is empty."
};
40
}
41
42
std::mt19937_64& gen =
getGenerator
();
43
44
using
RangeValue = std::ranges::range_value_t<
decltype
(range)>;
45
auto
consume_itr = [&itr]() ->
decltype
(
auto
)
46
{
47
using
reference_type = std::ranges::range_reference_t<
decltype
(range)>;
48
if
constexpr
(std::is_reference_v<reference_type>)
49
{
50
return
std::move(*itr);
51
}
52
else
53
{
54
return
*itr;
55
}
56
};
57
58
RangeValue result = consume_itr();
59
60
++itr;
61
62
std::size_t count = 1;
63
64
for
(; itr != end; ++itr, ++count)
65
{
66
std::uniform_int_distribution<size_t> distrib(0, count);
67
if
(distrib(gen) == 0)
68
{
69
result = consume_itr();
70
}
71
}
72
73
return
result;
74
}
75
90
91
template
<
class
T>
92
struct
WeightedElement
93
{
94
unsigned
weight
;
95
T
value
;
96
};
97
98
template
<
class
T>
99
T
weightedRandomElement
(
const
std::vector<
WeightedElement<T>
>& data)
100
{
101
if
(data.empty())
102
{
103
throw
std::invalid_argument{
"Data is empty."
};
104
}
105
106
const
auto
sumOfWeights =
107
std::accumulate(data.begin(), data.end(), 0u,
108
[](
unsigned
sum,
const
WeightedElement<T>
& element) { return sum + element.weight; });
109
110
if
(sumOfWeights == 0u)
111
{
112
throw
std::invalid_argument{
"Sum of weights cannot be zero."
};
113
}
114
115
const
auto
targetWeightValue =
number::integer
(1u, sumOfWeights);
116
117
auto
currentSum = 0u;
118
119
for
(
const
auto
& elem : data)
120
{
121
currentSum += elem.weight;
122
123
if
(currentSum > targetWeightValue)
124
{
125
return
elem.value;
126
}
127
}
128
129
return
data.back().value;
130
}
131
132
}
faker::helper::input_range_with_faster_size_compute_than_linear_rng
Definition
helper.h:13
generator.h
faker::helper
Definition
helper.h:11
faker::helper::weightedRandomElement
T weightedRandomElement(const std::vector< WeightedElement< T > > &data)
Definition
helper.h:99
faker::helper::randomElement
decltype(auto) randomElement(Range &&range)
Definition
helper.h:17
faker::number::integer
I integer(I min, I max)
Generates a random integer number in the given range, bounds included.
Definition
number.h:33
faker::getGenerator
FAKER_CXX_EXPORT std::mt19937_64 & getGenerator()
number.h
faker::helper::WeightedElement
Get a random element by weight from a vector.
Definition
helper.h:93
faker::helper::WeightedElement::weight
unsigned weight
Definition
helper.h:94
faker::helper::WeightedElement::value
T value
Definition
helper.h:95
include
faker-cxx
helper.h
Generated by
1.17.0