87 lines · plain
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the definition of the RandomGenerator class, a concrete11/// range-based generator that randomly creates inputs from a given sequence of12/// ranges.13///14//===----------------------------------------------------------------------===//15 16#ifndef MATHTEST_RANDOMGENERATOR_HPP17#define MATHTEST_RANDOMGENERATOR_HPP18 19#include "mathtest/IndexedRange.hpp"20#include "mathtest/RandomState.hpp"21#include "mathtest/RangeBasedGenerator.hpp"22 23#include <cstddef>24#include <cstdint>25#include <tuple>26 27namespace mathtest {28 29template <typename... InTypes>30class [[nodiscard]] RandomGenerator final31 : public RangeBasedGenerator<RandomGenerator<InTypes...>, InTypes...> {32 33 friend class RangeBasedGenerator<RandomGenerator<InTypes...>, InTypes...>;34 35 using Base = RangeBasedGenerator<RandomGenerator<InTypes...>, InTypes...>;36 37 using Base::RangesTuple;38 using Base::Size;39 40public:41 explicit constexpr RandomGenerator(42 SeedTy BaseSeed, uint64_t Size,43 const IndexedRange<InTypes> &...Ranges) noexcept44 : Base(Size, Ranges...), BaseSeed(BaseSeed) {}45 46private:47 [[nodiscard]] static uint64_t getRandomIndex(RandomState &RNG,48 uint64_t RangeSize) noexcept {49 if (RangeSize == 0)50 return 0;51 52 const uint64_t Threshold = (-RangeSize) % RangeSize;53 54 uint64_t RandomNumber;55 do {56 RandomNumber = RNG.next();57 } while (RandomNumber < Threshold);58 59 return RandomNumber % RangeSize;60 }61 62 template <typename BufferPtrsTupleType>63 void writeInputs(uint64_t CurrentFlatIndex, uint64_t Offset,64 BufferPtrsTupleType BufferPtrsTuple) const noexcept {65 66 RandomState RNG(SeedTy{BaseSeed.Value ^ (CurrentFlatIndex + Offset)});67 writeInputsImpl<0>(RNG, Offset, BufferPtrsTuple);68 }69 70 template <std::size_t Index, typename BufferPtrsTupleType>71 void writeInputsImpl(RandomState &RNG, uint64_t Offset,72 BufferPtrsTupleType BufferPtrsTuple) const noexcept {73 if constexpr (Index < Base::NumInputs) {74 const auto &Range = std::get<Index>(RangesTuple);75 const auto RandomIndex = getRandomIndex(RNG, Range.getSize());76 std::get<Index>(BufferPtrsTuple)[Offset] = Range[RandomIndex];77 78 writeInputsImpl<Index + 1>(RNG, Offset, BufferPtrsTuple);79 }80 }81 82 SeedTy BaseSeed;83};84} // namespace mathtest85 86#endif // MATHTEST_RANDOMGENERATOR_HPP87