/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */ #ifndef MPT_RANDOM_ENGINE_LCG_HPP #define MPT_RANDOM_ENGINE_LCG_HPP #include "mpt/base/detect.hpp" #include "mpt/base/macros.hpp" #include "mpt/base/integer.hpp" #include "mpt/base/namespace.hpp" #include "mpt/base/numeric.hpp" #include "mpt/random/random.hpp" #include namespace mpt { inline namespace MPT_INLINE_NS { #if MPT_COMPILER_MSVC #pragma warning(push) #pragma warning(disable : 4724) // potential mod by 0 #endif // MPT_COMPILER_MSVC template class lcg_engine { public: typedef Tstate state_type; typedef Tvalue result_type; private: state_type state; public: template explicit inline lcg_engine(Trng & rd) : state(mpt::random(rd)) { operator()(); // we return results from the current state and update state after returning. results in better pipelining. } explicit inline lcg_engine(state_type seed) : state(seed) { operator()(); // we return results from the current state and update state after returning. results in better pipelining. } public: static MPT_CONSTEXPRINLINE result_type min() { return static_cast(0); } static MPT_CONSTEXPRINLINE result_type max() { static_assert(((result_mask >> result_shift) << result_shift) == result_mask); return static_cast(result_mask >> result_shift); } static MPT_CONSTEXPRINLINE int result_bits() { static_assert(((static_cast(1) << result_bits_) - 1) == (result_mask >> result_shift)); return result_bits_; } inline result_type operator()() { // we return results from the current state and update state after returning. results in better pipelining. state_type s = state; result_type result = static_cast((s & result_mask) >> result_shift); s = mpt::modulo_if_not_zero((a * s) + c); state = s; return result; } }; #if MPT_COMPILER_MSVC #pragma warning(pop) #endif // MPT_COMPILER_MSVC typedef lcg_engine lcg_msvc; typedef lcg_engine lcg_c99; typedef lcg_engine lcg_musl; } // namespace MPT_INLINE_NS } // namespace mpt #endif // MPT_RANDOM_ENGINE_LCG_HPP