Coverage Report

Created: 2025-08-28 07:58

/src/duckdb/src/common/random_engine.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "duckdb/common/random_engine.hpp"
2
#include "duckdb/common/numeric_utils.hpp"
3
#include "pcg_random.hpp"
4
5
#ifdef __linux__
6
#include <sys/syscall.h>
7
#include <unistd.h>
8
#else
9
#include <random>
10
#endif
11
namespace duckdb {
12
13
struct RandomState {
14
25.1k
  RandomState() {
15
25.1k
  }
16
17
  pcg32 pcg;
18
};
19
20
25.1k
RandomEngine::RandomEngine(int64_t seed) : random_state(make_uniq<RandomState>()) {
21
25.1k
  if (seed < 0) {
22
24.3k
#ifdef __linux__
23
24.3k
    idx_t random_seed = 0;
24
24.3k
    int result = -1;
25
24.3k
#if defined(SYS_getrandom)
26
24.3k
    result = static_cast<int>(syscall(SYS_getrandom, &random_seed, sizeof(random_seed), 0));
27
24.3k
#endif
28
24.3k
    if (result == -1) {
29
      // Something went wrong with the syscall, we use chrono
30
0
      const auto now = std::chrono::high_resolution_clock::now();
31
0
      random_seed = now.time_since_epoch().count();
32
0
    }
33
24.3k
    random_state->pcg.seed(random_seed);
34
#else
35
    random_state->pcg.seed(pcg_extras::seed_seq_from<std::random_device>());
36
#endif
37
24.3k
  } else {
38
809
    random_state->pcg.seed(NumericCast<uint64_t>(seed));
39
809
  }
40
25.1k
}
41
42
25.1k
RandomEngine::~RandomEngine() {
43
25.1k
}
44
45
0
double RandomEngine::NextRandom(double min, double max) {
46
0
  D_ASSERT(max >= min);
47
0
  return min + (NextRandom() * (max - min));
48
0
}
49
50
25
double RandomEngine::NextRandom() {
51
25
  auto uint64 = NextRandomInteger64();
52
25
  return std::ldexp(uint64, -64);
53
25
}
54
55
0
double RandomEngine::NextRandom32(double min, double max) {
56
0
  D_ASSERT(max >= min);
57
0
  return min + (NextRandom32() * (max - min));
58
0
}
59
60
0
double RandomEngine::NextRandom32() {
61
0
  auto uint32 = NextRandomInteger();
62
0
  return std::ldexp(uint32, -32);
63
0
}
64
65
208
uint32_t RandomEngine::NextRandomInteger() {
66
208
  return random_state->pcg();
67
208
}
68
69
50
uint64_t RandomEngine::NextRandomInteger64() {
70
50
  return (static_cast<uint64_t>(NextRandomInteger()) << UINT64_C(32)) | static_cast<uint64_t>(NextRandomInteger());
71
50
}
72
73
0
uint32_t RandomEngine::NextRandomInteger(uint32_t min, uint32_t max) {
74
0
  return min + static_cast<uint32_t>(NextRandom() * double(max - min));
75
0
}
76
77
0
uint32_t RandomEngine::NextRandomInteger32(uint32_t min, uint32_t max) {
78
0
  return min + static_cast<uint32_t>(NextRandom32() * double(max - min));
79
0
}
80
81
25
void RandomEngine::SetSeed(uint64_t seed) {
82
25
  random_state->pcg.seed(seed);
83
25
}
84
85
} // namespace duckdb