Loading include/cxx/random +41 −7 Changes for include/cxx/random: 41 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -402,21 +402,55 @@ public: if (range == ~0ULL) return (IntType)(_a + (unsigned long long)g()); unsigned long long range_size = range + 1; unsigned long long range_size = range + 1; /* no overflow: range != ~0 */ unsigned long long gen_min = (unsigned long long)Generator::min(); unsigned long long gen_span = (unsigned long long)Generator::max() - gen_min; /* gen_span+1 only overflows when the generator's own native * width equals the full 64-bit range, which is exactly the * case already handled above -- safe here. */ if (gen_span >= range) { /* Rejection sampling over the generator's own range. Real * bug fixed: for a full-width generator (mt19937_64, * gen_span == ~0) gen_span+1 wrapped to 0, so limit was 0, * every draw was rejected and this looped forever -- e.g. * uniform_int_distribution<size_t>(0, n-1)(mt19937_64), * proxyplus' random load balancing. Count 2^64 mod n * without forming 2^64. */ unsigned long long limit; /* accept r < limit; 0 = accept all */ if (gen_span == ~0ULL) { unsigned long long rem = (~0ULL % range_size + 1) % range_size; limit = rem ? 0 - rem : 0; /* 2^64 - rem, mod 2^64 */ } else { unsigned long long gen_range_size = gen_span + 1; unsigned long long limit = gen_range_size - (gen_range_size % range_size); limit = gen_range_size - (gen_range_size % range_size); } unsigned long long r; do { r = (unsigned long long)g() - gen_min; } while (r >= limit); } while (limit && r >= limit); return (IntType)(_a + (r % range_size)); } /* Generator narrower than the range (mt19937 for a 64-bit * range; before, limit came out 0 and this hung too): gather * uniform 64-bit values from whole power-of-two chunks of the * generator's output, then reject as above. */ unsigned h = 0; /* highest set bit of gen_span */ while ((gen_span >> h) > 1) ++h; /* largest 2^bits <= gen_span+1: one more bit only when gen_span * is all ones (mt19937: 2^32-1 -> 32 bits; minstd: 2^31-3 -> 30) */ unsigned bits = (h < 63 && gen_span == (1ULL << (h + 1)) - 1) ? h + 1 : h; if (bits == 0) bits = 1; /* gen_span >= 1 for any real engine */ unsigned long long chunk = 1ULL << bits; unsigned long long rem = (~0ULL % range_size + 1) % range_size; unsigned long long limit = rem ? 0 - rem : 0; unsigned long long r; do { r = 0; for (unsigned got = 0; got < 64; got += bits) { unsigned long long d; do { d = (unsigned long long)g() - gen_min; } while (d >= chunk); r = (r << bits) | d; /* bits beyond 64 fall off: still uniform */ } } while (limit && r >= limit); return (IntType)(_a + (r % range_size)); } Loading Loading
include/cxx/random +41 −7 Changes for include/cxx/random: 41 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -402,21 +402,55 @@ public: if (range == ~0ULL) return (IntType)(_a + (unsigned long long)g()); unsigned long long range_size = range + 1; unsigned long long range_size = range + 1; /* no overflow: range != ~0 */ unsigned long long gen_min = (unsigned long long)Generator::min(); unsigned long long gen_span = (unsigned long long)Generator::max() - gen_min; /* gen_span+1 only overflows when the generator's own native * width equals the full 64-bit range, which is exactly the * case already handled above -- safe here. */ if (gen_span >= range) { /* Rejection sampling over the generator's own range. Real * bug fixed: for a full-width generator (mt19937_64, * gen_span == ~0) gen_span+1 wrapped to 0, so limit was 0, * every draw was rejected and this looped forever -- e.g. * uniform_int_distribution<size_t>(0, n-1)(mt19937_64), * proxyplus' random load balancing. Count 2^64 mod n * without forming 2^64. */ unsigned long long limit; /* accept r < limit; 0 = accept all */ if (gen_span == ~0ULL) { unsigned long long rem = (~0ULL % range_size + 1) % range_size; limit = rem ? 0 - rem : 0; /* 2^64 - rem, mod 2^64 */ } else { unsigned long long gen_range_size = gen_span + 1; unsigned long long limit = gen_range_size - (gen_range_size % range_size); limit = gen_range_size - (gen_range_size % range_size); } unsigned long long r; do { r = (unsigned long long)g() - gen_min; } while (r >= limit); } while (limit && r >= limit); return (IntType)(_a + (r % range_size)); } /* Generator narrower than the range (mt19937 for a 64-bit * range; before, limit came out 0 and this hung too): gather * uniform 64-bit values from whole power-of-two chunks of the * generator's output, then reject as above. */ unsigned h = 0; /* highest set bit of gen_span */ while ((gen_span >> h) > 1) ++h; /* largest 2^bits <= gen_span+1: one more bit only when gen_span * is all ones (mt19937: 2^32-1 -> 32 bits; minstd: 2^31-3 -> 30) */ unsigned bits = (h < 63 && gen_span == (1ULL << (h + 1)) - 1) ? h + 1 : h; if (bits == 0) bits = 1; /* gen_span >= 1 for any real engine */ unsigned long long chunk = 1ULL << bits; unsigned long long rem = (~0ULL % range_size + 1) % range_size; unsigned long long limit = rem ? 0 - rem : 0; unsigned long long r; do { r = 0; for (unsigned got = 0; got < 64; got += bits) { unsigned long long d; do { d = (unsigned long long)g() - gen_min; } while (d >= chunk); r = (r << bits) | d; /* bits beyond 64 fall off: still uniform */ } } while (limit && r >= limit); return (IntType)(_a + (r % range_size)); } Loading