You've already forked Zygisk-Assistant
mirror of
https://github.com/snake-4/Zygisk-Assistant.git
synced 2025-09-06 06:37:02 +00:00
Initial commit
This commit is contained in:
+334
@@ -0,0 +1,334 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// <algorithm>
|
||||
|
||||
// template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Gen>
|
||||
// requires (forward_iterator<I> || random_access_iterator<O>) &&
|
||||
// indirectly_copyable<I, O> &&
|
||||
// uniform_random_bit_generator<remove_reference_t<Gen>>
|
||||
// O sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g); // Since C++20
|
||||
//
|
||||
// template<input_range R, weakly_incrementable O, class Gen>
|
||||
// requires (forward_range<R> || random_access_iterator<O>) &&
|
||||
// indirectly_copyable<iterator_t<R>, O> &&
|
||||
// uniform_random_bit_generator<remove_reference_t<Gen>>
|
||||
// O sample(R&& r, O out, range_difference_t<R> n, Gen&& g); // Since C++20
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <random>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
#include "almost_satisfies_types.h"
|
||||
#include "test_iterators.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
class RandGen {
|
||||
public:
|
||||
constexpr static size_t min() { return 0; }
|
||||
constexpr static size_t max() { return 255; }
|
||||
|
||||
constexpr size_t operator()() {
|
||||
flip = !flip;
|
||||
return flip;
|
||||
}
|
||||
|
||||
private:
|
||||
bool flip = false;
|
||||
};
|
||||
|
||||
static_assert(std::uniform_random_bit_generator<RandGen>);
|
||||
// `std::uniform_random_bit_generator` is a subset of requirements of `__libcpp_random_is_valid_urng`. Make sure that
|
||||
// a type satisfying the required minimum is still accepted by `ranges::shuffle`.
|
||||
LIBCPP_STATIC_ASSERT(!std::__libcpp_random_is_valid_urng<RandGen>::value);
|
||||
|
||||
struct BadGen {
|
||||
constexpr static size_t min() { return 255; }
|
||||
constexpr static size_t max() { return 0; }
|
||||
constexpr size_t operator()() const;
|
||||
};
|
||||
static_assert(!std::uniform_random_bit_generator<BadGen>);
|
||||
|
||||
// Test constraints of the (iterator, sentinel) overload.
|
||||
// ======================================================
|
||||
|
||||
template <class Iter = int*, class Sent = int*, class Out = int*, class Gen = RandGen>
|
||||
concept HasSampleIter =
|
||||
requires(Iter&& iter, Sent&& sent, Out&& out, std::iter_difference_t<Iter> n, Gen&& gen) {
|
||||
std::ranges::sample(std::forward<Iter>(iter), std::forward<Sent>(sent),
|
||||
std::forward<Out>(out), n, std::forward<Gen>(gen));
|
||||
};
|
||||
|
||||
static_assert(HasSampleIter<int*, int*, int*, RandGen>);
|
||||
|
||||
// !input_iterator<I>
|
||||
static_assert(!HasSampleIter<InputIteratorNotDerivedFrom>);
|
||||
static_assert(!HasSampleIter<InputIteratorNotIndirectlyReadable>);
|
||||
static_assert(!HasSampleIter<InputIteratorNotInputOrOutputIterator>);
|
||||
|
||||
// !sentinel_for<S, I>
|
||||
static_assert(!HasSampleIter<int*, SentinelForNotSemiregular>);
|
||||
static_assert(!HasSampleIter<int*, SentinelForNotWeaklyEqualityComparableWith>);
|
||||
|
||||
// !weakly_incrementable<O>
|
||||
static_assert(!HasSampleIter<int*, int*, WeaklyIncrementableNotMovable>);
|
||||
|
||||
// (forward_iterator<I> || random_access_iterator<O>)
|
||||
static_assert(HasSampleIter<
|
||||
forward_iterator<int*>, forward_iterator<int*>,
|
||||
cpp20_output_iterator<int*>
|
||||
>);
|
||||
static_assert(HasSampleIter<
|
||||
cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>,
|
||||
random_access_iterator<int*>
|
||||
>);
|
||||
// !(forward_iterator<I> || random_access_iterator<O>)
|
||||
static_assert(!HasSampleIter<
|
||||
cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>,
|
||||
cpp20_output_iterator<int*>
|
||||
>);
|
||||
|
||||
// !indirectly_copyable<I, O>
|
||||
static_assert(!HasSampleIter<int*, int*, int**>);
|
||||
|
||||
// !uniform_random_bit_generator<remove_reference_t<Gen>>
|
||||
static_assert(!HasSampleIter<int*, int*, int*, BadGen>);
|
||||
|
||||
// Test constraints of the (range) overload.
|
||||
// =========================================
|
||||
|
||||
template <class Range, class Out = int*, class Gen = RandGen>
|
||||
concept HasSampleRange =
|
||||
requires(Range&& range, Out&& out, std::ranges::range_difference_t<Range> n, Gen&& gen) {
|
||||
std::ranges::sample(std::forward<Range>(range), std::forward<Out>(out), n, std::forward<Gen>(gen));
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using R = UncheckedRange<T>;
|
||||
|
||||
static_assert(HasSampleRange<R<int*>, int*, RandGen>);
|
||||
|
||||
// !input_range<R>
|
||||
static_assert(!HasSampleRange<InputRangeNotDerivedFrom>);
|
||||
static_assert(!HasSampleRange<InputRangeNotIndirectlyReadable>);
|
||||
static_assert(!HasSampleRange<InputRangeNotInputOrOutputIterator>);
|
||||
|
||||
// !weakly_incrementable<O>
|
||||
static_assert(!HasSampleRange<R<int*>, WeaklyIncrementableNotMovable>);
|
||||
|
||||
// (forward_range<R> || random_access_iterator<O>)
|
||||
static_assert(HasSampleRange<
|
||||
R<forward_iterator<int*>>,
|
||||
cpp20_output_iterator<int*>
|
||||
>);
|
||||
static_assert(HasSampleRange<
|
||||
R<cpp20_input_iterator<int*>>,
|
||||
random_access_iterator<int*>
|
||||
>);
|
||||
// !(forward_range<R> || random_access_iterator<O>)
|
||||
static_assert(!HasSampleRange<
|
||||
R<cpp20_input_iterator<int*>>,
|
||||
cpp20_output_iterator<int*>
|
||||
>);
|
||||
|
||||
// !indirectly_copyable<I, O>
|
||||
static_assert(!HasSampleRange<R<int*>, int**>);
|
||||
|
||||
// !uniform_random_bit_generator<remove_reference_t<Gen>>
|
||||
static_assert(!HasSampleRange<R<int*>, int*, BadGen>);
|
||||
|
||||
template <class Iter, class Sent, class Out, size_t N, class Gen>
|
||||
void test_one(std::array<int, N> in, size_t n, Gen gen) {
|
||||
assert(n <= static_cast<size_t>(N));
|
||||
|
||||
auto verify_is_subsequence = [&] (auto output) {
|
||||
auto sorted_input = in;
|
||||
std::ranges::sort(sorted_input);
|
||||
auto sorted_output = std::ranges::subrange(output.begin(), output.begin() + n);
|
||||
std::ranges::sort(sorted_output);
|
||||
assert(std::ranges::includes(sorted_input, sorted_output));
|
||||
};
|
||||
|
||||
{ // (iterator, sentinel) overload.
|
||||
auto begin = Iter(in.data());
|
||||
auto end = Sent(Iter(in.data() + in.size()));
|
||||
std::array<int, N> output;
|
||||
auto out = Out(output.begin());
|
||||
|
||||
std::same_as<Out> decltype(auto) result = std::ranges::sample(
|
||||
std::move(begin), std::move(end), std::move(out), n, gen);
|
||||
assert(base(result) == output.data() + n);
|
||||
verify_is_subsequence(output);
|
||||
// The output of `sample` is implementation-specific.
|
||||
}
|
||||
|
||||
{ // (range) overload.
|
||||
auto begin = Iter(in.data());
|
||||
auto end = Sent(Iter(in.data() + in.size()));
|
||||
std::array<int, N> output;
|
||||
auto out = Out(output.begin());
|
||||
|
||||
std::same_as<Out> decltype(auto) result = std::ranges::sample(std::ranges::subrange(
|
||||
std::move(begin), std::move(end)), std::move(out), n, gen);
|
||||
assert(base(result) == output.data() + n);
|
||||
verify_is_subsequence(output);
|
||||
// The output of `sample` is implementation-specific.
|
||||
}
|
||||
}
|
||||
|
||||
template <class Iter, class Sent, class Out>
|
||||
void test_iterators_iter_sent_out() {
|
||||
RandGen gen;
|
||||
|
||||
// Empty sequence.
|
||||
test_one<Iter, Sent, Out, 0>({}, 0, gen);
|
||||
// 1-element sequence.
|
||||
test_one<Iter, Sent, Out, 1>({1}, 1, gen);
|
||||
// 2-element sequence.
|
||||
test_one<Iter, Sent, Out, 2>({1, 2}, 1, gen);
|
||||
test_one<Iter, Sent, Out, 2>({1, 2}, 2, gen);
|
||||
// n == 0.
|
||||
test_one<Iter, Sent, Out, 3>({1, 2, 3}, 0, gen);
|
||||
|
||||
// Longer sequence.
|
||||
{
|
||||
std::array input = {1, 8, 2, 3, 4, 6, 5, 7};
|
||||
for (int i = 0; i <= static_cast<int>(input.size()); ++i){
|
||||
test_one<Iter, Sent, Out, input.size()>(input, i, gen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Iter, class Sent>
|
||||
void test_iterators_iter_sent() {
|
||||
if constexpr (std::forward_iterator<Iter>) {
|
||||
test_iterators_iter_sent_out<Iter, Sent, cpp20_output_iterator<int*>>();
|
||||
test_iterators_iter_sent_out<Iter, Sent, forward_iterator<int*>>();
|
||||
}
|
||||
test_iterators_iter_sent_out<Iter, Sent, random_access_iterator<int*>>();
|
||||
test_iterators_iter_sent_out<Iter, Sent, contiguous_iterator<int*>>();
|
||||
test_iterators_iter_sent_out<Iter, Sent, int*>();
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
void test_iterators_iter() {
|
||||
if constexpr (std::sentinel_for<Iter, Iter>) {
|
||||
test_iterators_iter_sent<Iter, Iter>();
|
||||
}
|
||||
test_iterators_iter_sent<Iter, sentinel_wrapper<Iter>>();
|
||||
}
|
||||
|
||||
void test_iterators() {
|
||||
test_iterators_iter<cpp20_input_iterator<int*>>();
|
||||
test_iterators_iter<random_access_iterator<int*>>();
|
||||
test_iterators_iter<contiguous_iterator<int*>>();
|
||||
test_iterators_iter<int*>();
|
||||
test_iterators_iter<const int*>();
|
||||
}
|
||||
|
||||
// Checks the logic for wrapping the given iterator to make sure it works correctly regardless of the value category of
|
||||
// the given generator object.
|
||||
template <class Gen, bool CheckConst = true>
|
||||
void test_generator() {
|
||||
std::array in = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
constexpr int N = 5;
|
||||
std::array<int, N> output;
|
||||
auto begin = in.begin();
|
||||
auto end = in.end();
|
||||
auto out = output.begin();
|
||||
|
||||
{ // Lvalue.
|
||||
Gen g;
|
||||
std::ranges::sample(begin, end, out, N, g);
|
||||
std::ranges::sample(in, out, N, g);
|
||||
}
|
||||
|
||||
if constexpr (CheckConst) { // Const lvalue.
|
||||
const Gen g;
|
||||
std::ranges::sample(begin, end, out, N, g);
|
||||
std::ranges::sample(in, out, N, g);
|
||||
}
|
||||
|
||||
{ // Prvalue.
|
||||
std::ranges::sample(begin, end, out, N, Gen());
|
||||
std::ranges::sample(in, out, N, Gen());
|
||||
}
|
||||
|
||||
{ // Xvalue.
|
||||
Gen g1, g2;
|
||||
std::ranges::sample(begin, end, out, N, std::move(g1));
|
||||
std::ranges::sample(in, out, N, std::move(g2));
|
||||
}
|
||||
}
|
||||
|
||||
// Checks the logic for wrapping the given iterator to make sure it works correctly regardless of whether the given
|
||||
// generator class has a const or non-const invocation operator (or both).
|
||||
void test_generators() {
|
||||
struct GenBase {
|
||||
constexpr static size_t min() { return 0; }
|
||||
constexpr static size_t max() { return 255; }
|
||||
};
|
||||
struct NonconstGen : GenBase {
|
||||
size_t operator()() { return 1; }
|
||||
};
|
||||
struct ConstGen : GenBase {
|
||||
size_t operator()() const { return 1; }
|
||||
};
|
||||
struct ConstAndNonconstGen : GenBase {
|
||||
size_t operator()() { return 1; }
|
||||
size_t operator()() const { return 1; }
|
||||
};
|
||||
|
||||
test_generator<ConstGen>();
|
||||
test_generator<NonconstGen, /*CheckConst=*/false>();
|
||||
test_generator<ConstAndNonconstGen>();
|
||||
}
|
||||
|
||||
void test() {
|
||||
test_iterators();
|
||||
test_generators();
|
||||
|
||||
{ // Stable (if `I` models `forward_iterator`).
|
||||
struct OrderedValue {
|
||||
int value;
|
||||
int original_order;
|
||||
bool operator==(const OrderedValue&) const = default;
|
||||
auto operator<=>(const OrderedValue& rhs) const { return value <=> rhs.value; }
|
||||
};
|
||||
|
||||
const std::array<OrderedValue, 8> in = {{
|
||||
{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}
|
||||
}};
|
||||
|
||||
{ // (iterator, sentinel) overload.
|
||||
std::array<OrderedValue, in.size()> out;
|
||||
std::ranges::sample(in.begin(), in.end(), out.begin(), in.size(), RandGen());
|
||||
assert(out == in);
|
||||
}
|
||||
|
||||
{ // (range) overload.
|
||||
std::array<OrderedValue, in.size()> out;
|
||||
std::ranges::sample(in, out.begin(), in.size(), RandGen());
|
||||
assert(out == in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
// Note: `ranges::sample` is not `constexpr`.
|
||||
|
||||
return 0;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
|
||||
// <algorithm>
|
||||
|
||||
// template <class PopulationIterator, class SampleIterator, class Distance,
|
||||
// class UniformRandomNumberGenerator>
|
||||
// SampleIterator sample(PopulationIterator first, PopulationIterator last,
|
||||
// SampleIterator out, Distance n,
|
||||
// UniformRandomNumberGenerator &&g);
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
template <class PopulationIterator, class SampleIterator> void test() {
|
||||
int ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
const unsigned is = sizeof(ia) / sizeof(ia[0]);
|
||||
const unsigned os = 4;
|
||||
int oa[os];
|
||||
std::minstd_rand g;
|
||||
std::sample(PopulationIterator(ia), PopulationIterator(ia + is),
|
||||
SampleIterator(oa), os, g);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed{{( due to requirement '.*')?}}{{.*}}SampleIterator must meet the requirements of RandomAccessIterator}}
|
||||
// expected-error@*:* 2 {{does not provide a subscript operator}}
|
||||
// expected-error@*:* {{invalid operands}}
|
||||
test<cpp17_input_iterator<int *>, cpp17_output_iterator<int *> >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
|
||||
// <algorithm>
|
||||
|
||||
// template <class PopulationIterator, class SampleIterator, class Distance,
|
||||
// class UniformRandomNumberGenerator>
|
||||
// SampleIterator sample(PopulationIterator first, PopulationIterator last,
|
||||
// SampleIterator out, Distance n,
|
||||
// UniformRandomNumberGenerator &&g);
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct ReservoirSampleExpectations {
|
||||
enum { os = 4 };
|
||||
static int oa1[os];
|
||||
static int oa2[os];
|
||||
};
|
||||
|
||||
int ReservoirSampleExpectations::oa1[] = {10, 5, 9, 4};
|
||||
int ReservoirSampleExpectations::oa2[] = {5, 2, 10, 4};
|
||||
|
||||
struct SelectionSampleExpectations {
|
||||
enum { os = 4 };
|
||||
static int oa1[os];
|
||||
static int oa2[os];
|
||||
};
|
||||
|
||||
int SelectionSampleExpectations::oa1[] = {1, 4, 6, 7};
|
||||
int SelectionSampleExpectations::oa2[] = {1, 2, 6, 8};
|
||||
|
||||
template <class IteratorCategory> struct TestExpectations
|
||||
: public SelectionSampleExpectations {};
|
||||
|
||||
template <>
|
||||
struct TestExpectations<std::input_iterator_tag>
|
||||
: public ReservoirSampleExpectations {};
|
||||
|
||||
template <template<class...> class PopulationIteratorType, class PopulationItem,
|
||||
template<class...> class SampleIteratorType, class SampleItem>
|
||||
void test() {
|
||||
typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
|
||||
typedef SampleIteratorType<SampleItem *> SampleIterator;
|
||||
PopulationItem ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
const unsigned is = sizeof(ia) / sizeof(ia[0]);
|
||||
typedef TestExpectations<typename std::iterator_traits<
|
||||
PopulationIterator>::iterator_category> Expectations;
|
||||
const unsigned os = Expectations::os;
|
||||
SampleItem oa[os];
|
||||
const int *oa1 = Expectations::oa1;
|
||||
((void)oa1); // Prevent unused warning
|
||||
const int *oa2 = Expectations::oa2;
|
||||
((void)oa2); // Prevent unused warning
|
||||
std::minstd_rand g;
|
||||
SampleIterator end = std::sample(PopulationIterator(ia),
|
||||
PopulationIterator(ia + is),
|
||||
SampleIterator(oa), os, g);
|
||||
assert(static_cast<std::size_t>(base(end) - oa) == std::min(os, is));
|
||||
// sample() is deterministic but non-reproducible;
|
||||
// its results can vary between implementations.
|
||||
LIBCPP_ASSERT(std::equal(oa, oa + os, oa1));
|
||||
end = std::sample(PopulationIterator(ia),
|
||||
PopulationIterator(ia + is),
|
||||
SampleIterator(oa), os, std::move(g));
|
||||
assert(static_cast<std::size_t>(base(end) - oa) == std::min(os, is));
|
||||
LIBCPP_ASSERT(std::equal(oa, oa + os, oa2));
|
||||
}
|
||||
|
||||
template <template<class...> class PopulationIteratorType, class PopulationItem,
|
||||
template<class...> class SampleIteratorType, class SampleItem>
|
||||
void test_empty_population() {
|
||||
typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
|
||||
typedef SampleIteratorType<SampleItem *> SampleIterator;
|
||||
PopulationItem ia[] = {42};
|
||||
const unsigned os = 4;
|
||||
SampleItem oa[os];
|
||||
std::minstd_rand g;
|
||||
SampleIterator end =
|
||||
std::sample(PopulationIterator(ia), PopulationIterator(ia),
|
||||
SampleIterator(oa), os, g);
|
||||
assert(base(end) == oa);
|
||||
}
|
||||
|
||||
template <template<class...> class PopulationIteratorType, class PopulationItem,
|
||||
template<class...> class SampleIteratorType, class SampleItem>
|
||||
void test_empty_sample() {
|
||||
typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
|
||||
typedef SampleIteratorType<SampleItem *> SampleIterator;
|
||||
PopulationItem ia[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
const unsigned is = sizeof(ia) / sizeof(ia[0]);
|
||||
SampleItem oa[1];
|
||||
std::minstd_rand g;
|
||||
SampleIterator end =
|
||||
std::sample(PopulationIterator(ia), PopulationIterator(ia + is),
|
||||
SampleIterator(oa), 0, g);
|
||||
assert(base(end) == oa);
|
||||
}
|
||||
|
||||
template <template<class...> class PopulationIteratorType, class PopulationItem,
|
||||
template<class...> class SampleIteratorType, class SampleItem>
|
||||
void test_small_population() {
|
||||
// The population size is less than the sample size.
|
||||
typedef PopulationIteratorType<PopulationItem *> PopulationIterator;
|
||||
typedef SampleIteratorType<SampleItem *> SampleIterator;
|
||||
PopulationItem ia[] = {1, 2, 3, 4, 5};
|
||||
const unsigned is = sizeof(ia) / sizeof(ia[0]);
|
||||
const unsigned os = 8;
|
||||
SampleItem oa[os];
|
||||
const SampleItem oa1[] = {1, 2, 3, 4, 5};
|
||||
std::minstd_rand g;
|
||||
SampleIterator end = std::sample(PopulationIterator(ia),
|
||||
PopulationIterator(ia + is),
|
||||
SampleIterator(oa), os, g);
|
||||
assert(static_cast<std::size_t>(base(end) - oa) == std::min(os, is));
|
||||
typedef typename std::iterator_traits<PopulationIterator>::iterator_category PopulationCategory;
|
||||
if (std::is_base_of<std::forward_iterator_tag, PopulationCategory>::value) {
|
||||
assert(std::equal(oa, base(end), oa1));
|
||||
} else {
|
||||
assert(std::is_permutation(oa, base(end), oa1));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<cpp17_input_iterator, int, random_access_iterator, int>();
|
||||
test<forward_iterator, int, cpp17_output_iterator, int>();
|
||||
test<forward_iterator, int, random_access_iterator, int>();
|
||||
|
||||
test<cpp17_input_iterator, int, random_access_iterator, double>();
|
||||
test<forward_iterator, int, cpp17_output_iterator, double>();
|
||||
test<forward_iterator, int, random_access_iterator, double>();
|
||||
|
||||
test_empty_population<cpp17_input_iterator, int, random_access_iterator, int>();
|
||||
test_empty_population<forward_iterator, int, cpp17_output_iterator, int>();
|
||||
test_empty_population<forward_iterator, int, random_access_iterator, int>();
|
||||
|
||||
test_empty_sample<cpp17_input_iterator, int, random_access_iterator, int>();
|
||||
test_empty_sample<forward_iterator, int, cpp17_output_iterator, int>();
|
||||
test_empty_sample<forward_iterator, int, random_access_iterator, int>();
|
||||
|
||||
test_small_population<cpp17_input_iterator, int, random_access_iterator, int>();
|
||||
test_small_population<forward_iterator, int, cpp17_output_iterator, int>();
|
||||
test_small_population<forward_iterator, int, random_access_iterator, int>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14
|
||||
|
||||
// <algorithm>
|
||||
|
||||
// template <class PopulationIterator, class SampleIterator, class Distance,
|
||||
// class UniformRandomNumberGenerator>
|
||||
// SampleIterator sample(PopulationIterator first, PopulationIterator last,
|
||||
// SampleIterator out, Distance n,
|
||||
// UniformRandomNumberGenerator &&g);
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
|
||||
// Stable if and only if PopulationIterator meets the requirements of a
|
||||
// ForwardIterator type.
|
||||
template <class PopulationIterator, class SampleIterator>
|
||||
void test_stability(bool expect_stable) {
|
||||
const unsigned kPopulationSize = 100;
|
||||
int ia[kPopulationSize];
|
||||
for (unsigned i = 0; i < kPopulationSize; ++i)
|
||||
ia[i] = i;
|
||||
PopulationIterator first(ia);
|
||||
PopulationIterator last(ia + kPopulationSize);
|
||||
|
||||
const unsigned kSampleSize = 20;
|
||||
int oa[kPopulationSize];
|
||||
SampleIterator out(oa);
|
||||
|
||||
std::minstd_rand g;
|
||||
|
||||
const int kIterations = 1000;
|
||||
bool unstable = false;
|
||||
for (int i = 0; i < kIterations; ++i) {
|
||||
std::sample(first, last, out, kSampleSize, g);
|
||||
unstable |= !std::is_sorted(oa, oa + kSampleSize);
|
||||
}
|
||||
assert(expect_stable == !unstable);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test_stability<forward_iterator<int *>, cpp17_output_iterator<int *> >(true);
|
||||
test_stability<cpp17_input_iterator<int *>, random_access_iterator<int *> >(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user