diff --git a/include/emp/math/Random.hpp b/include/emp/math/Random.hpp index 23133fa066..169533ecc0 100644 --- a/include/emp/math/Random.hpp +++ b/include/emp/math/Random.hpp @@ -85,6 +85,10 @@ namespace emp { weyl_state *= 2; // Make sure starting state is even. + // Reset other internal state + value = 0; + expRV = 0.0; + Get(); // Prime the new sequence by skipping the first number. } diff --git a/tests/math/Random.cpp b/tests/math/Random.cpp index 8182df62dc..6eb2a997a9 100644 --- a/tests/math/Random.cpp +++ b/tests/math/Random.cpp @@ -71,7 +71,7 @@ TEST_CASE("Test Random", "[math]") REQUIRE(b2_result < 50); emp::RandomStdAdaptor randomStd(rnd); - REQUIRE(randomStd(4) == 1); + REQUIRE(randomStd(4) == 3); REQUIRE(rnd.GetRandGeometric(1) == 1); REQUIRE(rnd.GetRandGeometric(0) == std::numeric_limits::infinity()); @@ -295,3 +295,48 @@ TEST_CASE("Another Test random", "[math]") REQUIRE(v.first + v.second == 0); } } + +TEST_CASE("Calling ResetSeed should reset all generator internal state", "[math]") { + + SECTION("Test internal 'value'") { + // Get Seed + emp::Random rnd(-1); // Initialize without a seed + rnd.ResetSeed(5); + REQUIRE(rnd.GetSeed() == 5); + + emp::vector sequence_a; + for (size_t i = 0; i < 10; ++i) { + sequence_a.emplace_back(rnd.GetInt(10000)); + } + + rnd.ResetSeed(5); + emp::vector sequence_b; + for (size_t i = 0; i < 10; ++i) { + sequence_b.emplace_back(rnd.GetInt(10000)); + } + + // Tests internal 'value' + REQUIRE(sequence_a == sequence_b); + } + + SECTION("Test internal expV") { + emp::Random rnd(10); + rnd.GetRandNormal(); // Adjusts expV with time-based seed generator + + rnd.ResetSeed(4); // Should reset expV + emp::vector norm_seq_a; + for (size_t i = 0; i < 1000; ++i) { + norm_seq_a.emplace_back(rnd.GetRandNormal()); + } + + rnd.ResetSeed(4); + emp::vector norm_seq_b; + for (size_t i = 0; i < 1000; ++i) { + norm_seq_b.emplace_back(rnd.GetRandNormal()); + } + + // Tests internal expV + REQUIRE(norm_seq_a == norm_seq_b); + } + +}