blob: 5f1d3a6eb8b7be3f6c25c587d10c47d150b1c3be (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#pragma once
#include "WAVM/Inline/Assert.h"
#include "WAVM/Inline/BasicTypes.h"
namespace WAVM {
// A stream that uses a combination of a PRNG and input data to produce pseudo-random values.
struct RandomStream
{
RandomStream(const U8* inData, Uptr numBytes)
: next(inData), end(inData + numBytes), denominator(0), numerator(0), seed(0)
{
refill();
}
// Returns a pseudo-random value between 0 and maxResult, inclusive.
template<typename Result> Result get(Result maxResult)
{
Result result = Result(get64(maxResult));
WAVM_ASSERT(result <= maxResult);
return result;
}
private:
const U8* next;
const U8* end;
U64 denominator;
U64 numerator;
U64 seed;
void refill()
{
while(denominator <= UINT32_MAX)
{
if(next < end) { numerator += (denominator + 1) * *next++; }
denominator += 255 * (denominator + 1);
};
}
U32 get32(U32 maxResult)
{
if(maxResult == 0) { return 0; }
WAVM_ASSERT(denominator >= maxResult);
seed ^= numerator;
const U32 result = U32(seed % (U64(maxResult) + 1));
seed /= (U64(maxResult) + 1);
numerator /= (U64(maxResult) + 1);
denominator /= (U64(maxResult) + 1);
seed = 6364136223846793005 * seed + 1442695040888963407;
refill();
return result;
}
U64 get64(U64 maxResult)
{
U64 result = get32(U32(maxResult));
result += U64(get32(U32(maxResult >> 32))) << 32;
WAVM_ASSERT(result <= maxResult);
return result;
}
};
}
|