#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace NKikimr::NMiniKQL { namespace NPrivate { template struct TRandomDataGenerator { static_assert(sizeof(T) == 0, "TRandomDataGenerator is not specialized for this type. " "Add a specialization of TRandomDataGenerator to support it."); }; template <> struct TRandomDataGenerator { struct TSettings { double TrueProbability = 0.5; }; static bool Generate(IRandomProvider& provider, const TSettings& settings) { Y_ENSURE(settings.TrueProbability >= 0.0 && settings.TrueProbability <= 1.0); return provider.GenRandReal2() < settings.TrueProbability; } }; template requires std::is_integral_v && (!std::is_same_v) struct TRandomDataGenerator { struct TSettings { T Min = std::numeric_limits::min(); T Max = std::numeric_limits::max(); }; static T Generate(IRandomProvider& provider, const TSettings& settings) { Y_ENSURE(settings.Min < settings.Max); const auto range = static_cast(settings.Max) - static_cast(settings.Min); return static_cast(static_cast(settings.Min) + provider.GenRand64() % range); } }; template requires std::is_floating_point_v struct TRandomDataGenerator { struct TSettings { T Min = T(0); T Max = T(1); }; static T Generate(IRandomProvider& provider, const TSettings& settings) { Y_ENSURE(settings.Min < settings.Max); return static_cast( settings.Min + provider.GenRandReal2() * static_cast(settings.Max - settings.Min)); } }; template <> struct TRandomDataGenerator { struct TSettings { size_t MinSize = 0; size_t MaxSize = 32; TStringBuf Alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; }; static TString Generate(IRandomProvider& provider, const TSettings& settings) { Y_ENSURE(settings.MinSize < settings.MaxSize); Y_ENSURE(!settings.Alphabet.empty()); const size_t len = settings.MinSize + provider.GenRand64() % (settings.MaxSize - settings.MinSize); TString result(len, '\0'); for (size_t i = 0; i < len; ++i) { result[i] = settings.Alphabet[provider.GenRand64() % settings.Alphabet.size()]; } return result; } }; template struct TRandomDataGenerator> { struct TSettings { double NullProbability = 0.1; typename TRandomDataGenerator::TSettings Inner{}; }; static TMaybe Generate(IRandomProvider& provider, const TSettings& settings) { Y_ENSURE(settings.NullProbability >= 0.0 && settings.NullProbability <= 1.0); if (provider.GenRandReal2() < settings.NullProbability) { return Nothing(); } return TRandomDataGenerator::Generate(provider, settings.Inner); } }; template struct TRandomDataGenerator> { using TSettings = std::tuple::TSettings...>; static std::tuple Generate(IRandomProvider& provider, const TSettings& settings) { return [&](std::index_sequence) { return std::make_tuple(TRandomDataGenerator::Generate(provider, std::get(settings))...); }(std::index_sequence_for{}); } }; template struct TRandomDataGenerator> { struct TSettings { std::array Weights = [] { std::array w{}; w.fill(1.0); return w; }(); std::tuple::TSettings...> InnerSettings{}; }; static std::variant Generate(IRandomProvider& provider, const TSettings& settings) { const size_t idx = SelectWeightedIndex(provider, settings.Weights); std::variant result; [&](std::index_sequence) { Y_UNUSED(((Is == idx && (result = std::variant( std::in_place_index, TRandomDataGenerator::Generate( provider, std::get(settings.InnerSettings))), true)) || ...)); }(std::index_sequence_for{}); return result; } private: static size_t SelectWeightedIndex(IRandomProvider& provider, const std::array& weights) { double total = 0.0; for (double w : weights) { Y_ENSURE(w >= 0.0); total += w; } Y_ENSURE(total > 0.0); const double roll = provider.GenRandReal2() * total; double cumulative = 0.0; for (size_t i = 0; i + 1 < sizeof...(Ts); ++i) { cumulative += weights[i]; if (roll < cumulative) { return i; } } return sizeof...(Ts) - 1; } }; } // namespace NPrivate template using TGeneratorSettings = typename NPrivate::TRandomDataGenerator::TSettings; template TVector GenerateRandomData(TIntrusivePtr provider, TGeneratorSettings settings, size_t count) { TVector result; result.reserve(count); for (size_t i = 0; i < count; ++i) { result.push_back(NPrivate::TRandomDataGenerator::Generate(*provider, settings)); } return result; } template TVector GenerateRandomData(TIntrusivePtr provider, size_t count) { return GenerateRandomData(std::move(provider), TGeneratorSettings{}, count); } } // namespace NKikimr::NMiniKQL