Line | Branch | Exec | Source |
---|---|---|---|
1 | // This file is part of INSTINCT, the INS Toolkit for Integrated | ||
2 | // Navigation Concepts and Training by the Institute of Navigation of | ||
3 | // the University of Stuttgart, Germany. | ||
4 | // | ||
5 | // This Source Code Form is subject to the terms of the Mozilla Public | ||
6 | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
7 | // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
8 | |||
9 | /// @file RandomNumberGenerator.hpp | ||
10 | /// @brief Random Number Generator | ||
11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
12 | /// @date 2023-08-24 | ||
13 | |||
14 | #pragma once | ||
15 | |||
16 | #include <random> | ||
17 | #include <string> | ||
18 | |||
19 | #include <nlohmann/json.hpp> | ||
20 | using json = nlohmann::json; ///< json namespace | ||
21 | |||
22 | #include "SHA256.hpp" | ||
23 | |||
24 | namespace NAV | ||
25 | { | ||
26 | |||
27 | /// @brief Manages a thread which calls a specified function at a specified interval | ||
28 | class RandomNumberGenerator | ||
29 | { | ||
30 | public: | ||
31 | /// @brief Default constructor | ||
32 | 1680 | explicit RandomNumberGenerator(bool useSeed = true) : useSeed(useSeed) {} // NOLINT(cert-msc32-c,cert-msc51-cpp) | |
33 | /// @brief Copy constructor | ||
34 | RandomNumberGenerator(const RandomNumberGenerator&) = delete; | ||
35 | /// @brief Move constructor | ||
36 | RandomNumberGenerator(RandomNumberGenerator&&) = delete; | ||
37 | /// @brief Copy assignment operator | ||
38 | RandomNumberGenerator& operator=(const RandomNumberGenerator&) = delete; | ||
39 | /// @brief Move assignment operator | ||
40 | RandomNumberGenerator& operator=(RandomNumberGenerator&&) = delete; | ||
41 | /// @brief Destructor | ||
42 | ~RandomNumberGenerator() = default; | ||
43 | |||
44 | /// @brief Reset the seed to the internal seed or the system time | ||
45 | /// @param id Some id used to make a unique hash when using the system time to set the seed | ||
46 | 84 | void resetSeed(size_t id = 0) | |
47 | { | ||
48 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | uint64_t seed = useSeed ? this->seed : static_cast<uint64_t>(std::chrono::system_clock::now().time_since_epoch().count()); |
49 |
7/24✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 84 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 14 taken 84 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 84 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 84 times.
✗ Branch 21 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 84 times.
✓ Branch 28 taken 84 times.
✗ Branch 29 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
|
252 | auto hash = hashSeed(std::to_string(seed) + (useSeed || id == 0 ? "" : " " + std::to_string(id))); |
50 |
1/2✓ Branch 3 taken 84 times.
✗ Branch 4 not taken.
|
84 | std::seed_seq seed_seq(hash.begin(), hash.end()); |
51 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
84 | _generator.seed(seed_seq); |
52 | 84 | } | |
53 | |||
54 | /// @brief Reset the seed to the specified seed, but do not update the internal seed | ||
55 | /// @param[in] userSeed Seed to use once | ||
56 | void resetSeedOnce(uint64_t userSeed) | ||
57 | { | ||
58 | auto hash = hashSeed(std::to_string(userSeed)); | ||
59 | std::seed_seq seed_seq(hash.begin(), hash.end()); | ||
60 | _generator.seed(seed_seq); | ||
61 | } | ||
62 | |||
63 | /// @brief Gets a random integer number from an uniform distribution | ||
64 | /// @tparam IntType The result type generated by the generator. The effect is undefined if this is not one of short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long. | ||
65 | /// @param min Minimum value | ||
66 | /// @param max Maximum value | ||
67 | /// @return Random number | ||
68 | template<typename IntType = int> | ||
69 | ✗ | double getRand_uniformIntDist(IntType min = 0, IntType max = std::numeric_limits<IntType>::max()) | |
70 | { | ||
71 | ✗ | return std::uniform_int_distribution<IntType>(min, max)(_generator); | |
72 | } | ||
73 | |||
74 | /// @brief Gets a random real number from an uniform distribution | ||
75 | /// @tparam RealType The result type generated by the generator. The effect is undefined if this is not one of float, double, or long double | ||
76 | /// @param min Minimum value | ||
77 | /// @param max Maximum value | ||
78 | /// @return Random number | ||
79 | template<typename RealType = double> | ||
80 | ✗ | double getRand_uniformRealDist(RealType min = 0.0, RealType max = 1.0) | |
81 | { | ||
82 | ✗ | return std::uniform_real_distribution<RealType>(min, max)(_generator); | |
83 | } | ||
84 | |||
85 | /// @brief Gets a random number from a normal distribution | ||
86 | /// @tparam RealType The result type generated by the generator. The effect is undefined if this is not one of float, double, or long double | ||
87 | /// @param mean The μ distribution parameter (mean) | ||
88 | /// @param stddev The σ distribution parameter (standard deviation) | ||
89 | /// @return Random number | ||
90 | template<typename RealType = double> | ||
91 | 1065018 | double getRand_normalDist(RealType mean = 0.0, RealType stddev = 1.0) | |
92 | { | ||
93 |
2/4✓ Branch 1 taken 1065082 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1065177 times.
✗ Branch 5 not taken.
|
1065018 | return std::normal_distribution<RealType>(mean, stddev)(_generator); |
94 | } | ||
95 | |||
96 | bool useSeed = true; ///< Flag whether to use the seed instead of the system time | ||
97 | uint64_t seed = 0; ///< Seed for the random number generator | ||
98 | |||
99 | private: | ||
100 | /// @brief Hash the given seed | ||
101 | /// @param seed Seed | ||
102 | /// @return Hashed seed | ||
103 | 84 | static std::string hashSeed(const std::string& seed) | |
104 | { | ||
105 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
84 | SHA256 sha; |
106 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
84 | sha.update(seed); |
107 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
84 | uint8_t* digest = sha.digest(); |
108 | |||
109 |
1/2✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
|
84 | std::string hashed(digest, digest + 32); // NOLINT //SHA256::ToString method is shady... (manipulates data?). Keep Pointer Arithmetic |
110 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | delete[] digest; // NOLINT |
111 | |||
112 | 168 | return hashed; | |
113 | } | ||
114 | |||
115 | std::mt19937_64 _generator; ///< Random number generator | ||
116 | }; | ||
117 | |||
118 | /// @brief Write info to a json object | ||
119 | /// @param[out] j Json output | ||
120 | /// @param[in] rng Object to read info from | ||
121 | void to_json(json& j, const RandomNumberGenerator& rng); | ||
122 | /// @brief Read info from a json object | ||
123 | /// @param[in] j Json variable to read info from | ||
124 | /// @param[out] rng Output object | ||
125 | void from_json(const json& j, RandomNumberGenerator& rng); | ||
126 | |||
127 | } // namespace NAV | ||
128 |