.. _program_listing_file_src_utils_RngThread.hpp: Program Listing for File RngThread.hpp ====================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/utils/RngThread.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef RNGUTILS_HPP #define RNGUTILS_HPP #include "ThreadVec.hpp" #include #include #include #include #include #include #include #ifdef _OPENMP # include #endif #include #include #include #include #include #include namespace utils { using RngType = pcg64; inline constexpr size_t rngStateWidth = 128; using RngState = std::array; class RngThread { public: RngThread() { for (auto& r : rngEngines_) { pcg_extras::seed_seq_from seedSource; r = std::make_unique(seedSource); } } RngThread(const RngType::state_type seed) { for (int i = 0; i < rngEngines_.size(); ++i) { rngEngines_[i] = std::make_unique(seed + i); // NOLINT(cppcoreguidelines-pro-bounds-avoid-unchecked-container-access) } } ~RngThread() = default; // Disable copy and move constructors and assignment operators RngThread(const RngThread&) = delete; RngThread(RngThread&&) = delete; auto operator=(const RngThread&) -> RngThread& = delete; auto operator=(RngThread&&) -> RngThread& = delete; void seed(const RngType::state_type seed) { for (int i = 0; i < rngEngines_.size(); ++i) { rngEngines_[i]->seed(seed+i); // NOLINT(cppcoreguidelines-pro-bounds-avoid-unchecked-container-access) } } auto operator()() const -> RngType& { return *rngEngines_(); } [[nodiscard]] auto getState() const -> RngState { std::ostringstream stateStream; stateStream << *rngEngines_(); const std::string state = stateStream.str(); if (state.size() >= rngStateWidth) { throw std::runtime_error( "RngThread: serialized state does not fit in the " "fixed-width RngState buffer"); } RngState buf{}; std::ranges::copy(state, buf.begin()); return buf; } void setState(const RngState& state) { std::istringstream stateStream{std::string(state.data())}; stateStream >> *rngEngines_(); } private: ThreadVec > rngEngines_; }; inline auto rng() -> RngThread& { try { static RngThread instance; return instance; } catch (const std::exception& error) { std::cerr << "FATAL: random number generator initialization " "failed: " << error.what() << "\n"; std::exit(1); // NOLINT(concurrency-mt-unsafe) -- the program is terminating regardless; thread-safety of the shutdown path doesn't matter } } } // namespace utils #endif // RNGUTILS_HPP