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+
1928namespace wndx ::algo {
2029namespace gen {
2130
@@ -25,10 +34,17 @@ namespace gen {
2534 */
2635inline 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
121109template <typename T>
122110inline 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>
136125inline 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)
152142template <typename T>
153143inline 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