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
45#ifndef TPL_ARRAYQUEUE_H
46#define TPL_ARRAYQUEUE_H
47
48#include <ahAssert.H>
49#include <ahDefs.H>
50#include <htlist.H>
51#include <ah-dry.H>
52#include <ah-args-ctor.H>
53#include <tpl_dynDlist.H>
54#include <tpl_memArray.H>
55
56namespace Aleph {
57
71template <typename T>
72class ArrayQueue : public MemArray<T>,
73 public LocateFunctions<ArrayQueue<T>, T>,
74 public FunctionalMethods<ArrayQueue<T>, T>,
75 public GenericKeys<ArrayQueue<T>, T>,
76 public EqualToMethod<ArrayQueue<T>>,
77 public StlAlephIterator<ArrayQueue<T>>
78{
79private:
80 size_t front_index; // items are extracted from this point
81 size_t rear_index; // new item is inserted by this point
82
83 void increase_index(size_t &i, const size_t inc = 1) const noexcept
84 {
85 i += inc;
86 i %= this->dim;
87 }
88
89 T &rear_item(const size_t i = 0) const noexcept
90 {
91 const size_t offset = (rear_index + this->dim - (i + 1) % this->dim) % this->dim;
92 return this->access(offset);
93 }
94
96 {
97 front_index = 0;
98 rear_index = this->n;
99 }
100
101public:
103 void swap(ArrayQueue &q) noexcept
104 {
105 this->MemArray<T>::swap(q);
106 std::swap(front_index, q.front_index);
107 std::swap(rear_index, q.rear_index);
108 }
109
115 ArrayQueue(const size_t sz = 8) : MemArray<T>(sz), front_index(0), rear_index(0)
116 {
117 // empty
118 }
119
124
127 : MemArray<T>(std::move(q)), front_index(q.front_index), rear_index(q.rear_index)
128 {
129 q.front_index = 0;
130 q.rear_index = 0;
131 }
132
134
137 {
138 if (this == &q)
139 return *this;
140
141 static_cast<MemArray<T> &>(*this) = q;
142
145
146 return *this;
147 }
148
151 {
152 std::swap(front_index, q.front_index);
153 std::swap(rear_index, q.rear_index);
154 static_cast<MemArray<T> *>(this)->swap(q);
155 return *this;
156 }
157
158private:
160 {
161 T &ret_val = this->access(rear_index);
163 ++this->n;
164 return ret_val;
165 }
166
167public:
174 T &put(const T &item)
175 {
176 if (this->expand(front_index))
178 this->access(rear_index) = item;
179 return complete_put();
180 }
181
183 T &put(T &&item)
184 {
185 if (this->expand(front_index))
187 this->access(rear_index) = std::forward<T>(item);
188 return complete_put();
189 }
190
192 T &append(const T &item)
193 {
194 return put(item);
195 }
196
198 T &append(T &&item)
199 {
200 return put(std::forward<T>(item));
201 }
202
204 T &insert(const T &item)
205 {
206 return put(item);
207 }
208
210 T &insert(T &&item)
211 {
212 return put(std::forward<T>(item));
213 }
214
228 T &putn(const size_t sz)
229 {
230 const size_t max_sz = 2 * this->dim - this->n;
231 ah_overflow_error_if(sz > max_sz) << "Maximum putn size reached";
232
233 size_t remaining = sz;
234 while (remaining > 0)
235 {
236 const size_t available = this->dim - this->n;
237 if (available == 0)
238 {
239 if (this->expand(front_index))
241 continue;
242 }
243
244 const size_t delta = remaining < available ? remaining : available;
246 this->n += delta;
247 remaining -= delta;
248 }
249
250 return rear_item();
251 }
252
259 {
260 ah_underflow_error_if(this->n == 0) << "queue is empty";
261
262 T ret_val = std::move(this->access(front_index));
263 --this->n;
264 increase_index(front_index);
265
266 if (this->contract(front_index))
268
269 return ret_val;
270 }
271
278 T &getn(const size_t i)
279 {
280 ah_underflow_error_if(i >= this->n) << "queue is empty";
281
282 this->n -= i;
284
285 if (this->contract(front_index))
287
288 return this->access(front_index);
289 }
290
297 T &front(const size_t i = 0) const
298 {
299 ah_range_error_if(i >= this->n) << "index of front out of range";
300
301 return this->access((front_index + i) % this->dim);
302 }
303
310 T &rear(const size_t i = 0) const
311 {
312 ah_range_error_if(i >= this->n) << "index of rear out of range";
313
314 return rear_item(i);
315 }
316
324 template <class Operation>
326 {
327 if (this->n == 0)
328 return true;
329
330 for (size_t i = 0, idx = front_index; i < this->n; increase_index(idx), ++i)
331 if (not operation(this->access(idx)))
332 return false;
333 return true;
334 }
335
337 template <class Operation>
339 {
340 return const_cast<ArrayQueue *>(this)->traverse(operation);
341 }
342
344 template <class Operation>
346 {
348 }
349
351 template <class Operation>
353 {
355 }
356
363 struct Iterator : public MemArray<T>::Iterator
364 {
365 using Base = typename MemArray<T>::Iterator;
366 using Base::Base;
368
370 : Base(q.ptr, q.dim, q.n, q.front_index, (q.rear_index - 1) % q.dim)
371 {}
372 };
373};
374
387template <typename T>
388class FixedQueue : public LocateFunctions<FixedQueue<T>, T>,
389 public FunctionalMethods<FixedQueue<T>, T>,
390 public GenericKeys<FixedQueue<T>, T>,
391 public EqualToMethod<FixedQueue<T>>,
392 public StlAlephIterator<FixedQueue<T>>
393{
394 size_t dim;
396 size_t front_index; /* index of oldest inserted item */
398 size_t mask;
399 size_t num_items;
400
401 void increase_index(size_t &i, const size_t inc = 1) const noexcept
402 {
403 assert(((i + inc) % dim) == ((i + inc) & mask));
404
405 i += inc;
406 i &= mask;
407 }
408
409 T &rear_item(const size_t i = 0) const noexcept
410 {
411 assert(static_cast<size_t>((rear_index - i - 1) & mask) == (rear_index - i - 1) % dim);
412
413 return array[static_cast<size_t>((rear_index - i - 1) & mask)];
414 }
415
416public:
417 using Item_Type = T;
418
419 void swap(FixedQueue &q) noexcept
420 {
421 std::swap(dim, q.dim);
422 std::swap(array, q.array);
423 std::swap(front_index, q.front_index);
424 std::swap(rear_index, q.rear_index);
425 std::swap(mask, q.mask);
426 std::swap(num_items, q.num_items);
427 }
428
431 {
433 }
434
441 {
442 empty();
443 }
444
452 FixedQueue(size_t d = 1024)
453 // Don't change the default value because you would risk of
454 // breaking the tests
455 : dim(0), array(nullptr), front_index(0), rear_index(0), mask(0), num_items(0)
456 {
457 size_t k = log2(d);
458 dim = is_power_of_2(d) ? d : 1 << ++k;
459 mask = dim - 1;
460 array = new T[dim];
461 }
462
464 {
465 if (array != nullptr)
466 delete[] array;
467 }
468
473 {
474 for (size_t i = front_index; i != rear_index; ++i)
475 array[i] = q.array[i];
476 }
477
480 {
481 swap(q);
482 }
483
485
488 {
489 if (this == &q)
490 return *this;
491
492 FixedQueue tmp(q);
493 swap(tmp);
494 return *this;
495 }
496
499 {
500 swap(q);
501 return *this;
502 }
503
509 T &put(const T &item) noexcept
510 {
512 array[rear_index] = item;
515 num_items++;
516 return ret_val;
517 }
518
520 T &put(T &&item) noexcept
521 {
523 array[rear_index] = std::forward<T>(item);
526 num_items++;
527 return ret_val;
528 }
529
531 T &append(const T &item) noexcept
532 {
533 return put(item);
534 }
535
537 T &append(T &&item) noexcept
538 {
539 return put(std::forward<T>(item));
540 }
541
543 T &insert(const T &item) noexcept
544 {
545 return put(item);
546 }
547
549 T &insert(T &&item) noexcept
550 {
551 return put(std::forward<T>(item));
552 }
553
559 T &putn(const size_t n) noexcept
560 {
561 assert(num_items + n < dim);
563 num_items += n;
564 return rear_item();
565 }
566
572 {
573 assert(num_items > 0);
574 num_items--;
575 T ret_val = std::move(array[front_index]);
577 return ret_val;
578 }
579
586 T &getn(const size_t n) noexcept
587 {
588 assert(num_items >= n);
589 num_items -= n;
591 return array[front_index];
592 }
593
599 T &front(const size_t i = 0) const noexcept
600 {
601 assert(i < num_items);
602 return array[front_index + i];
603 }
604
610 T &rear(const size_t i = 0) const noexcept
611 {
612 assert(i < num_items);
613 return rear_item(i);
614 }
615
617 [[nodiscard]] constexpr size_t size() const noexcept
618 {
619 return num_items;
620 }
621
623 [[nodiscard]] constexpr bool is_empty() const noexcept
624 {
625 return num_items == 0;
626 }
627
629 [[nodiscard]] constexpr size_t capacity() const noexcept
630 {
631 return dim;
632 }
633
641 template <class Operation>
643 {
644 if (num_items == 0)
645 return true;
646 for (size_t i = 0, idx = front_index; i < num_items; increase_index(idx), ++i)
647 if (not operation(array[idx]))
648 return false;
649 return true;
650 }
651
653 template <class Operation>
655 {
656 return const_cast<FixedQueue *>(this)->traverse(operation);
657 }
658
660 template <class Operation>
662 {
664 }
665
667 template <class Operation>
672
679 struct Iterator : public MemArray<T>::Iterator
680 {
681 using Base = typename MemArray<T>::Iterator;
682 using Base::Base;
684
686 : Base(q.array, q.dim, q.num_items, q.front_index, (q.rear_index - 1) % q.dim)
687 {}
688 };
689};
690
691} // end namespace Aleph
692
693#endif /* TPL_ARRAYQUEUE_H */
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 & 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.
ArrayQueue & operator=(ArrayQueue &&q) noexcept
Move assign.
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 & putn(const size_t sz)
Put in constant time sz empty entries to the stack.
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 & operator=(FixedQueue &&q) noexcept
Move assign.
FixedQueue(const FixedQueue &q)
Copy constructor.
void clear() noexcept
Empties the container.
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:1826
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:642
Common sequential searching methods on containers.
Definition ah-dry.H:196
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
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
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:1714
static int * k
Dynamic doubly linked list implementation.
Simple, scalable, contiguous dynamic array.