Aleph-w  1.9
General library for algorithms and data structures
tpl_arrayQueue.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 
28 # ifndef TPL_ARRAYQUEUE_H
29 # define TPL_ARRAYQUEUE_H
30 
31 # include <ahAssert.H>
32 # include <ahDefs.H>
33 # include <htlist.H>
34 # include <ah-dry.H>
35 # include <ah-args-ctor.H>
36 # include <tpl_dynDlist.H>
37 # include <tpl_memArray.H>
38 
39 using namespace Aleph;
40 
41 namespace Aleph {
42 
56  template <typename T>
57 class ArrayQueue : public MemArray<T>,
58  public LocateFunctions<ArrayQueue<T>, T>,
59  public FunctionalMethods<ArrayQueue<T>, T>,
60  public GenericKeys<ArrayQueue<T>, T>,
61  public EqualToMethod<ArrayQueue<T>>,
62  public StlAlephIterator<ArrayQueue<T>>
63 {
64 private:
65 
66  size_t front_index; // items are extracted from this point
67  size_t rear_index; // new item are inserted by this point
68 
69  void increase_index(size_t & i, const size_t inc = 1) const noexcept
70  {
71  i += inc;
72  i %= this->dim;
73  }
74 
75  T & rear_item(const size_t i = 0) const noexcept
76  {
77  return this->access((size_t) (rear_index - i - 1) % this->dim);
78  }
79 
80 public:
81 
83  void swap(ArrayQueue & q) noexcept
84  {
85  this->MemArray<T>::swap(q);
86  std::swap(front_index, q.front_index);
87  std::swap(rear_index, q.rear_index);
88  }
89 
95  ArrayQueue(const size_t sz = 8)
96  : MemArray<T>(sz), front_index(0), rear_index(0)
97  {
98  // empty
99  }
100 
103  : MemArray<T>(q), front_index(q.front_index), rear_index(q.rear_index)
104  {
105 
106  }
107 
110  : MemArray<T>(std::forward<ArrayQueue>(q)),
111  front_index(q.front_index), rear_index(q.rear_index)
112  {
113  // empty
114  }
115 
116  Special_Ctors(ArrayQueue, T);
117 
120  {
121  if (this == &q)
122  return *this;
123 
124  static_cast<MemArray<T>&>(*this) = q;
125 
126  front_index = q.front_index;
127  rear_index = q.rear_index;
128 
129  return *this;
130  }
131 
134  {
135  std::swap(front_index, q.front_index);
136  std::swap(rear_index, q.rear_index);
137  static_cast<MemArray<T>*>(this)->swap(q);
138  return *this;
139  }
140 
141 private:
142 
143  T & complete_put() noexcept
144  {
145  T & ret_val = this->access(rear_index);
146  increase_index(rear_index);
147  ++this->n;
148  return ret_val;
149  }
150 
151 public:
152 
159  T & put(const T & item)
160  {
161  if (this->expand(front_index))
162  {
163  front_index = 0;
164  rear_index = this->n;
165  }
166  this->access(rear_index) = item;
167  return complete_put();
168  }
169 
171  T & put(T && item)
172  {
173  if (this->expand(front_index))
174  {
175  front_index = 0;
176  rear_index = this->n;
177  }
178  this->access(rear_index) = std::forward<T>(item);
179  return complete_put();
180  }
181 
183  T & append(const T & item) { return put(item); }
184 
186  T & append(T && item) { return put(std::forward<T>(item)); }
187 
189  T & insert(const T & item) { return put(item); }
190 
192  T & insert(T && item) { return put(std::forward<T>(item)); }
193 
207  T & putn(size_t sz)
208  {
209  const size_t max_sz = 2*this->dim - this->n;
210  if (sz > max_sz)
211  throw std::overflow_error("Maximum putn size reached");
212 
213  const int avail_n = this->dim - this->n;
214  if (avail_n <= sz)
215  {
216  sz -= this->dim - this->n;
217  this->n = this->dim;
218  this->expand(front_index);
219  }
220 
221  increase_index(rear_index, sz);
222  this->n += sz;
223  return rear_item();
224  }
225 
231  T get()
232  {
233  if (this->n == 0)
234  throw std::underflow_error ("queue is empty");
235 
236  T ret_val = std::forward<T>(this->access(front_index));
237  this->n--;
238  increase_index(front_index);
239 
240  if (this->contract(front_index))
241  {
242  front_index = 0;
243  rear_index = this->n;
244  }
245 
246  return ret_val;
247  }
248 
255  T & getn(const size_t i)
256  {
257  if (i >= this->n)
258  throw std::underflow_error ("queue is empty");
259 
260  this->n -= i;
261  increase_index(front_index, i);
262 
263  if (this->contract(front_index))
264  {
265  front_index = 0;
266  rear_index = this->n;
267  }
268 
269  return this->access(front_index);
270  }
271 
278  T & front(const size_t i = 0) const
279  {
280  if (i >= this->n)
281  throw std::range_error ("index of front out of range");
282 
283  return this->access((front_index + i) % this->dim);
284  }
285 
292  T & rear(const size_t i = 0) const
293  {
294  if (i >= this->n)
295  throw std::range_error ("index of rear out of range");
296 
297  return rear_item(i);
298  }
299 
307  template <class Operation>
308  bool traverse(Operation & operation)
309  {
310  if (this->n == 0)
311  return true;
312 
313  for (size_t i = 0, idx = front_index; i < this->n; increase_index(idx), ++i)
314  if (not operation(this->access(idx)))
315  return false;
316  return true;
317  }
318 
320  template <class Operation>
321  bool traverse(Operation & operation) const
322  {
323  return const_cast<ArrayQueue*>(this)->traverse(operation);
324  }
325 
327  template <class Operation>
328  bool traverse(Operation && operation) const
329  {
330  return traverse<Operation>(operation);
331  }
332 
334  template <class Operation>
335  bool traverse(Operation && operation)
336  {
337  return traverse<Operation>(operation);
338  }
339 
346  struct Iterator : public MemArray<T>::Iterator
347  {
348  using Base = typename MemArray<T>::Iterator;
349  using Base::Base;
350  using Set_Type = ArrayQueue;
351 
352  Iterator(const ArrayQueue & q)
353  : Base(q.ptr, q.dim, q.n, q.front_index, (q.rear_index - 1) % q.dim) {}
354  };
355 };
356 
357 
370  template <typename T>
371 class FixedQueue : public LocateFunctions<FixedQueue<T>, T>,
372  public FunctionalMethods<FixedQueue<T>, T>,
373  public GenericKeys<FixedQueue<T>, T>,
374  public EqualToMethod<FixedQueue<T>>,
375  public StlAlephIterator<FixedQueue<T>>
376 {
377 private:
378 
379  size_t dim;
380  T * array;
381  size_t front_index; /* index of oldest inserted item */
382  size_t rear_index;
383  size_t mask;
384  size_t num_items;
385 
386  void increase_index(size_t & i, const size_t inc = 1) const noexcept
387  {
388  assert( ((i + inc)%dim) == ((i+ inc)&mask) );
389 
390  i += inc;
391  i &= mask;
392  }
393 
394  T & rear_item(const size_t i = 0) const noexcept
395  {
396  assert(static_cast<size_t>((rear_index - i - 1) & mask) ==
397  (rear_index - i - 1)%dim);
398 
399  return array[static_cast<size_t> ((rear_index - i - 1) & mask)];
400  }
401 
402 public:
403 
404  using Item_Type = T;
405 
406  void swap(FixedQueue & q) noexcept
407  {
408  std::swap(dim, q.dim);
409  std::swap(array, q.array);
410  std::swap(front_index, q.front_index);
411  std::swap(rear_index, q.rear_index);
412  std::swap(mask, q.mask);
413  std::swap(num_items, q.num_items);
414  }
415 
417  void empty() noexcept
418  {
419  front_index = rear_index = num_items = 0;
420  }
421 
429  FixedQueue(size_t d = 1024)
430  // Don't change the default value because you would risk of
431  // breaking the tests
432  : array(nullptr), front_index(0), rear_index(0), num_items(0)
433  {
434  size_t k = log2(d);
435  dim = is_power_of_2(d) ? d : 1 << ++k;
436  mask = dim - 1;
437  array = new T [dim];
438  }
439 
440  ~FixedQueue()
441  {
442  if (array != nullptr)
443  delete [] array;
444  }
445 
448  : dim(q.dim), array(new T [dim]), front_index(q.front_index),
449  rear_index(q.rear_index), mask(q.mask), num_items(q.num_items)
450  {
451  for (size_t i = front_index; i != rear_index; ++i)
452  array[i] = q.array[i];
453  }
454 
456  FixedQueue(FixedQueue && q) noexcept : FixedQueue()
457  {
458  swap(q);
459  }
460 
461  Special_Ctors(FixedQueue, T);
462 
465  {
466  if (this == &q)
467  return *this;
468 
469  if (array != nullptr)
470  delete [] array;
471 
472  new (this) FixedQueue(q);
473  return *this;
474  }
475 
478  {
479  swap(q);
480  return *this;
481  }
482 
488  T & put(const T& item) noexcept
489  {
490  assert(num_items < dim);
491  array[rear_index] = item;
492  T & ret_val = array[rear_index];
493  increase_index(rear_index);
494  num_items++;
495  return ret_val;
496  }
497 
499  T & put(T && item) noexcept
500  {
501  assert(num_items < dim);
502  array[rear_index] = std::forward<T>(item);
503  T & ret_val = array[rear_index];
504  increase_index(rear_index);
505  num_items++;
506  return ret_val;
507  }
508 
510  T & append(const T& item) noexcept { return put(item); }
511 
513  T & append(T && item) noexcept { return put(std::forward<T>(item)); }
514 
516  T & insert(const T& item) noexcept { return put(item); }
517 
519  T & insert(T && item) noexcept { return put(std::forward<T>(item)); }
520 
526  T & putn(const size_t n) noexcept
527  {
528  assert(num_items + n < dim);
529  increase_index(rear_index, n);
530  num_items += n;
531  return rear_item();
532  }
533 
538  T get() noexcept
539  {
540  assert(num_items > 0);
541  num_items--;
542  T ret_val = std::move(array[front_index]);
543  increase_index(front_index);
544  return ret_val;
545  }
546 
553  T & getn(const size_t n) noexcept
554  {
555  assert(num_items >= n);
556  num_items -= n;
557  increase_index(front_index, n);
558  return array[front_index];
559  }
560 
566  T & front(const size_t i = 0) const noexcept
567  {
568  assert(i < num_items);
569  return array[front_index + i];
570  }
571 
577  T & rear(const size_t i = 0) const noexcept
578  {
579  assert(i < num_items);
580  return rear_item(i);
581  }
582 
584  size_t size() const noexcept { return num_items; }
585 
587  bool is_empty() const noexcept { return num_items == 0; }
588 
590  size_t capacity() const noexcept { return dim; }
591 
599  template <class Operation>
600  bool traverse(Operation & operation) noexcept(noexcept(operation))
601  {
602  if (num_items == 0)
603  return true;
604  for (size_t i = 0, idx = front_index; i < num_items; increase_index(idx), ++i)
605  if (not operation(array[idx]))
606  return false;
607  return true;
608  }
609 
611  template <class Operation>
612  bool traverse(Operation & operation) const noexcept(noexcept(operation))
613  {
614  return const_cast<FixedQueue*>(this)->traverse(operation);
615  }
616 
618  template <class Operation>
619  bool traverse(Operation && operation = Operation())
620  const noexcept(noexcept(operation))
621  {
622  return traverse<Operation>(operation);
623  }
624 
626  template <class Operation>
627  bool traverse(Operation && operation = Operation())
628  noexcept(noexcept(operation))
629  {
630  return traverse<Operation>(operation);
631  }
632 
639  struct Iterator : public MemArray<T>::Iterator
640  {
641  using Base = typename MemArray<T>::Iterator;
642  using Base::Base;
643  using Set_Type = FixedQueue;
644 
645  Iterator(const FixedQueue & q) noexcept
646  : Base(q.array, q.dim, q.num_items, q.front_index,
647  (q.rear_index - 1) % q.dim) {}
648  };
649 };
650 
651 } // end namespace Aleph
652 
653 # endif /* TPL_ARRAYQUEUE_H */
654 
655 
656 
657 
658 
659 
Definition: tpl_memArray.H:73
T & access(const size_t i) const noexcept
Definition: tpl_memArray.H:565
Definition: htlist.H:450
Definition: htlist.H:1290
T & putn(size_t sz)
Definition: tpl_arrayQueue.H:207
Definition: tpl_arrayQueue.H:639
Definition: htlist.H:133
T & getn(const size_t n) noexcept
Definition: tpl_arrayQueue.H:553
T & put(T &&item)
Definition: tpl_arrayQueue.H:171
T & front(const size_t i=0) const noexcept
Definition: tpl_arrayQueue.H:566
T & insert(T &&item) noexcept
Definition: tpl_arrayQueue.H:519
bool traverse(Operation &&operation) const
Definition: tpl_arrayQueue.H:328
ArrayQueue & operator=(const ArrayQueue &q)
Copy assign.
Definition: tpl_arrayQueue.H:119
bool traverse(Operation &&operation=Operation()) noexcept(noexcept(operation))
Definition: tpl_arrayQueue.H:627
T & front(const size_t i=0) const
Definition: tpl_arrayQueue.H:278
Definition: tpl_arrayQueue.H:371
void empty() noexcept
empty the queue
Definition: tpl_arrayQueue.H:417
void swap(MemArray &a) noexcept
Swap in constant time this with a
Definition: tpl_memArray.H:238
Definition: tpl_arrayQueue.H:57
T & append(T &&item)
Definition: tpl_arrayQueue.H:186
bool traverse(Operation &operation) noexcept(noexcept(operation))
Definition: tpl_arrayQueue.H:600
bool contract(const size_t first=0)
Definition: tpl_memArray.H:151
T & put(const T &item)
Definition: tpl_arrayQueue.H:159
Definition: tpl_arrayQueue.H:346
T & append(T &&item) noexcept
Definition: tpl_arrayQueue.H:513
T & insert(const T &item)
Definition: tpl_arrayQueue.H:189
T & put(const T &item) noexcept
Definition: tpl_arrayQueue.H:488
T & getn(const size_t i)
Definition: tpl_arrayQueue.H:255
ArrayQueue(const ArrayQueue &q)
Copy constructor.
Definition: tpl_arrayQueue.H:102
T & insert(const T &item) noexcept
Definition: tpl_arrayQueue.H:516
bool traverse(Operation &operation) const noexcept(noexcept(operation))
Definition: tpl_arrayQueue.H:612
bool traverse(Operation &&operation)
Definition: tpl_arrayQueue.H:335
Definition: ah-comb.H:35
T & putn(const size_t n) noexcept
Definition: tpl_arrayQueue.H:526
Definition: tpl_memArray.H:635
ArrayQueue(ArrayQueue &&q)
Move constructor.
Definition: tpl_arrayQueue.H:109
void swap(ArrayQueue &q) noexcept
Swap this with q
Definition: tpl_arrayQueue.H:83
size_t size() const noexcept
Return the number of items.
Definition: tpl_arrayQueue.H:584
bool is_empty() const noexcept
Return true if the queue is empty.
Definition: tpl_arrayQueue.H:587
bool traverse(Operation &operation)
Definition: tpl_arrayQueue.H:308
FixedQueue(FixedQueue &&q) noexcept
Move constructor.
Definition: tpl_arrayQueue.H:456
bool traverse(Operation &operation) const
Definition: tpl_arrayQueue.H:321
FixedQueue(size_t d=1024)
Definition: tpl_arrayQueue.H:429
bool expand(const size_t first=0)
Definition: tpl_memArray.H:118
ArrayQueue(const size_t sz=8)
Definition: tpl_arrayQueue.H:95
FixedQueue(const FixedQueue &q)
Copy constructor.
Definition: tpl_arrayQueue.H:447
T & put(T &&item) noexcept
Definition: tpl_arrayQueue.H:499
size_t capacity() const noexcept
Return the queue capacity (maximum number of element to be stored)
Definition: tpl_arrayQueue.H:590
T & rear(const size_t i=0) const noexcept
Definition: tpl_arrayQueue.H:577
T & append(const T &item) noexcept
Definition: tpl_arrayQueue.H:510
T & append(const T &item)
Definition: tpl_arrayQueue.H:183
Definition: htlist.H:1323
bool traverse(Operation &&operation=Operation()) const noexcept(noexcept(operation))
Definition: tpl_arrayQueue.H:619
T & rear(const size_t i=0) const
Definition: tpl_arrayQueue.H:292
T & insert(T &&item)
Definition: tpl_arrayQueue.H:192

Leandro Rabindranath León