Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_arrayQueue.H
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
46#ifndef TPL_ARRAYQUEUE_H
47#define TPL_ARRAYQUEUE_H
48
49#include <ahAssert.H>
50#include <ahDefs.H>
51#include <htlist.H>
52#include <ah-dry.H>
53#include <ah-args-ctor.H>
54#include <tpl_dynDlist.H>
55#include <tpl_memArray.H>
56
57namespace Aleph {
58
72 template <typename T>
73class ArrayQueue : public MemArray<T>,
74 public LocateFunctions<ArrayQueue<T>, T>,
75 public FunctionalMethods<ArrayQueue<T>, T>,
76 public GenericKeys<ArrayQueue<T>, T>,
77 public EqualToMethod<ArrayQueue<T>>,
78 public StlAlephIterator<ArrayQueue<T>>
79{
80private:
81
82 size_t front_index; // items are extracted from this point
83 size_t rear_index; // new item is inserted by this point
84
85 void increase_index(size_t & i, const size_t inc = 1) const noexcept
86 {
87 i += inc;
88 i %= this->dim;
89 }
90
91 T & rear_item(const size_t i = 0) const noexcept
92 {
93 const size_t offset = (rear_index + this->dim - (i + 1) % this->dim) % this->dim;
94 return this->access(offset);
95 }
96
98 {
99 front_index = 0;
100 rear_index = this->n;
101 }
102
103public:
104
106 void swap(ArrayQueue & q) noexcept
107 {
108 this->MemArray<T>::swap(q);
109 std::swap(front_index, q.front_index);
110 std::swap(rear_index, q.rear_index);
111 }
112
118 ArrayQueue(const size_t sz = 8)
119 : MemArray<T>(sz), front_index(0), rear_index(0)
120 {
121 // empty
122 }
123
127 {
128
129 }
130
133 : MemArray<T>(std::move(q)),
134 front_index(q.front_index), rear_index(q.rear_index)
135 {
136 q.front_index = 0;
137 q.rear_index = 0;
138 }
139
141
144 {
145 if (this == &q)
146 return *this;
147
148 static_cast<MemArray<T>&>(*this) = q;
149
152
153 return *this;
154 }
155
158 {
159 std::swap(front_index, q.front_index);
160 std::swap(rear_index, q.rear_index);
161 static_cast<MemArray<T>*>(this)->swap(q);
162 return *this;
163 }
164
165private:
166
168 {
169 T & ret_val = this->access(rear_index);
171 ++this->n;
172 return ret_val;
173 }
174
175public:
176
183 T & put(const T & item)
184 {
185 if (this->expand(front_index))
187 this->access(rear_index) = item;
188 return complete_put();
189 }
190
192 T & put(T && item)
193 {
194 if (this->expand(front_index))
196 this->access(rear_index) = std::forward<T>(item);
197 return complete_put();
198 }
199
201 T & append(const T & item) { return put(item); }
202
204 T & append(T && item) { return put(std::forward<T>(item)); }
205
207 T & insert(const T & item) { return put(item); }
208
210 T & insert(T && item) { return put(std::forward<T>(item)); }
211
225 T & putn(size_t sz)
226 {
227 const size_t max_sz = 2*this->dim - this->n;
228 ah_overflow_error_if(sz > max_sz) << "Maximum putn size reached";
229
230 size_t remaining = sz;
231 while (remaining > 0)
232 {
233 const size_t available = this->dim - this->n;
234 if (available == 0)
235 {
236 if (this->expand(front_index))
238 continue;
239 }
240
241 const size_t delta = remaining < available ? remaining : available;
243 this->n += delta;
244 remaining -= delta;
245 }
246
247 return rear_item();
248 }
249
256 {
257 ah_underflow_error_if(this->n == 0) << "queue is empty";
258
259 T ret_val = std::move(this->access(front_index));
260 this->n--;
261 increase_index(front_index);
262
263 if (this->contract(front_index))
265
266 return ret_val;
267 }
268
275 T & getn(const size_t i)
276 {
277 ah_underflow_error_if(i >= this->n) << "queue is empty";
278
279 this->n -= i;
281
282 if (this->contract(front_index))
284
285 return this->access(front_index);
286 }
287
294 T & front(const size_t i = 0) const
295 {
296 ah_range_error_if(i >= this->n) << "index of front out of range";
297
298 return this->access((front_index + i) % this->dim);
299 }
300
307 T & rear(const size_t i = 0) const
308 {
309 ah_range_error_if(i >= this->n) << "index of rear out of range";
310
311 return rear_item(i);
312 }
313
321 template <class Operation>
323 {
324 if (this->n == 0)
325 return true;
326
327 for (size_t i = 0, idx = front_index; i < this->n; increase_index(idx), ++i)
328 if (not operation(this->access(idx)))
329 return false;
330 return true;
331 }
332
334 template <class Operation>
336 {
337 return const_cast<ArrayQueue*>(this)->traverse(operation);
338 }
339
341 template <class Operation>
343 {
345 }
346
348 template <class Operation>
350 {
352 }
353
360 struct Iterator : public MemArray<T>::Iterator
361 {
362 using Base = typename MemArray<T>::Iterator;
363 using Base::Base;
365
367 : Base(q.ptr, q.dim, q.n, q.front_index, (q.rear_index - 1) % q.dim) {}
368 };
369};
370
371
384 template <typename T>
385class FixedQueue : public LocateFunctions<FixedQueue<T>, T>,
386 public FunctionalMethods<FixedQueue<T>, T>,
387 public GenericKeys<FixedQueue<T>, T>,
388 public EqualToMethod<FixedQueue<T>>,
389 public StlAlephIterator<FixedQueue<T>>
390{
391private:
392
393 size_t dim;
395 size_t front_index; /* index of oldest inserted item */
397 size_t mask;
398 size_t num_items;
399
400 void increase_index(size_t & i, const size_t inc = 1) const noexcept
401 {
402 assert( ((i + inc)%dim) == ((i+ inc)&mask) );
403
404 i += inc;
405 i &= mask;
406 }
407
408 T & rear_item(const size_t i = 0) const noexcept
409 {
410 assert(static_cast<size_t>((rear_index - i - 1) & mask) ==
411 (rear_index - i - 1)%dim);
412
413 return array[static_cast<size_t> ((rear_index - i - 1) & mask)];
414 }
415
416public:
417
418 using Item_Type = T;
419
420 void swap(FixedQueue & q) noexcept
421 {
422 std::swap(dim, q.dim);
423 std::swap(array, q.array);
424 std::swap(front_index, q.front_index);
425 std::swap(rear_index, q.rear_index);
426 std::swap(mask, q.mask);
427 std::swap(num_items, q.num_items);
428 }
429
432 {
434 }
435
443 FixedQueue(size_t d = 1024)
444 // Don't change the default value because you would risk of
445 // breaking the tests
446 : dim(0), array(nullptr), front_index(0), rear_index(0), mask(0), num_items(0)
447 {
448 size_t k = log2(d);
449 dim = is_power_of_2(d) ? d : 1 << ++k;
450 mask = dim - 1;
451 array = new T [dim];
452 }
453
455 {
456 if (array != nullptr)
457 delete [] array;
458 }
459
464 {
465 for (size_t i = front_index; i != rear_index; ++i)
466 array[i] = q.array[i];
467 }
468
471 {
472 swap(q);
473 }
474
476
479 {
480 if (this == &q)
481 return *this;
482
483 FixedQueue tmp(q);
484 swap(tmp);
485 return *this;
486 }
487
490 {
491 swap(q);
492 return *this;
493 }
494
500 T & put(const T& item) noexcept
501 {
503 array[rear_index] = item;
506 num_items++;
507 return ret_val;
508 }
509
511 T & put(T && item) noexcept
512 {
514 array[rear_index] = std::forward<T>(item);
517 num_items++;
518 return ret_val;
519 }
520
522 T & append(const T& item) noexcept { return put(item); }
523
525 T & append(T && item) noexcept { return put(std::forward<T>(item)); }
526
528 T & insert(const T& item) noexcept { return put(item); }
529
531 T & insert(T && item) noexcept { return put(std::forward<T>(item)); }
532
538 T & putn(const size_t n) noexcept
539 {
540 assert(num_items + n < dim);
542 num_items += n;
543 return rear_item();
544 }
545
551 {
552 assert(num_items > 0);
553 num_items--;
554 T ret_val = std::move(array[front_index]);
556 return ret_val;
557 }
558
565 T & getn(const size_t n) noexcept
566 {
567 assert(num_items >= n);
568 num_items -= n;
570 return array[front_index];
571 }
572
578 T & front(const size_t i = 0) const noexcept
579 {
580 assert(i < num_items);
581 return array[front_index + i];
582 }
583
589 T & rear(const size_t i = 0) const noexcept
590 {
591 assert(i < num_items);
592 return rear_item(i);
593 }
594
596 [[nodiscard]] constexpr size_t size() const noexcept { return num_items; }
597
599 [[nodiscard]] constexpr bool is_empty() const noexcept { return num_items == 0; }
600
602 [[nodiscard]] constexpr size_t capacity() const noexcept { return dim; }
603
611 template <class Operation>
613 {
614 if (num_items == 0)
615 return true;
616 for (size_t i = 0, idx = front_index; i < num_items; increase_index(idx), ++i)
617 if (not operation(array[idx]))
618 return false;
619 return true;
620 }
621
623 template <class Operation>
625 {
626 return const_cast<FixedQueue*>(this)->traverse(operation);
627 }
628
630 template <class Operation>
632 {
634 }
635
637 template <class Operation>
639 {
641 }
642
649 struct Iterator : public MemArray<T>::Iterator
650 {
651 using Base = typename MemArray<T>::Iterator;
652 using Base::Base;
654
656 : Base(q.array, q.dim, q.num_items, q.front_index,
657 (q.rear_index - 1) % q.dim) {}
658 };
659};
660
661} // end namespace Aleph
662
663# endif /* TPL_ARRAYQUEUE_H */
664
665
666
667
Variadic constructor macros for containers.
Container traversal and functional operation mixins.
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:368
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_range_error_if(C)
Throws std::range_error if condition holds.
Definition ah-errors.H:207
Debug assertion and warning utilities.
Core definitions, constants, and utility macros for Aleph-w.
#define Special_Ctors(Set_Type, Type)
Generates special constructors for containers.
Definition ahDry.H:113
Queue implemented with a single dynamic array.
T & insert(T &&item)
ArrayQueue(const size_t sz=8)
Construct a queue with capacity sz
bool traverse(Operation &&operation) const
T & putn(size_t sz)
Put in constant time sz empty entries to the stack.
T & insert(const T &item)
bool traverse(Operation &operation) const
T & complete_put() noexcept
T & front(const size_t i=0) const
Return the i-th oldest item of the queue.
void increase_index(size_t &i, const size_t inc=1) const noexcept
void recenter_indices() noexcept
bool traverse(Operation &operation)
Traverse all the elements from the youngest to the oldest and execute operation on each on them.
T & getn(const size_t i)
Remove the i oldest items of the queue.
ArrayQueue(const ArrayQueue &q)
Copy constructor.
bool traverse(Operation &&operation)
T & append(const T &item)
ArrayQueue & operator=(const ArrayQueue &q)
Copy assign.
T & put(const T &item)
Copy and put an item in the queue.
T & rear(const size_t i=0) const
Return the i-th youngest item of the queue.
T & put(T &&item)
T get()
Remove the oldest item of the queue and return a copy.
ArrayQueue(ArrayQueue &&q) noexcept
Move constructor.
void swap(ArrayQueue &q) noexcept
Swap this with q
T & rear_item(const size_t i=0) const noexcept
T & append(T &&item)
Very simple queue implemented with a contiguous array.
T & insert(const T &item) noexcept
T & append(const T &item) noexcept
T & put(const T &item) noexcept
Put an item into the queue by copy.
bool traverse(Operation &&operation=Operation())
FixedQueue & operator=(const FixedQueue &q)
Copy assign.
T & insert(T &&item) noexcept
bool traverse(Operation &operation)
Traverse all the elements from the youngest to the oldest and execute operation on each on them.
constexpr bool is_empty() const noexcept
Return true if the queue is empty.
FixedQueue(const FixedQueue &q)
Copy constructor.
T get() noexcept
Remove the oldest item of the queue.
T & putn(const size_t n) noexcept
Put n cells to the queue in constant time.
void swap(FixedQueue &q) noexcept
FixedQueue(size_t d=1024)
Construct a queue of capacity the immediately two power of d
bool traverse(Operation &&operation=Operation()) const
T & append(T &&item) noexcept
void empty() noexcept
empty the queue
void increase_index(size_t &i, const size_t inc=1) const noexcept
T & getn(const size_t n) noexcept
Remove in constant time the n oldest items of the queue.
constexpr size_t size() const noexcept
Return the number of items.
T & rear_item(const size_t i=0) const noexcept
FixedQueue(FixedQueue &&q) noexcept
Move constructor.
T & put(T &&item) noexcept
T & rear(const size_t i=0) const noexcept
Return the i-th youngest item.
constexpr size_t capacity() const noexcept
Return the queue capacity (maximum number of element to be stored)
bool traverse(Operation &operation) const
T & front(const size_t i=0) const noexcept
Return the i-th oldest item.
Simple, scalable and fast dynamic array.
bool contract(const size_t first=0)
Test if n is lesser than contract_threshold and eventually contract the array half long and copies it...
T & access(const size_t i) const noexcept
Return a modifiable reference to the ith element.
bool expand(const size_t first=0)
Test is array is full and if affrimative, then expand the array twice as long and copy the content by...
void swap(MemArray &a) noexcept
Swap in constant time this with a
Equality test for containers.
Definition ah-dry.H:1534
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:548
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
Definition ah-dry.H:904
Common sequential searching methods on containers.
Definition ah-dry.H:164
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_log2_function > > log2(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4064
Singly linked list implementations with head-tail access.
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
bool is_power_of_2(unsigned long x)
Taken from http://stackoverflow.com/questions/3638431/determine-if-an-int-is-a-power-of-2-or-not-in-a...
Definition ahUtils.H:224
Simple iterator on elements of a queue.
typename MemArray< T >::Iterator Base
Iterator(const ArrayQueue &q)
Simple iterator on elements of a queue.
Iterator(const FixedQueue &q) noexcept
typename MemArray< T >::Iterator Base
Simple iterator on elements of array.
Generic list of items stored in a container.
Definition ah-dry.H:1501
Dynamic doubly linked list implementation.
Simple, scalable, contiguous dynamic array.