Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions include/tscore/Random.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,30 @@ class Random
static uint64_t
random()
{
std::uniform_int_distribution<uint64_t> dist{0, UINT64_MAX};
return dist(_engine);
return _state.int_dist(_state.engine);
}

static double
drandom()
{
std::uniform_real_distribution<double> dist{0, 1};
return dist(_engine);
return _state.real_dist(_state.engine);
}

static void
seed(uint64_t s)
{
_engine.seed(s);
_state.engine.seed(s);
_state.int_dist.reset();
_state.real_dist.reset();
}

private:
thread_local static std::mt19937_64 _engine;
struct State {
std::mt19937_64 engine{std::random_device{}()};
std::uniform_int_distribution<uint64_t> int_dist{0, UINT64_MAX};
std::uniform_real_distribution<double> real_dist{0.0, 1.0};
};

thread_local static State _state;
};
}; // namespace ts
2 changes: 1 addition & 1 deletion src/tscore/Random.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@

namespace ts
{
thread_local std::mt19937_64 Random::_engine{std::random_device{}()};
thread_local Random::State Random::_state;
}; // namespace ts
38 changes: 38 additions & 0 deletions src/tscore/unit_tests/test_Random.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,41 @@ TEST_CASE("test random", "[libts][random]")
diff = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - start);
std::cout << static_cast<double>(diff.count()) / 1000000 << " ns per InkRand::random()" << std::endl;
}

TEST_CASE("test random reseeding", "[libts][random]")
{
// Test that reseeding produces deterministic sequences
// This verifies that distribution reset() is called properly in seed()

// Generate first sequence
ts::Random::seed(42);
uint64_t first_int = ts::Random::random();
double first_double = ts::Random::drandom();

// Generate some values to potentially populate distribution cache
for (int i = 0; i < 100; ++i) {
ts::Random::random();
ts::Random::drandom();
}

// Reseed with same value - should reset distributions and produce identical sequence
ts::Random::seed(42);
uint64_t second_int = ts::Random::random();
double second_double = ts::Random::drandom();

REQUIRE(first_int == second_int);
REQUIRE(first_double == second_double);

// Verify this works with InkRand too for consistency
InkRand ink1(42);
InkRand ink2(42);

REQUIRE(ink1.random() == ink2.random());
REQUIRE(ink1.drandom() == ink2.drandom());

// And that ts::Random matches InkRand after reseeding
ts::Random::seed(42);
InkRand ink3(42);

REQUIRE(ts::Random::random() == ink3.random());
}