Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
flat_set_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 https://github.com/lrleon/Aleph-w
6
7 This file is part of Aleph-w library
8
9 Copyright (c) 2002-2026 Leandro Rabindranath Leon
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28*/
29
40#include <random>
41#include <set>
42#include <stdexcept>
43#include <string>
44#include <vector>
45
46#include <gtest/gtest.h>
47
48#include <tpl_flat_set.H>
49
50using Aleph::FlatSet;
51
53{
56 EXPECT_EQ(s.size(), 0u);
58 EXPECT_EQ(s.find(42), s.end());
59 EXPECT_EQ(s.begin(), s.end());
60 EXPECT_EQ(s.count(42), 0u);
61}
62
64{
66 EXPECT_TRUE(s.insert(5).second);
67 EXPECT_TRUE(s.insert(1).second);
68 EXPECT_TRUE(s.insert(3).second);
69 EXPECT_FALSE(s.insert(3).second); // duplicate
70
71 ASSERT_EQ(s.size(), 3u);
72 EXPECT_EQ(s.nth(0), 1);
73 EXPECT_EQ(s.nth(1), 3);
74 EXPECT_EQ(s.nth(2), 5);
75
76 // The iterator returned on a duplicate points to the existing element.
77 auto [it, inserted] = s.insert(1);
78 EXPECT_FALSE(inserted);
79 EXPECT_EQ(*it, 1);
80 EXPECT_EQ(it, s.begin());
81}
82
84{
85 FlatSet<int> s = {5, 1, 3, 1, 5, 5};
86 ASSERT_EQ(s.size(), 3u);
87 EXPECT_EQ(s.nth(0), 1);
88 EXPECT_EQ(s.nth(1), 3);
89 EXPECT_EQ(s.nth(2), 5);
90}
91
93{
94 const std::vector<int> v = {9, 7, 7, 8, 1};
95 FlatSet<int> s(v.begin(), v.end());
96 ASSERT_EQ(s.size(), 4u);
97 EXPECT_TRUE(std::is_sorted(s.begin(), s.end()));
101}
102
104{
105 const FlatSet<int> s = {10, 20, 30, 40};
106
107 EXPECT_EQ(*s.lower_bound(20), 20);
108 EXPECT_EQ(*s.lower_bound(25), 30);
109 EXPECT_EQ(*s.upper_bound(20), 30);
110 EXPECT_EQ(s.lower_bound(50), s.end());
111 EXPECT_EQ(s.upper_bound(40), s.end());
112 EXPECT_EQ(*s.lower_bound(5), 10);
113
114 auto [lo, hi] = s.equal_range(30);
115 ASSERT_EQ(hi - lo, 1);
116 EXPECT_EQ(*lo, 30);
117
118 auto [lo2, hi2] = s.equal_range(35);
119 EXPECT_EQ(lo2, hi2);
120}
121
123{
124 FlatSet<int> s = {1, 2, 3, 4, 5};
125
126 EXPECT_EQ(s.erase(3), 1u);
127 EXPECT_EQ(s.erase(3), 0u); // already gone
128 EXPECT_EQ(s.size(), 4u);
130
131 auto it = s.find(2);
132 ASSERT_NE(it, s.end());
133 it = s.erase(it);
134 EXPECT_EQ(*it, 4); // element following the erased one
135 EXPECT_EQ(s.size(), 3u);
136
137 // Erasing an end iterator must throw out_of_range.
138 EXPECT_THROW((void) s.erase(s.end()), std::out_of_range);
139}
140
142{
143 FlatSet<int> s = {7, 3, 9};
144 EXPECT_EQ(s.get_first(), 3);
145 EXPECT_EQ(s.get_last(), 9);
146 EXPECT_EQ(s.min(), 3);
147 EXPECT_EQ(s.max(), 9);
148 EXPECT_THROW((void) s.nth(3), std::out_of_range);
149
150 const FlatSet<int> e;
151 EXPECT_THROW((void) e.get_first(), std::underflow_error);
152 EXPECT_THROW((void) e.get_last(), std::underflow_error);
153}
154
156{
157 FlatSet<int> s = {1, 2, 3};
158
159 // Aleph convention: empty() clears, is_empty() tests.
160 s.empty();
162
163 s = {4, 5, 6, 7};
164 s.clear();
166
167 s = {1, 2, 3, 4};
168 int sum = 0;
169 EXPECT_TRUE(s.traverse([&sum] (const int &x) { sum += x; return true; }));
170 EXPECT_EQ(sum, 10);
171
172 // Early stop: visit only until (and including) the first even key.
173 int visited = 0;
174 EXPECT_FALSE(s.traverse([&visited] (const int &x)
175 {
176 ++visited;
177 return x % 2 != 0;
178 }));
179 EXPECT_EQ(visited, 2); // 1 (odd, continue), 2 (even, stop)
180}
181
183{
184 FlatSet<std::string> s = {"beta", "alpha", "gamma"};
186 EXPECT_EQ(copy, s);
187
188 FlatSet<std::string> moved = std::move(copy);
189 EXPECT_EQ(moved, s);
190
191 moved.insert("delta");
192 EXPECT_NE(moved, s);
193
195 assigned = s;
197
199 move_assigned = std::move(assigned);
201}
202
204{
205 FlatSet<int, std::greater<int>> s = {1, 5, 3};
206 EXPECT_EQ(s.nth(0), 5);
207 EXPECT_EQ(s.nth(1), 3);
208 EXPECT_EQ(s.nth(2), 1);
209 EXPECT_TRUE(s.contains(3));
210 EXPECT_FALSE(s.insert(5).second);
211}
212
214{
215 FlatSet<int> s;
216 s.reserve(1000);
217 const size_t cap = s.capacity();
218 EXPECT_GE(cap, 1000u);
219 for (int i = 0; i < 1000; ++i)
220 s.insert(i);
221 EXPECT_EQ(s.capacity(), cap); // no reallocation after reserve
222 EXPECT_EQ(s.size(), 1000u);
223}
224
226{
227 FlatSet<int> s = {4, 2, 8, 6};
228 const int *p = s.data();
229 ASSERT_EQ(s.size(), 4u);
230 EXPECT_EQ(p[0], 2);
231 EXPECT_EQ(p[3], 8);
232 EXPECT_EQ(s.begin(), p);
233 EXPECT_EQ(s.end(), p + 4);
234}
235
237{
238 FlatSet<int> a = {1, 2};
239 FlatSet<int> b = {9};
240 a.swap(b);
241 EXPECT_EQ(a.size(), 1u);
242 EXPECT_TRUE(a.contains(9));
243 EXPECT_EQ(b.size(), 2u);
244 EXPECT_TRUE(b.contains(1) and b.contains(2));
245}
246
247// Randomized parity test: FlatSet must behave exactly like std::set under
248// an arbitrary interleaving of insertions, removals and lookups.
250{
251 std::mt19937 rng(20260702);
252 std::uniform_int_distribution<int> key_dist(0, 200);
253 std::uniform_int_distribution<int> op_dist(0, 2);
254
255 FlatSet<int> fs;
256 std::set<int> ref;
257
258 for (int step = 0; step < 4000; ++step)
259 {
260 const int k = key_dist(rng);
261 switch (op_dist(rng))
262 {
263 case 0:
264 EXPECT_EQ(fs.insert(k).second, ref.insert(k).second);
265 break;
266 case 1:
267 EXPECT_EQ(fs.erase(k), ref.erase(k));
268 break;
269 default:
270 EXPECT_EQ(fs.contains(k), ref.count(k) == 1);
271 break;
272 }
273 }
274
275 ASSERT_EQ(fs.size(), ref.size());
276 size_t i = 0;
277 for (const int k : ref)
278 EXPECT_EQ(fs.nth(i++), k);
279}
Ordered set stored as a sorted contiguous array.
size_t capacity() const noexcept
Return the capacity of the backing array. O(1).
const Key & min() const
Smallest key (checked). Alias of get_first().
const_iterator upper_bound(const Key &k) const
First element greater than k.
size_t erase(const Key &k)
Remove the key equivalent to k, if present.
const_iterator end() const noexcept
Iterator past the greatest key. O(1).
const_iterator find(const Key &k) const
Find a key.
void empty() noexcept
Remove all keys (Aleph convention).
size_t count(const Key &k) const
Count occurrences of a key (0 or 1).
std::pair< const_iterator, const_iterator > equal_range(const Key &k) const
Range of elements equivalent to k.
void clear() noexcept
Remove all keys. Alias of empty(). Capacity is kept.
const Key & max() const
Greatest key (checked). Alias of get_last().
bool traverse(Operation operation) const
Traverse keys in sorted order while operation returns true.
const Key * data() const noexcept
Pointer to the underlying sorted, contiguous storage. O(1).
void reserve(size_t cap)
Reserve capacity for at least cap keys.
const_iterator lower_bound(const Key &k) const
First element not less than k.
bool contains(const Key &k) const
Test membership.
size_t size() const noexcept
Return the number of stored keys. O(1).
bool is_empty() const noexcept
Return true if the set holds no keys. O(1).
const Key & get_first() const
Smallest key (checked).
const Key & nth(size_t i) const
Positional access to the i-th smallest key (checked).
std::pair< const_iterator, bool > insert(const Key &k)
Insert a copy of k if no equivalent key exists.
const Key & get_last() const
Greatest key (checked).
void swap(FlatSet &s) noexcept(std::is_nothrow_swappable_v< Compare >)
Swap contents with s in O(1).
const_iterator begin() const noexcept
Iterator to the smallest key. O(1).
#define TEST(name)
static mt19937 rng
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
and
Check uniqueness with explicit hash + equality functors.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
static int * k
Sorted-array set (Aleph::FlatSet), a cache-friendly ordered set.