mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-22 11:23:29 +01:00
Make uniform_floating_point_distribution reproducible
By moving to use our `uniform_integer_distribution`, which is reproducible across different platforms, instead of the stdlib one which is not, we can provide reproducible results for `float`s and `double`s. Still no reproducibility for `long double`s, because those are too different across different platforms.
This commit is contained in:
parent
ed9d672b5c
commit
28c66fdc5a
@ -10,10 +10,10 @@
|
||||
#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_random_floating_point_helpers.hpp>
|
||||
#include <catch2/internal/catch_uniform_integer_distribution.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <random>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@ -76,8 +76,7 @@ class uniform_floating_point_distribution {
|
||||
FloatType m_a, m_b;
|
||||
FloatType m_ulp_magnitude;
|
||||
WidthType m_floats_in_range;
|
||||
// TODO: we want to eventually replace this distribution with our own for reproducibility
|
||||
std::uniform_int_distribution<WidthType> m_int_dist;
|
||||
uniform_integer_distribution<WidthType> m_int_dist;
|
||||
|
||||
// In specific cases, we can overflow into `inf` when computing the
|
||||
// `steps * g` offset. To avoid this, we don't offset by more than this
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <catch2/generators/catch_generators.hpp>
|
||||
#include <catch2/matchers/catch_matchers_range_equals.hpp>
|
||||
|
||||
#include <random>
|
||||
|
||||
TEST_CASE("Our PCG implementation provides expected results for known seeds", "[rng]") {
|
||||
Catch::SimplePcg32 rng;
|
||||
SECTION("Default seeded") {
|
||||
@ -489,3 +491,80 @@ TEMPLATE_TEST_CASE( "uniform_integer_distribution is reproducible",
|
||||
|
||||
REQUIRE_THAT(generated, Catch::Matchers::RangeEquals(uniform_integer_test_params<TestType>::expected));
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
struct uniform_fp_test_params;
|
||||
|
||||
template<>
|
||||
struct uniform_fp_test_params<float> {
|
||||
// These are exactly representable
|
||||
static constexpr float lowest = -256.125f;
|
||||
static constexpr float highest = 385.125f;
|
||||
// These are just round-trip formatted
|
||||
static constexpr float expected[] = { 92.56961f,
|
||||
-23.170044f,
|
||||
310.81833f,
|
||||
-53.023132f,
|
||||
105.03287f,
|
||||
198.77591f,
|
||||
-172.72931f,
|
||||
51.805176f,
|
||||
-241.10156f,
|
||||
64.66101f,
|
||||
212.12509f,
|
||||
-49.24292f,
|
||||
-177.1399f,
|
||||
245.23679f,
|
||||
173.22421f };
|
||||
};
|
||||
template <>
|
||||
struct uniform_fp_test_params<double> {
|
||||
// These are exactly representable
|
||||
static constexpr double lowest = -234582.9921875;
|
||||
static constexpr double highest = 261238.015625;
|
||||
// These are just round-trip formatted
|
||||
static constexpr double expected[] = { 35031.207052832615,
|
||||
203783.3401838024,
|
||||
44667.940405848756,
|
||||
-170100.5877224467,
|
||||
-222966.7418051684,
|
||||
127472.72630072923,
|
||||
-173510.88209096913,
|
||||
97394.16172239158,
|
||||
119123.6921592663,
|
||||
22595.741022785165,
|
||||
8988.68409120926,
|
||||
136906.86520606978,
|
||||
33369.19104222473,
|
||||
60912.7615841752,
|
||||
-149060.05936760217 };
|
||||
};
|
||||
|
||||
// We need these definitions for C++14 and earlier, but
|
||||
// GCC will complain about them in newer C++ standards
|
||||
#if __cplusplus <= 201402L
|
||||
constexpr float uniform_fp_test_params<float>::expected[];
|
||||
constexpr double uniform_fp_test_params<double>::expected[];
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
TEMPLATE_TEST_CASE( "uniform_floating_point_distribution is reproducible",
|
||||
"[rng][distribution][floating-point][approvals]",
|
||||
float,
|
||||
double ) {
|
||||
Catch::SimplePcg32 pcg( 0xaabb'aabb );
|
||||
|
||||
const auto lowest = uniform_fp_test_params<TestType>::lowest;
|
||||
const auto highest = uniform_fp_test_params<TestType>::highest;
|
||||
Catch::uniform_floating_point_distribution<TestType> dist( lowest, highest );
|
||||
|
||||
constexpr auto iters = 15;
|
||||
std::array<TestType, iters> generated;
|
||||
for ( int i = 0; i < iters; ++i ) {
|
||||
generated[i] = dist( pcg );
|
||||
}
|
||||
|
||||
REQUIRE_THAT( generated, Catch::Matchers::RangeEquals( uniform_fp_test_params<TestType>::expected ) );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user