Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
memarray.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
33
38# include <gtest/gtest.h>
39
40# include <tpl_memArray.H>
41# include <htlist.H>
42
43using namespace std;
44using namespace testing;
45using namespace Aleph;
46
47bool is_power_of_two(size_t x)
48{
49 return ((x != 0) && !(x & (x - 1))) != 0;
50}
51
52struct Default_MemArray : public Test
53{
54 const size_t n = 64;
56};
57
58struct MemArray_with_30_items : public Test
59{
62 {
63 for (size_t i = 0; i < 30; ++i)
64 m.append(i);
65 }
66};
67
69{
70 {
72 EXPECT_TRUE(is_power_of_two(m1.capacity()));
73 EXPECT_EQ(m1.size(), 0);
75 EXPECT_THROW(m1.get(), underflow_error);
76 }
77
78 {
79 MemArray<int> m1(32);
80 EXPECT_TRUE(is_power_of_two(m1.capacity()));
81 EXPECT_EQ(m1.size(), 0);
83 EXPECT_THROW(m1.get(), underflow_error);
84
85 MemArray<int> m2(31);
86 MemArray<int> m3(17);
87 EXPECT_TRUE(is_power_of_two(m2.capacity()));
90 EXPECT_EQ(m2.size(), 0);
91 EXPECT_EQ(m3.size(), 0);
92 EXPECT_EQ(m1.capacity(), m2.capacity());
93 EXPECT_EQ(m1.capacity(), m3.capacity());
94 }
95
96 {
97 MemArray<int> m1(512);
98 EXPECT_TRUE(is_power_of_two(m1.capacity()));
99 EXPECT_EQ(m1.size(), 0);
101 EXPECT_THROW(m1.get(), underflow_error);
102
103 MemArray<int> m2(257);
104 MemArray<int> m3(316);
105 EXPECT_TRUE(is_power_of_two(m2.capacity()));
108 EXPECT_EQ(m2.size(), 0);
109 EXPECT_EQ(m3.size(), 0);
110 EXPECT_EQ(m1.capacity(), m2.capacity());
111 EXPECT_EQ(m1.capacity(), m3.capacity());
112 }
113
114 {
115 MemArray<int> m1(4096);
116 EXPECT_TRUE(is_power_of_two(m1.capacity()));
117 EXPECT_EQ(m1.size(), 0);
119 EXPECT_THROW(m1.get(), underflow_error);
120
121 MemArray<int> m2(2049);
122 MemArray<int> m3(3000);
123 EXPECT_TRUE(is_power_of_two(m2.capacity()));
126 EXPECT_EQ(m2.size(), 0);
127 EXPECT_EQ(m3.size(), 0);
128 EXPECT_EQ(m1.capacity(), m2.capacity());
129 EXPECT_EQ(m1.capacity(), m3.capacity());
130 }
131}
132
134{
135 const size_t n = m.capacity();
136 for (size_t i = 0; i < n; ++i)
137 m.append(i);
138
139 EXPECT_EQ(m.size(), n);
140 EXPECT_EQ(m.capacity(), n);
141
142 m.append(n); // this append would cause expansion
143 EXPECT_EQ(m.capacity(), 2 * n);
144 EXPECT_EQ(m.size(), n + 1);
145 EXPECT_EQ(m.get_first(), 0);
146 EXPECT_EQ(m.get_last(), n);
147
148 // testing gap opening
149 m.insert(-1);
150 EXPECT_EQ(m.get_first(), -1);
151 EXPECT_EQ(m.get_last(), n);
152
153 EXPECT_THROW(m[m.size()], out_of_range);
154 EXPECT_THROW(m[m.capacity()], out_of_range);
155
156 { // Testing operator [] in read mode
157 int k = -1;
158 for (size_t i = 0; i < m.size(); ++i, ++k)
159 EXPECT_EQ(m[i], k);
160 EXPECT_EQ(k, n + 1);
161 }
162
163 { // Testing operator [] in write mode
164 for (size_t i = 0; i < m.size(); ++i)
165 m[i]++;
166
167 int k = 0;
168 for (size_t i = 0; i < m.size(); ++i, ++k)
169 EXPECT_EQ(m[i], k);
170 EXPECT_EQ(k, n + 2);
171 }
172}
173
175{
176 const size_t dim = m.capacity();
177
178 m.putn(dim + 1); // This will cause expansion
179
180 EXPECT_EQ(m.capacity(), 2 * dim); // Verify expansion
181 EXPECT_FALSE(m.is_empty());
182 EXPECT_EQ(m.size(), dim + 1);
183
184 for (size_t i = 0; i < m.size(); ++i)
185 {
186 EXPECT_NO_THROW(m[i]);
187 m[i] = i;
188 }
189
190 EXPECT_THROW(m[m.size()], out_of_range);
191 EXPECT_THROW(m.get(m.size() + 1), underflow_error);
192
193 size_t k = 0;
194 EXPECT_NE(m.size(), k);
195 for (size_t i = 0; i < m.size(); ++i, ++k)
196 EXPECT_EQ(m[i], i);
197 EXPECT_EQ(k, m.size()); // TEST that loop has been executed
198
199 const size_t curr_cap = m.capacity();
200 const size_t avail = m.capacity() - m.size();
201 m.putn(avail); // this shouldn't cause expansion
202
203 EXPECT_EQ(m.capacity(), curr_cap);
204 EXPECT_EQ(m.size(), m.capacity());
205
206 int item;
207 EXPECT_NO_THROW(item = m.get(m.size())); // it must take out all items
208
209 EXPECT_EQ(item, 0);
210 EXPECT_TRUE(m.is_empty());
211 EXPECT_EQ(m.size(), 0);
212}
213
215{
216 EXPECT_TRUE(m.is_empty());
217 EXPECT_EQ(m.size(), 0);
218 EXPECT_NE(m.capacity(), 0);
219
220 const size_t cap1 = m.capacity();
221
222 // Test invalid accesses without insertion neither expansion
223 size_t k = 0;
224 for (size_t i = 0; i < m.capacity(); ++i, ++k)
225 EXPECT_THROW(m[i], out_of_range);
226 EXPECT_EQ(k, m.capacity());
227 EXPECT_EQ(m.capacity(), cap1); // capacity has not changed
228 EXPECT_TRUE(m.is_empty());
229 EXPECT_EQ(m.size(), 0);
230
231 // Insert until capacity (no expansion)
232 k = 0;
233 for (size_t i = 0; i < m.capacity(); ++i, ++k)
234 m.append(i);
235 EXPECT_EQ(k, m.capacity());
236 EXPECT_EQ(m.size(), m.capacity());
237
238 // Test that item were inserted
239 k = 0;
240 for (size_t i = 0; i < m.capacity(); ++i, ++k)
241 {
242 EXPECT_NO_THROW(m[i]);
243 EXPECT_EQ(m[i], i);
244 }
245 EXPECT_EQ(k, m.capacity());
246
247 // Now we cause an expansion
248 k = 0;
249 for (size_t i = m.size(); i < 2 * cap1; ++i, ++k)
250 m.append(i);
251
252 EXPECT_EQ(k, cap1);
253 EXPECT_EQ(m.capacity(), 2 * cap1);
254 EXPECT_EQ(m.size(), 2 * cap1);
255
256 k = 0;
257 for (size_t i = 0; i < m.size(); ++i, ++k)
258 {
259 EXPECT_NO_THROW(m[i]);
260 EXPECT_EQ(m[i], i);
261 }
262 EXPECT_EQ(k, m.capacity());
263}
264
266{
267 const size_t cap = m.capacity();
268 EXPECT_TRUE(m.is_empty());
269 EXPECT_NE(m.capacity(), 0);
270 EXPECT_EQ(m.size(), 0);
271
272 m.reserve(2 * cap + 1); // this should expand to 4*cap
273 EXPECT_EQ(m.capacity(), 4 * cap);
274}
275
277{
278 EXPECT_FALSE(m.is_empty());
279 EXPECT_EQ(m.size(), 30);
280 EXPECT_EQ(m.capacity(), 32);
281 size_t k = 0;
282 for (size_t i = 0; i < m.size(); ++i, ++k)
283 EXPECT_EQ(m[i], i);
284 EXPECT_EQ(k, m.size());
285
286 { // Copy constructor
287 MemArray<int> aux = m;
288 EXPECT_FALSE(aux.is_empty());
289 EXPECT_EQ(aux.size(), 30);
290 EXPECT_EQ(aux.capacity(), 32);
291 size_t k = 0;
292 for (size_t i = 0; i < m.size(); ++i, ++k)
293 EXPECT_EQ(aux[i], i);
294 EXPECT_EQ(k, m.size());
295 EXPECT_NE(m.get_ptr(), aux.get_ptr());
296 }
297
298 { // move constructor
299 auto ptr = m.get_ptr();
300 MemArray<int> aux = move(m);
301 EXPECT_EQ(aux.get_ptr(), ptr);
302 EXPECT_FALSE(aux.is_empty());
303 EXPECT_EQ(aux.size(), 30);
304 EXPECT_EQ(aux.capacity(), 32);
305 EXPECT_TRUE(m.is_empty());
306 EXPECT_EQ(m.size(), 0);
307 EXPECT_EQ(m.capacity(), 0);
308 EXPECT_EQ(m.get_ptr(), nullptr); // array of zero must be nullptr
309 size_t k = 0;
310 for (size_t i = 0; i < m.size(); ++i, ++k)
311 EXPECT_EQ(aux[i], i);
312 EXPECT_EQ(k, m.size());
313 EXPECT_NE(m.get_ptr(), aux.get_ptr());
314
315 m.swap(aux); // restore m to previous initialized state
316 EXPECT_EQ(m.get_ptr(), ptr);
317 EXPECT_TRUE(aux.is_empty());
318 EXPECT_EQ(aux.size(), 0);
319 EXPECT_EQ(aux.capacity(), 0);
320 EXPECT_FALSE(m.is_empty());
321 EXPECT_EQ(m.size(), 30);
322 EXPECT_EQ(m.capacity(), 32);
323 k = 0;
324 for (size_t i = 0; i < m.size(); ++i, ++k)
325 EXPECT_EQ(m[i], i);
326 EXPECT_EQ(k, m.size());
327 }
328
329 // copy assigment
330 MemArray<int> aux;
331 EXPECT_TRUE(aux.is_empty());
332 EXPECT_EQ(aux.size(), 0);
333 EXPECT_NE(aux.capacity(), 0);
334 EXPECT_NE(aux.get_ptr(), nullptr);
335
336 aux = m;
337 EXPECT_FALSE(aux.is_empty());
338 EXPECT_NE(m.size(), 0);
339 EXPECT_EQ(aux.size(), m.size());
340 EXPECT_EQ(aux.capacity(), m.capacity());
341 EXPECT_FALSE(m.is_empty());
342 EXPECT_NE(m.size(), 0);
343 EXPECT_NE(m.capacity(), 0);
344 EXPECT_NE(m.get_ptr(), aux.get_ptr()); // array of zero must be nullptr
345 k = 0;
346 for (size_t i = 0; i < m.size(); ++i, ++k)
347 EXPECT_EQ(aux[i], m[i]);
348 EXPECT_EQ(k, m.size());
349
350 // TODO move assigment
351}
352
354{
355 MemArray<int> m(0);
356 EXPECT_NE(m.capacity(), 0);
357 EXPECT_EQ(m.size(), 0);
358 EXPECT_NE(m.get_ptr(), nullptr);
360}
361
363{
365 EXPECT_EQ(m.size(), 0);
367
368 size_t N = 0;
369 for (size_t i = 0; i < 10; ++i)
370 {
373 for (size_t k = 0; k < 10; ++k, ++N)
374 l.append(N);
376 m.insert(move(l));
378 }
379
380 size_t n = 0;
381 for (long i = 9; i >= 0; --i) // descending for matching values of N
382 {
383 const DynList<int> &l = m[i];
385 for (auto it = l.get_it(); it.has_curr(); it.next(), ++n)
386 EXPECT_EQ(it.get_curr(), n);
387 }
388}
389
391{
392 constexpr size_t num_items = 10;
394 size_t N = 0;
395 for (size_t i = 0; i < num_items; ++i)
396 {
399 for (size_t k = 0; k < num_items; ++k, ++N)
400 l.insert(N);
402 m.insert(move(l));
404 }
405
406 size_t n = N - 1;
407 for (size_t i = 0; i < num_items; ++i)
408 {
410 auto it = l.get_it();
411 for (size_t k = 0; k < 10; ++k, it.next(), --n)
412 EXPECT_EQ(it.get_curr(), n);
413 assert(num_items - i < m.capacity()); // hard assert. Better leave it!
414 EXPECT_TRUE(m(num_items - i - 1).is_empty()); // verify moving
415 }
416}
417
419{
420 for (size_t i = 0; i < n; ++i)
421 m.append(i);
422
423 EXPECT_EQ(m.capacity(), n);
424 EXPECT_EQ(m.capacity(), m.size());
425
426 size_t N = m.capacity();
427 for (size_t i = 0; i < n; ++i)
428 {
429 EXPECT_EQ(m.remove_last(), n - i - 1);
430 if (m.size() == N / 4 - 1 and m.size() > m.contract_threshold)
431 {
432 N /= 2;
433 EXPECT_EQ(m.capacity(), N); // valid if contraction was done!
434 }
435 }
436}
437
439{
440 EXPECT_THROW(m.remove_last(), underflow_error);
441 EXPECT_THROW(m.remove_first(), underflow_error);
442 EXPECT_THROW(m.get(), underflow_error);
443 EXPECT_THROW(m.get(2), underflow_error);
444}
445
447{
449
450 EXPECT_THROW(m.top(), underflow_error);
451
452 for (size_t i = 0; i < 100; ++i)
453 EXPECT_EQ(m.push(i), i);
454
455 for (size_t i = 100; i > 0; --i)
456 EXPECT_EQ(m.pop(), i - 1);
457
459 ASSERT_EQ(m.size(), 0);
460 EXPECT_THROW(m.top(), underflow_error);
461 EXPECT_THROW(m.pop(), underflow_error);
462}
463
465{
469 EXPECT_THROW(it.get_curr(), overflow_error);
470 EXPECT_THROW(it.next(), overflow_error);
471 EXPECT_THROW(it.prev(), underflow_error);
472 it.reset();
474 EXPECT_THROW(it.get_curr(), overflow_error);
475 EXPECT_THROW(it.next(), overflow_error);
476 EXPECT_THROW(it.prev(), underflow_error);
477 it.reset_last();
479 EXPECT_THROW(it.get_curr(), underflow_error);
480 EXPECT_THROW(it.next(), overflow_error);
481 EXPECT_THROW(it.prev(), underflow_error);
482}
483
485{
486 int i = 0;
487 for (MemArray<int>::Iterator it = m; it.has_curr(); it.next(), ++i)
488 EXPECT_EQ(it.get_curr(), i);
489
491 it.reset_last();
492 i = n - 1;
493 for (MemArray<int>::Iterator it = m; it.has_curr(); it.prev(), --i)
494 EXPECT_EQ(it.get_curr(), i);
495}
496
498{
500 size_t n = 0;
501 auto ret = m.traverse([&n](int)
502 {
503 ++n;
504 return true;
505 });
507 EXPECT_EQ(n, 0);
508}
509
511{
512 int N = 0;
513 auto ret = m.traverse([&N, this](int i)
514 {
515 ++N;
516 return i == n / 2;
517 }); // m is empty
519 EXPECT_EQ(N, 0);
520
521 for (size_t i = 0; i < n; ++i)
522 m.append(i);
523
524 EXPECT_EQ(N, 0);
525 EXPECT_TRUE(m.size() > 0);
526 EXPECT_EQ(m.size(), n);
527 ret = m.traverse([&N, this](int i)
528 {
529 ++N;
530 return i < n / 2;
531 });
533 EXPECT_EQ(N, n / 2 + 1);
534}
T & get_curr() const
Get the current item with bounds checking.
Definition array_it.H:245
void reset_last() noexcept
Reset the iterator to the last item.
Definition array_it.H:307
void reset() noexcept
Reset the iterator to the first item.
Definition array_it.H:297
void prev()
Move to the previous item with bounds checking.
Definition array_it.H:289
void next()
Advance to the next item with bounds checking.
Definition array_it.H:269
bool has_curr() const noexcept
Check if there is a current valid item.
Definition array_it.H:219
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Simple, scalable and fast dynamic array.
bool traverse(Operation &operation)
Traverse all the elements from index 0 to n - 1 and execute operation on each on them.
size_t size() const noexcept
Return the number of elements.
T & top() const
T & append(T &item)
T * get_ptr() const noexcept
Return the current base of array.
constexpr size_t capacity() const noexcept
The type of element of array.
bool is_empty() const noexcept
Return true is the array is empty.
T pop()
pop() the most recently pushed item
T & insert(T &item)
T & push(const T &item)
Push a copy of item at the beginning of sequence.
T remove_first()
Remove first item. Gap is closed.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
#define TEST(name)
#define N
Definition fib.C:294
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_dim_function > > dim(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4052
Singly linked list implementations with head-tail access.
bool is_power_of_two(size_t x)
Definition memarray.cc:47
TEST_F(Default_MemArray, growing_in_2_powers)
Definition memarray.cc:133
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool traverse(Node *root, Op op)
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Simple iterator on elements of array.
const size_t n
Definition memarray.cc:54
MemArray< int > m
Definition memarray.cc:55
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95
MemArray< int > m
Definition memarray.cc:60
Simple, scalable, contiguous dynamic array.
DynList< int > l