← comparison · impl/random_inl.h
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