Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
bitwise_uniform_distribution.hpp
Go to the documentation of this file.
1#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TESTING_BITWISE_UNIFORM_DISTRIBUTION_HPP_
2#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TESTING_BITWISE_UNIFORM_DISTRIBUTION_HPP_
3
4#include "arene/base/constraints/constraints.hpp"
5#include "arene/base/stdlib_choice/climits.hpp"
6#include "arene/base/stdlib_choice/cstddef.hpp"
7#include "arene/base/stdlib_choice/enable_if.hpp"
8#include "arene/base/stdlib_choice/is_integral.hpp"
9#include "arene/base/stdlib_choice/is_unsigned.hpp"
10#include "arene/base/stdlib_choice/make_unsigned.hpp"
11
12namespace arene {
13namespace base {
14namespace testing {
15
16/// @brief A uniform distribution to apply on top of a bit generator. Primary template (deliberately undefined).
17/// @tparam T The value type to generate
18template <typename T, typename = arene::base::constraints<>>
19class bitwise_uniform_distribution;
20
21/// @brief A uniform distribution to apply on top of a bit generator. SFINAE overload for integral types.
22/// @tparam T The value type to generate
23template <typename T>
24class bitwise_uniform_distribution<T, arene::base::constraints<std::enable_if_t<std::is_integral<T>::value>>> {
25 /// @brief Assert that the PRNG being used covers its type's whole range, since that's all our code currently handles
26 /// @tparam BitGenerator A bit generator (PRNG) type satisfying UniformRandomBitGenerator
27 template <typename BitGenerator>
28 static constexpr auto assert_generator_is_ok() noexcept -> void {
29 using result_type = typename BitGenerator::result_type;
30 static_assert(
32 "BitGenerator::result_type must be unsigned integral for BitGenerator to satisfy UniformRandomBitGenerator"
33 );
34 static_assert(
36 "More sophisticated generation code is needed to handle cases where the real range is smaller than the type"
37 );
38 static_assert(
39 BitGenerator::max() == static_cast<result_type>(~result_type{}),
40 "More sophisticated generation code is needed to handle cases where the real range is smaller than the type"
41 );
42 }
43
44 /// @brief Use a PRNG to generate a requested number of bits; overload for when the PRNG @c result_type is big enough
45 /// @tparam ExpectedBitsType An unsigned integer type that's bit enough to be used for the subsequent type conversion
46 /// @tparam BitGenerator A bit generator (PRNG) type satisfying UniformRandomBitGenerator
47 /// @param prng A bit generator (PRNG) instance
48 /// @return A uniformly-distributed random sequence of bits which can be converted into @c T
49 template <
50 typename ExpectedBitsType,
51 typename BitGenerator,
53 std::enable_if_t<sizeof(typename BitGenerator::result_type) >= sizeof(ExpectedBitsType)>> = nullptr>
54 static constexpr auto generate_bits(BitGenerator& prng) noexcept(noexcept(prng())) -> ExpectedBitsType {
56
57 return static_cast<ExpectedBitsType>(prng());
58 }
59
60 /// @brief Use a PRNG to generate a requested number of bits; overload for when the PRNG @c result_type is too small
61 /// @tparam ExpectedBitsType An unsigned integer type that's bit enough to be used for the subsequent type conversion
62 /// @tparam BitGenerator A bit generator (PRNG) type satisfying UniformRandomBitGenerator
63 /// @param prng A bit generator (PRNG) instance
64 /// @return A uniformly-distributed random sequence of bits which can be converted into @c T
65 template <
66 typename ExpectedBitsType,
67 typename BitGenerator,
69 std::enable_if_t<sizeof(typename BitGenerator::result_type) < sizeof(ExpectedBitsType)>> = nullptr>
70 static constexpr auto generate_bits(BitGenerator& prng) noexcept(noexcept(prng())) -> ExpectedBitsType {
72
73 using chunk_type = typename BitGenerator::result_type;
74 static_assert(
75 sizeof(ExpectedBitsType) % sizeof(chunk_type) == 0U,
76 "Implementation assumes that an integer number of chunks fits in ExpectedBitsType"
77 );
78
80 for (std::size_t chunk_idx{}; chunk_idx < (sizeof(ExpectedBitsType) / sizeof(chunk_type)); ++chunk_idx) {
81 auto new_bits = static_cast<ExpectedBitsType>(prng());
82 result_bits = static_cast<ExpectedBitsType>(
83 result_bits | static_cast<ExpectedBitsType>(new_bits << (chunk_idx * sizeof(chunk_type) * CHAR_BIT))
84 );
85 }
86
87 return result_bits;
88 }
89
90 public:
91 /// @brief Generate a value of type <c>T</c>; overload for when T is integral
92 /// @tparam BitGenerator A bit generator (PRNG) type satisfying UniformRandomBitGenerator
93 /// @param prng A bit generator (PRNG) instance
94 /// @return A random, uniformly-distributed @c T value
95 template <
96 typename BitGenerator,
98 constexpr auto operator()(BitGenerator& prng) const noexcept(noexcept(prng())) -> T {
99 return static_cast<T>(generate_bits<std::make_unsigned_t<T>>(prng));
100 }
101};
102
103} // namespace testing
104} // namespace base
105} // namespace arene
106
107#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TESTING_BITWISE_UNIFORM_DISTRIBUTION_HPP_
Definition customization.hpp:36
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10