forked from alibaba/AliSQL
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrandom_engine.cpp
More file actions
85 lines (70 loc) · 2.07 KB
/
random_engine.cpp
File metadata and controls
85 lines (70 loc) · 2.07 KB
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "duckdb/common/random_engine.hpp"
#include "duckdb/common/numeric_utils.hpp"
#include "pcg_random.hpp"
#ifdef __linux__
#include <sys/syscall.h>
#include <unistd.h>
#else
#include <random>
#endif
namespace duckdb {
struct RandomState {
RandomState() {
}
pcg32 pcg;
};
RandomEngine::RandomEngine(int64_t seed) : random_state(make_uniq<RandomState>()) {
if (seed < 0) {
#ifdef __linux__
idx_t random_seed = 0;
int result = -1;
#if defined(SYS_getrandom)
result = static_cast<int>(syscall(SYS_getrandom, &random_seed, sizeof(random_seed), 0));
#endif
if (result == -1) {
// Something went wrong with the syscall, we use chrono
const auto now = std::chrono::high_resolution_clock::now();
random_seed = now.time_since_epoch().count();
}
random_state->pcg.seed(random_seed);
#else
random_state->pcg.seed(pcg_extras::seed_seq_from<std::random_device>());
#endif
} else {
random_state->pcg.seed(NumericCast<uint64_t>(seed));
}
}
RandomEngine::~RandomEngine() {
}
double RandomEngine::NextRandom(double min, double max) {
D_ASSERT(max >= min);
return min + (NextRandom() * (max - min));
}
double RandomEngine::NextRandom() {
auto uint64 = NextRandomInteger64();
return std::ldexp(uint64, -64);
}
double RandomEngine::NextRandom32(double min, double max) {
D_ASSERT(max >= min);
return min + (NextRandom32() * (max - min));
}
double RandomEngine::NextRandom32() {
auto uint32 = NextRandomInteger();
return std::ldexp(uint32, -32);
}
uint32_t RandomEngine::NextRandomInteger() {
return random_state->pcg();
}
uint64_t RandomEngine::NextRandomInteger64() {
return (static_cast<uint64_t>(NextRandomInteger()) << UINT64_C(32)) | static_cast<uint64_t>(NextRandomInteger());
}
uint32_t RandomEngine::NextRandomInteger(uint32_t min, uint32_t max) {
return min + static_cast<uint32_t>(NextRandom() * double(max - min));
}
uint32_t RandomEngine::NextRandomInteger32(uint32_t min, uint32_t max) {
return min + static_cast<uint32_t>(NextRandom32() * double(max - min));
}
void RandomEngine::SetSeed(uint64_t seed) {
random_state->pcg.seed(seed);
}
} // namespace duckdb