Add gRandom and gArbitrary and initFuzz

This commit is contained in:
2024-05-15 14:14:44 -07:00
parent 75d5e811de
commit 2b22a7823a
2 changed files with 127 additions and 136 deletions

View File

@@ -63,117 +63,6 @@ void munmapSafe(void *ptr, size_t size) {
}
}
struct Random {
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
//
// Modified - mostly c -> c++
Random() = default;
Random(uint64_t initState, uint64_t initSeq) {
pcg32_srandom_r(initState, initSeq);
next();
}
/// Draws from a uniform distribution of uint32_t's
uint32_t next() {
auto result = next_;
next_ = pcg32_random_r();
return result;
}
/// Draws from a uniform distribution of [0, s). From
/// https://arxiv.org/pdf/1805.10941.pdf
uint32_t bounded(uint32_t s) {
assert(s != 0);
uint32_t x = next();
auto m = uint64_t(x) * uint64_t(s);
auto l = uint32_t(m);
if (l < s) {
uint32_t t = -s % s;
while (l < t) {
x = next();
m = uint64_t(x) * uint64_t(s);
l = uint32_t(m);
}
}
uint32_t result = m >> 32;
return result;
}
/// Fill `bytes` with `size` random hex bytes
void randomHex(uint8_t *bytes, int size);
private:
uint32_t pcg32_random_r() {
uint64_t oldState = state;
// Advance internal state
state = oldState * 6364136223846793005ULL + inc;
// Calculate output function (XSH RR), uses old state for max ILP
uint32_t xorShifted = ((oldState >> 18u) ^ oldState) >> 27u;
uint32_t rot = oldState >> 59u;
return (xorShifted >> rot) | (xorShifted << ((-rot) & 31));
}
// Seed the rng. Specified in two parts, state initializer and a
// sequence selection constant (a.k.a. stream id)
void pcg32_srandom_r(uint64_t initstate, uint64_t initSeq) {
state = 0U;
inc = (initSeq << 1u) | 1u;
pcg32_random_r();
state += initstate;
pcg32_random_r();
}
uint32_t next_{};
// RNG state. All values are possible.
uint64_t state{};
// Controls which RNG sequence (stream) is selected. Must *always* be odd.
uint64_t inc{};
};
void Random::randomHex(uint8_t *bytes, int size) {
int i = 0;
while (i + 8 < size) {
uint32_t r = next();
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
}
uint32_t r = next();
while (i < size) {
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
}
}
Random seededRandom() {
FILE *f = fopen("/dev/urandom", "r");
if (f == nullptr) {
fprintf(stderr, "Failed to open /dev/urandom\n");
abort();
}
uint64_t seed[2];
if (fread(seed, sizeof(seed[0]), sizeof(seed) / sizeof(seed[0]), f) !=
sizeof(seed) / sizeof(seed[0])) {
fprintf(stderr, "Failed to read from /dev/urandom\n");
abort();
}
fclose(f);
return Random{seed[0], seed[1]};
}
namespace weaselab {
// 96 is enough for an entire search path in a tree with a size that
@@ -773,7 +662,7 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
// Prepare new node
uint32_t node = newNode(
pointVersion, rangeVersion, key.p, key.len, val->p, val->len,
inserted ? random.next() : mm.base[finger.backNode()].entry->priority);
inserted ? gRandom.next() : mm.base[finger.backNode()].entry->priority);
if (!inserted) {
auto &n = mm.base[node];
n.pointer[0] = child<std::memory_order_relaxed>(finger.backNode(), false,
@@ -945,13 +834,6 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
void firstGeq(const Key *key, const int64_t *version, Iterator *iterator,
int count) const;
Random random =
#ifndef NDEBUG
{};
#else
seededRandom();
#endif
MemManager mm;
RootSet roots;
// Only meaningful within the callstack of `addMutations`