//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file contains the definition of the RandomGenerator class, a concrete /// range-based generator that randomly creates inputs from a given sequence of /// ranges. /// //===----------------------------------------------------------------------===// #ifndef MATHTEST_RANDOMGENERATOR_HPP #define MATHTEST_RANDOMGENERATOR_HPP #include "mathtest/IndexedRange.hpp" #include "mathtest/RandomState.hpp" #include "mathtest/RangeBasedGenerator.hpp" #include #include #include namespace mathtest { template class [[nodiscard]] RandomGenerator final : public RangeBasedGenerator, InTypes...> { friend class RangeBasedGenerator, InTypes...>; using Base = RangeBasedGenerator, InTypes...>; using Base::RangesTuple; using Base::Size; public: explicit constexpr RandomGenerator( SeedTy BaseSeed, uint64_t Size, const IndexedRange &...Ranges) noexcept : Base(Size, Ranges...), BaseSeed(BaseSeed) {} private: [[nodiscard]] static uint64_t getRandomIndex(RandomState &RNG, uint64_t RangeSize) noexcept { if (RangeSize == 0) return 0; const uint64_t Threshold = (-RangeSize) % RangeSize; uint64_t RandomNumber; do { RandomNumber = RNG.next(); } while (RandomNumber < Threshold); return RandomNumber % RangeSize; } template void writeInputs(uint64_t CurrentFlatIndex, uint64_t Offset, BufferPtrsTupleType BufferPtrsTuple) const noexcept { RandomState RNG(SeedTy{BaseSeed.Value ^ (CurrentFlatIndex + Offset)}); writeInputsImpl<0>(RNG, Offset, BufferPtrsTuple); } template void writeInputsImpl(RandomState &RNG, uint64_t Offset, BufferPtrsTupleType BufferPtrsTuple) const noexcept { if constexpr (Index < Base::NumInputs) { const auto &Range = std::get(RangesTuple); const auto RandomIndex = getRandomIndex(RNG, Range.getSize()); std::get(BufferPtrsTuple)[Offset] = Range[RandomIndex]; writeInputsImpl(RNG, Offset, BufferPtrsTuple); } } SeedTy BaseSeed; }; } // namespace mathtest #endif // MATHTEST_RANDOMGENERATOR_HPP