1#ifndef JNGEN_INCLUDE_RANDOM_INL_H2#error File "random_inl.h" must not be included directly.3#include "../random.h" // for completion engine4#endif56namespace jngen {78void assertRandomEngineConsistency() {9 std::mt19937 engine(1234);10 ENSURE(engine() == 822569775,11 "std::mt19937 doesn't conform to the C++ standard");12 ENSURE(engine() == 2137449171,13 "std::mt19937 doesn't conform to the C++ standard");14 ENSURE(engine() == 2671936806,15 "std::mt19937 doesn't conform to the C++ standard");16}1718void assertIntegerSizes() {19 static_assert(20 std::numeric_limits<unsigned char>::max() == 255,21 "max(unsigned char) != 255");22 static_assert(sizeof(int) == 4, "sizeof(int) != 4");23 static_assert(sizeof(long long) == 8, "sizeof(long long) != 8");24 static_assert(25 sizeof(size_t) == 4 || sizeof(size_t) == 8,26 "sizeof(size_t) is neither 4 nor 8");27 static_assert(28 sizeof(std::size_t) == sizeof(size_t),29 "sizeof(size_t) != sizeof(std::size_t)");30}3132void registerGen(int argc, char *argv[], int version) {33 (void)version; // unused, only for testlib.h compatibility3435 std::vector<uint32_t> seed;36 for (int i = 1; i < argc; ++i) {37 int startPosition = seed.size();38 seed.emplace_back();39 for (char *s = argv[i]; *s; ++s) {40 ++seed[startPosition];41 seed.push_back(*s);42 }43 }44 rnd.seed(seed);45}4647uint64_t maskForBound(uint64_t bound) {48 --bound;49 uint64_t mask = ~0;50 if ((mask >> 32) >= bound) mask >>= 32;51 if ((mask >> 16) >= bound) mask >>= 16;52 if ((mask >> 8 ) >= bound) mask >>= 8 ;53 if ((mask >> 4 ) >= bound) mask >>= 4 ;54 if ((mask >> 2 ) >= bound) mask >>= 2 ;55 if ((mask >> 1 ) >= bound) mask >>= 1 ;56 return mask;57}5859void Random::seed(uint32_t val) {60 randomEngine_.seed(val);61}6263void Random::seed(const std::vector<uint32_t>& seed) {64 std::seed_seq seq(seed.begin(), seed.end());65 randomEngine_.seed(seq);66}6768uint32_t Random::next() {69 return randomEngine_();70}7172uint64_t Random::next64() {73 uint64_t a = next();74 uint64_t b = next();75 return (a << 32) ^ b;76}7778double Random::nextf() {79 return (double)randomEngine_() / randomEngine_.max();80}8182int Random::next(int n) {83 ensure(n > 0);84 return uniformRandom(n, *this, (uint32_t (Random::*)())&Random::next);85}8687long long Random::next(long long n) {88 ensure(n > 0);89 return uniformRandom(n, *this, &Random::next64);90}9192size_t Random::next(size_t n) {93 ensure(n > 0);94 return uniformRandom(n, *this, &Random::next64);95}9697double Random::next(double n) {98 ensure(n >= 0);99 return nextf() * n;100}101102int Random::next(int l, int r) {103 ensure(l <= r);104 uint32_t n = static_cast<uint32_t>(r) - l + 1;105 return l + uniformRandom(106 n, *this, (uint32_t (Random::*)())&Random::next);107}108109long long Random::next(long long l, long long r) {110 ensure(l <= r);111 uint64_t n = static_cast<uint64_t>(r) - l + 1;112 return l + uniformRandom(n, *this, &Random::next64);113}114115size_t Random::next(size_t l, size_t r) {116 ensure(l <= r);117 uint64_t n = static_cast<uint64_t>(r) - l + 1;118 return l + uniformRandom(n, *this, &Random::next64);119}120121double Random::next(double l, double r) {122 ensure(l <= r);123 return l + next(r-l);124}125126int Random::wnext(int n, int w) {127 ensure(n > 0);128 if (std::abs(w) <= WNEXT_LIMIT) {129 return smallWnext<int>(w, n);130 } else {131 double t = realWnext(w);132 return n * t;133 }134}135136long long Random::wnext(long long n, int w) {137 ensure(n > 0);138 if (std::abs(w) <= WNEXT_LIMIT) {139 return smallWnext<long long>(w, n);140 } else {141 return n * realWnext(w);142 }143}144145size_t Random::wnext(size_t n, int w) {146 ensure(n > 0);147 if (std::abs(w) <= WNEXT_LIMIT) {148 return smallWnext<size_t>(w, n);149 } else {150 return n * realWnext(w);151 }152}153154double Random::wnext(double n, int w) {155 ensure(n >= 0);156 if (std::abs(w) <= WNEXT_LIMIT) {157 return smallWnext<double>(w, n);158 } else {159 return realWnext(w) * n;160 }161}162163int Random::wnext(int l, int r, int w) {164 ensure(l <= r);165 if (std::abs(w) <= WNEXT_LIMIT) {166 return smallWnext<int>(w, l, r);167 } else {168 uint32_t n = static_cast<uint32_t>(r) - l + 1;169 return l + static_cast<uint32_t>(n * realWnext(w));170 }171}172173long long Random::wnext(long long l, long long r, int w) {174 ensure(l <= r);175 if (std::abs(w) <= WNEXT_LIMIT) {176 return smallWnext<long long>(w, l, r);177 } else {178 uint64_t n = static_cast<uint64_t>(r) - l + 1;179 return l + static_cast<uint64_t>(n * realWnext(w));180 }181}182183size_t Random::wnext(size_t l, size_t r, int w) {184 ensure(l <= r);185 if (std::abs(w) <= WNEXT_LIMIT) {186 return smallWnext<size_t>(w, l, r);187 } else {188 uint64_t n = static_cast<uint64_t>(r) - l + 1;189 return l + static_cast<uint64_t>(n * realWnext(w));190 }191}192193double Random::wnext(double l, double r, int w) {194 ensure(l <= r);195 if (std::abs(w) <= WNEXT_LIMIT) {196 return smallWnext<double>(w, l, r);197 } else {198 return realWnext(w) * (r - l) + l;199 }200}201202std::string Random::next(const std::string& pattern) {203 return Pattern(pattern).next([this](int n) { return next(n); });204}205206} // namespace jngen