/* SPDX-License-Identifier: BSD-3-Clause */ /* SPDX-FileCopyrightText: Olivier Lapicque */ /* SPDX-FileCopyrightText: OpenMPT Project Developers and Contributors */ #pragma once #include "openmpt/all/BuildSettings.hpp" #include "mpt/base/bit.hpp" #include "mpt/random/random.hpp" #include "openmpt/base/Types.hpp" #include #include OPENMPT_NAMESPACE_BEGIN namespace mpt { namespace rng { template class modplug { public: typedef Tstate state_type; typedef Tvalue result_type; private: state_type state1; state_type state2; public: template explicit inline modplug(Trng &rd) : state1(mpt::random(rd)) , state2(mpt::random(rd)) { } explicit inline modplug(state_type seed1, state_type seed2) : state1(seed1) , state2(seed2) { } public: static MPT_CONSTEXPRINLINE result_type min() { return static_cast(0); } static MPT_CONSTEXPRINLINE result_type max() { return std::numeric_limits::max(); } static MPT_CONSTEXPRINLINE int result_bits() { static_assert(std::is_integral::value); static_assert(std::is_unsigned::value); return std::numeric_limits::digits; } inline result_type operator()() { state_type a = state1; state_type b = state2; a = mpt::rotl(a, rol1); a ^= x1; a += x2 + (b * x3); b += mpt::rotl(a, rol2) * x4; state1 = a; state2 = b; result_type result = static_cast(b); return result; } }; typedef modplug modplug_dither; } // namespace rng } // namespace mpt OPENMPT_NAMESPACE_END