Commit 08d8f4bb authored by jan.koester's avatar jan.koester
Browse files

test

parent e28ab20c
Loading
Loading
Loading
Loading
+41 −7
Changes for include/cxx/random: 41 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -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));
    }