Skip to content

Commit e42b28b

Browse files
committed
[gen.hpp] WNDX_ALGO_FIXED_SEED, explicit std::move, cleanup,
WNDX_MSC - non cryptographic randomness via chrono time_since_epoch(). explicit std::move containers - to not rely on NRVO (named return value optimization).
1 parent 196aa4f commit e42b28b

File tree

1 file changed

+26
-68
lines changed

1 file changed

+26
-68
lines changed

include/wndx/algo/util/gen.hpp

Lines changed: 26 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
#endif//defined ...
1717
#endif//WNDX_MSC
1818

19+
#ifndef WNDX_ALGO_FIXED_SEED
20+
#define WNDX_ALGO_FIXED_SEED 0
21+
#endif//WNDX_ALGO_FIXED_SEED
22+
23+
#if WNDX_MSC && !WNDX_ALGO_FIXED_SEED
24+
#include <chrono>
25+
#include <cstdint> // std::uint64_t
26+
#endif//WNDX_MSC
27+
1928
namespace wndx::algo {
2029
namespace gen {
2130

@@ -25,10 +34,17 @@ namespace gen {
2534
*/
2635
inline std::mt19937& g_rng()
2736
{
28-
#if WNDX_MSC
37+
#if WNDX_MSC || WNDX_ALGO_FIXED_SEED
2938
// deterministic seeding! std::random_device => drmemory "WARNING: writing to readonly memory".
3039
// because of the SH*TTY WIN random_* implementation: BCryptGenRandom, CryptGenRandom, etc.
31-
constexpr int seed{ 123456 };
40+
#if WNDX_ALGO_FIXED_SEED
41+
constexpr std::size_t seed{ 9876543210 }; // fixed seed (value chosen arbitrarily)
42+
#else
43+
static const auto now{ std::chrono::steady_clock::now().time_since_epoch() };
44+
static const std::uint64_t seed{ static_cast<std::uint64_t>(
45+
std::chrono::duration_cast<std::chrono::seconds>(now).count()
46+
)};
47+
#endif//WNDX_ALGO_FIXED_SEED
3248
static std::mt19937 s_rng(seed);
3349
#else
3450
static std::random_device s_rd;
@@ -37,33 +53,6 @@ inline std::mt19937& g_rng()
3753
return s_rng;
3854
}
3955

40-
#if 0
41-
/**
42-
* @brief simple random number generator.
43-
*
44-
* @param fr - range from the number (lower bound of the distribution).
45-
* @param to - range to the number (upper bound of the distribution).
46-
* @return random number in range of distribution.
47-
*
48-
* NOTE: construcs a new std::random_device and engine on every call
49-
* => expensive and can degrade randomness on some platforms.
50-
*/
51-
template<typename T>
52-
inline T srng(const T fr, const T to)
53-
{
54-
#if WNDX_MSC
55-
// deterministic seeding! std::random_device => drmemory error "UNADDRESSABLE ACCESS: reading".
56-
// because of the SH*TTY WIN random_* implementation: BCryptGenRandom, CryptGenRandom, etc.
57-
constexpr int seed{ 123456 };
58-
std::default_random_engine rng(seed);
59-
#else
60-
std::random_device rd;
61-
std::default_random_engine rng(rd());
62-
#endif
63-
std::uniform_real_distribution<double> dist(static_cast<double>(fr), static_cast<double>(to));
64-
return static_cast<T>(dist(rng));
65-
}
66-
#else
6756
/**
6857
* @brief simple random number generator.
6958
*
@@ -82,7 +71,6 @@ inline T srng(const T fr, const T to)
8271
return dist(g_rng());
8372
}
8473
}
85-
#endif
8674

8775
/**
8876
* @brief @return generate random unordered_set containing n unique elements.
@@ -108,11 +96,11 @@ inline std::unordered_set<T> random_uset(const std::size_t n, const T fr, const
10896
} while(!((uset.insert(rn)).second));
10997
// ^ loop till successful insert of unique value
11098
}
111-
return uset;
99+
return std::move(uset);
112100
}
113101

114102
/**
115-
* @brief generate random C array.
103+
* @brief random fill C-style array.
116104
*
117105
* @param fr - range from the number (lower bound of the distribution).
118106
* @param to - range to the number (upper bound of the distribution).
@@ -121,8 +109,9 @@ inline std::unordered_set<T> random_uset(const std::size_t n, const T fr, const
121109
template<typename T>
122110
inline void random(T *out, const std::size_t n, const T fr, const T to)
123111
{
124-
for (std::size_t i = 0; i < n; i++)
112+
for (std::size_t i = 0; i < n; i++) {
125113
out[i] = gen::srng<T>(fr, to);
114+
}
126115
}
127116

128117
/**
@@ -136,9 +125,10 @@ template<typename T, std::size_t n>
136125
inline std::array<T, n> random(const T fr, const T to)
137126
{
138127
std::array<T, n> out;
139-
for (std::size_t i = 0; i < n; i++)
128+
for (std::size_t i = 0; i < n; i++) {
140129
out.at(i) = gen::srng<T>(fr, to);
141-
return out;
130+
}
131+
return std::move(out);
142132
}
143133

144134
/**
@@ -152,48 +142,16 @@ inline std::array<T, n> random(const T fr, const T to)
152142
template<typename T>
153143
inline std::vector<T> random(const std::size_t n, const T fr, const T to, const bool unique=false)
154144
{
155-
// if (n == 0) return {}; // XXX
156145
if (unique) {
157146
std::unordered_set<T> uset{ gen::random_uset<T>(n, fr, to) };
158147
return{ uset.begin(), uset.end() };
159148
}
160-
#if 1
161149
std::vector<T> out(n);
162-
#else
163-
std::vector<T> out;
164-
out.reserve(n); // allocate space but keep size = 0
165-
// out.resize(n); // size bocomes n
166-
#endif
167-
// std::random_device rd;
168-
// std::mt19937 rng(rd());
169-
#if 0
170-
// drmemory UNADDRESSABLE ACCESS: reading
171-
std::uniform_int_distribution<T> dist(fr, to);
172-
std::generate_n(out.begin(), n, [&rng, &dist]() { return dist(rng); });
173-
#else
174150
for (std::size_t i = 0; i < n; i++) {
175-
#if 1
176151
out.at(i) = gen::srng<T>(fr, to);
177-
// out[i] = gen::srng<T>(fr, to);
178-
#elif 1
179-
out[i] = static_cast<T>(to); // XXX
180-
#elif 1
181-
std::uniform_int_distribution<T> dist(fr, to);
182-
T val = dist(rng);
183-
out[i] = val;
184-
#elif 0
185-
std::uniform_int_distribution<T> dist; // default ctor
186-
dist.param(typename std::uniform_int_distribution<T>::param_type(fr, to));
187-
out[i] = dist(rng);
188-
#else
189-
T val = gen::srng<T>(fr, to); // ensure a copy, not a reference | copy from read-only source
190-
out[i] = val;
191-
#endif
192152
}
193-
#endif
194153
return std::move(out);
195-
// return out; // rely on NRVO (named return value optimization)
196154
}
197155

198156
} // namespace gen
199-
} // namespace wndx::algo
157+
} // namespace wndx::algo

0 commit comments

Comments
 (0)