15 #include <gtest/gtest.h>
20 #include <type_traits>
21 #include <unordered_map>
24 #include <range/v3/algorithm/count.hpp>
25 #include <range/v3/algorithm/find.hpp>
26 #include <range/v3/range/access.hpp>
27 #include <range/v3/range/concepts.hpp>
28 #include <range/v3/range/conversion.hpp>
29 #include <range/v3/range/dangling.hpp>
30 #include <range/v3/range/primitives.hpp>
31 #include <range/v3/view/const.hpp>
32 #include <range/v3/view/take_exactly.hpp>
41 TEST(SampleView, FromEmptyRange) {
42 auto input = std::vector<int>{};
46 TEST(SampleView, ConceptChecksFromContiguousRange) {
47 auto input = std::array{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
50 static_assert(ranges::common_range<decltype(input)>);
51 static_assert(!ranges::common_range<decltype(output)>);
53 static_assert(!ranges::viewable_range<decltype(input)>);
54 static_assert(ranges::viewable_range<decltype(output)>);
56 static_assert(ranges::forward_range<decltype(input)>);
57 static_assert(!ranges::forward_range<decltype(output)>);
59 static_assert(ranges::sized_range<decltype(input)>);
60 static_assert(!ranges::sized_range<decltype(output)>);
62 static_assert(ranges::bidirectional_range<decltype(input)>);
63 static_assert(!ranges::bidirectional_range<decltype(output)>);
65 static_assert(ranges::random_access_range<decltype(input)>);
66 static_assert(!ranges::random_access_range<decltype(output)>);
68 static_assert(ranges::contiguous_range<decltype(input)>);
69 static_assert(!ranges::contiguous_range<decltype(output)>);
71 static_assert(ranges::range<decltype(output)>);
72 static_assert(ranges::semiregular<decltype(output)>);
73 static_assert(ranges::enable_view<decltype(output)>);
76 TEST(SampleView, UniformDistributionSingleElement) {
77 auto input = std::array{5};
79 ASSERT_EQ(ranges::count(output, 5), 20);
82 TEST(SampleView, DiscreteDistributionSingleElement) {
83 auto input = std::array{5};
86 ASSERT_EQ(ranges::count(output, 5), 20);
89 TEST(SampleView, DiscreteDistributionSingleElementFromParticleRange) {
93 auto output = input |
beluga::views::sample | ranges::views::take_exactly(20) | ranges::to<std::vector>;
98 TEST(SampleView, DiscreteDistributionWeightZero) {
99 auto input = std::array{42, 5};
100 auto weights = std::array{0.0, 1.0};
102 ASSERT_EQ(ranges::count(output, 5), 20);
105 TEST(SampleView, DoubleDereference) {
106 auto engine = std::mt19937{std::random_device()()};
107 auto input = std::array{10, 42, 39, 20, 50};
109 auto it = ranges::begin(output);
112 ASSERT_EQ(value, *it);
113 ASSERT_EQ(value, *it);
116 TEST(SampleView, NonBorrowedRange) {
117 auto input = std::array{42};
119 auto it = ranges::find(create_view(), 42);
120 static_assert(std::is_same_v<decltype(it), ranges::dangling>);
124 TEST(SampleView, EngineArgument) {
125 auto engine = std::mt19937{std::random_device()()};
126 auto input = std::array{5};
127 auto weights = std::array{1.0};
128 auto particles = std::array{std::make_tuple(5,
beluga::Weight(1.0))};
130 [[maybe_unused]]
auto view2 = input | view1;
131 [[maybe_unused]]
auto view3 = particles | view1;
137 TEST(SampleView, DiscreteDistributionProbability) {
138 const auto size = 100
'000;
140 const auto input = beluga::TupleVector<std::tuple<int, beluga::Weight>>{
141 std::make_tuple(1, beluga::Weight(0.3)), //
142 std::make_tuple(2, beluga::Weight(0.1)), //
143 std::make_tuple(3, beluga::Weight(0.4)), //
144 std::make_tuple(4, beluga::Weight(0.2))};
146 auto output = input | //
147 ranges::views::const_ | //
148 beluga::views::sample | //
149 ranges::views::take_exactly(size);
151 std::unordered_map<int, std::size_t> buckets;
152 for (auto [value, weight] : output) {
154 ASSERT_EQ(weight, 1.0);
157 ASSERT_EQ(ranges::size(buckets), 4);
159 ASSERT_NEAR(static_cast<double>(buckets[1]) / size, 0.3, 0.01);
160 ASSERT_NEAR(static_cast<double>(buckets[2]) / size, 0.1, 0.01);
161 ASSERT_NEAR(static_cast<double>(buckets[3]) / size, 0.4, 0.01);
162 ASSERT_NEAR(static_cast<double>(buckets[4]) / size, 0.2, 0.01);
165 TEST(SampleView, FromRandomDistributionFalse) {
166 auto distribution = std::bernoulli_distribution{0.0};
167 auto output = beluga::views::sample(distribution) | ranges::views::take_exactly(10);
168 ASSERT_EQ(ranges::count(output, false), 10);
171 TEST(SampleView, FromRandomDistributionTrue) {
172 auto distribution = std::bernoulli_distribution{1.0};
173 auto output = beluga::views::sample(distribution) | ranges::views::take_exactly(10);
174 ASSERT_EQ(ranges::count(output, true), 10);