Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
persistent_vector_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
35#include <gtest/gtest.h>
36
38
39#include <memory>
40#include <random>
41#include <stdexcept>
42#include <vector>
43
44using namespace Aleph;
45
46namespace
47{
48 struct CopyTrackedValue
49 {
50 static inline int copy_assignments = 0;
51 static inline int moves = 0;
52
53 int value = 0;
54
55 CopyTrackedValue() = default;
56 explicit CopyTrackedValue(const int v) noexcept : value(v) {}
57 CopyTrackedValue(const CopyTrackedValue &) = default;
58
59 CopyTrackedValue &operator = (const CopyTrackedValue &other) noexcept
60 {
61 value = other.value;
62 ++copy_assignments;
63 return *this;
64 }
65
66 CopyTrackedValue(CopyTrackedValue &&other) noexcept : value(other.value)
67 {
68 ++moves;
69 }
70
71 CopyTrackedValue &operator = (CopyTrackedValue &&other) noexcept
72 {
73 value = other.value;
74 ++moves;
75 return *this;
76 }
77
78 bool operator == (const CopyTrackedValue &other) const noexcept
79 {
80 return value == other.value;
81 }
82
83 static void reset_counters() noexcept
84 {
85 copy_assignments = 0;
86 moves = 0;
87 }
88 };
89
90 template <typename T>
91 std::vector<T> to_vector(const PersistentVector<T> &vector)
92 {
93 std::vector<T> out;
94 out.reserve(vector.size());
95 for (size_t i = 0; i < vector.size(); ++i)
96 out.push_back(vector.get(i));
97 return out;
98 }
99}
100
102{
104
105 EXPECT_TRUE(vector.is_empty());
106 EXPECT_EQ(vector.size(), 0u);
108 EXPECT_TRUE(vector.verify());
109 EXPECT_THROW(vector.get(0), std::out_of_range);
110 EXPECT_THROW(vector.pop_back(), std::underflow_error);
111}
112
114{
116 auto one = empty.push_back(10);
117 auto two = one.push_back(20);
118 auto three = two.push_back(30);
119
120 EXPECT_TRUE(empty.is_empty());
121 EXPECT_EQ(one.size(), 1u);
122 EXPECT_EQ(two.size(), 2u);
123 EXPECT_EQ(three.size(), 3u);
124
125 EXPECT_EQ(one.get(0), 10);
126 EXPECT_EQ(two.get(0), 10);
127 EXPECT_EQ(two.get(1), 20);
128 EXPECT_EQ(three.get(2), 30);
129 EXPECT_TRUE(empty.verify());
130 EXPECT_TRUE(one.verify());
131 EXPECT_TRUE(two.verify());
132 EXPECT_TRUE(three.verify());
133}
134
136{
137 auto base = PersistentVector<int>().push_back(1).push_back(2).push_back(3);
138 auto changed = base.set(1, 99);
139
140 EXPECT_EQ(to_vector(base), (std::vector<int>{1, 2, 3}));
141 EXPECT_EQ(to_vector(changed), (std::vector<int>{1, 99, 3}));
142 EXPECT_TRUE(base.verify());
143 EXPECT_TRUE(changed.verify());
144 EXPECT_THROW(base.set(3, 10), std::out_of_range);
145}
146
148{
150 for (int i = 0; i < 40; ++i)
151 vector = vector.push_back(i);
152
153 auto popped = vector.pop_back();
154 for (int i = 0; i < 7; ++i)
156
157 EXPECT_EQ(vector.size(), 40u);
158 EXPECT_EQ(popped.size(), 32u);
159 EXPECT_EQ(vector.get(39), 39);
160 EXPECT_EQ(popped.get(31), 31);
161 EXPECT_THROW(popped.get(32), std::out_of_range);
162 EXPECT_TRUE(vector.verify());
163 EXPECT_TRUE(popped.verify());
164}
165
167{
169 for (int i = 0; i < 1100; ++i)
170 vector = vector.push_back(i * 3);
171
172 ASSERT_EQ(vector.size(), 1100u);
173 EXPECT_EQ(vector.get(0), 0);
174 EXPECT_EQ(vector.get(31), 93);
175 EXPECT_EQ(vector.get(32), 96);
176 EXPECT_EQ(vector.get(1023), 3069);
177 EXPECT_EQ(vector.get(1024), 3072);
178 EXPECT_EQ(vector.get(1099), 3297);
179
180 auto changed = vector.set(1024, -1);
181 EXPECT_EQ(vector.get(1024), 3072);
182 EXPECT_EQ(changed.get(1024), -1);
183 EXPECT_TRUE(vector.verify());
184 EXPECT_TRUE(changed.verify());
185}
186
188{
190 for (int i = 0; i < 10; ++i)
191 vector = vector.push_back(i);
192
193 auto array = vector.to_array();
194 ASSERT_EQ(array.size(), 10u);
195 for (size_t i = 0; i < array.size(); ++i)
196 EXPECT_EQ(array[i], static_cast<int>(i));
197}
198
200{
202 const CopyTrackedValue one{1};
203 const CopyTrackedValue two{2};
204
205 vector = vector.push_back(one).push_back(two);
206
207 CopyTrackedValue::reset_counters();
208 auto array = vector.to_array();
209 ASSERT_EQ(array.size(), 2u);
210 EXPECT_EQ(array[0].value, 1);
211 EXPECT_EQ(array[1].value, 2);
212 EXPECT_EQ(CopyTrackedValue::copy_assignments, 2);
213 EXPECT_EQ(CopyTrackedValue::moves, 0);
214 EXPECT_TRUE(vector.verify());
215}
216
218{
220 auto one = vector.push_back(std::make_unique<int>(10));
221 auto two = one.push_back(std::make_unique<int>(20));
222 auto changed = two.set(0, std::make_unique<int>(99));
223
224 EXPECT_EQ(*one.get(0), 10);
225 EXPECT_EQ(*two.get(0), 10);
226 EXPECT_EQ(*two.get(1), 20);
227 EXPECT_EQ(*changed.get(0), 99);
228 EXPECT_EQ(*changed.get(1), 20);
229 EXPECT_TRUE(one.verify());
230 EXPECT_TRUE(two.verify());
231 EXPECT_TRUE(changed.verify());
232}
233
235{
236 std::mt19937 rng(0xFACEB00Cu);
237 std::uniform_int_distribution<int> op_dist(0, 2);
238 std::uniform_int_distribution<int> value_dist(-5000, 5000);
239
241 std::vector<int> reference;
242 std::vector<PersistentVector<int>> old_subjects;
243 std::vector<std::vector<int>> old_references;
244
245 for (int iter = 0; iter < 1800; ++iter)
246 {
247 if (iter % 53 == 0)
248 {
250 old_references.push_back(reference);
251 }
252
253 const int op = reference.empty() ? 0 : op_dist(rng);
254 if (op == 0)
255 {
256 const int value = value_dist(rng);
257 subject = subject.push_back(value);
258 reference.push_back(value);
259 }
260 else if (op == 1)
261 {
262 std::uniform_int_distribution<size_t> index_dist(0, reference.size() - 1);
263 const size_t index = index_dist(rng);
264 const int value = value_dist(rng);
265 subject = subject.set(index, value);
266 reference[index] = value;
267 }
268 else
269 {
270 subject = subject.pop_back();
271 reference.pop_back();
272 }
273
274 ASSERT_TRUE(subject.verify());
275 ASSERT_EQ(subject.size(), reference.size());
276 for (size_t i = 0; i < reference.size(); ++i)
277 ASSERT_EQ(subject.get(i), reference[i]) << "index " << i;
278 }
279
280 for (size_t i = 0; i < old_subjects.size(); ++i)
282}
size_t size_t int32_t value
Definition ca-c-api.h:116
size_t size_t int32_t * out
Definition ca-c-api.h:120
Immutable vector backed by a 32-way bitmapped trie.
Array< T > to_array() const
Return all values in an Aleph array.
PersistentVector push_back(const T &value) const
Return a new version with value appended by copy.
const T & get(const size_t index) const
Read a value by index.
bool verify() const noexcept
Verify trie shape and logical prefix invariants.
PersistentVector set(const size_t index, const T &value) const
Return a new version with one index replaced by copy.
size_t size() const noexcept
Return the number of values in this version.
bool is_empty() const noexcept
Return true when the vector has no values.
PersistentVector pop_back() const
Return a new version without the last value.
#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
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool operator==(const DynList< T > &l1, const DynList< T > &l2)
Equality operator for DynList.
std::vector< typename C::Item_Type > to_vector(const C &c)
Convert a container to a std::vector.
Definition ah-convert.H:238
Immutable bitmapped-vector trie with structural sharing.