Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_memArray.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
91#ifndef TPL_MEMARRAY_H
92#define TPL_MEMARRAY_H
93
94#include <utility>
95#include <cstdlib>
96#include <cmath>
97#include <stdexcept>
98
99#include <ah-errors.H>
100#include <ahUtils.H>
101#include <ahDry.H>
102#include <ahIterator.H>
103#include <array_it.H>
104#include <array_utils.H>
105
106namespace Aleph {
133template <typename T>
135{
136public:
137 static constexpr size_t Min_Dim = 4;
138
139protected:
140 T *ptr = nullptr;
141 size_t dim = Min_Dim;
142 size_t n = 0;
143
144public:
145 mutable size_t contract_threshold;
146
149 {
150 return ptr;
151 }
152
154 const size_t &get_dim() const noexcept
155 {
156 return dim;
157 }
158
159protected:
161 void allocate()
162 {
164 ptr = new T[dim];
166 }
167
179 bool expand(const size_t first = 0)
180 {
181 assert(ptr);
183 if (n < dim)
184 return false;
185
186 const size_t newsz = dim << 1; // 2*dim
187 const size_t mask = dim - 1;
188 T *new_ptr = new T[newsz];
189 for (size_t i = 0; i < dim; ++i)
190 {
191 assert(((i + first) & mask) == ((i + first) % dim));
192 std::swap(ptr[(i + first) & mask], new_ptr[i]);
193 }
194 delete[] ptr;
195 ptr = new_ptr;
196 dim = newsz;
198
199 return true;
200 }
201
212 bool contract(const size_t first = 0)
213 {
214 assert(ptr);
215 if (n > contract_threshold)
216 return false;
217
218 const size_t newsz = dim >> 1; // dim/2
219
220 if (newsz <= Min_Dim)
221 return false;
222
223 T *new_ptr = new T[newsz];
224
225 const size_t mask = dim - 1;
226 for (int i = 0; i < newsz; ++i)
227 {
228 assert(((first + i) & mask) == ((first + i) % dim));
229 std::swap(ptr[(first + i) & mask], new_ptr[i]);
230 }
231
232 delete[] ptr;
233 ptr = new_ptr;
234 dim = newsz;
236
237 return true;
238 }
239
245 void init_dim(size_t d) noexcept
246 {
247 if (d == 0)
248 d = Min_Dim;
249
250 size_t k = log2(d);
251 dim = is_power_of_2(d) ? d : 1 << ++k;
252
253 assert(dim >= d);
254 assert(dim == 1 << k);
255 }
256
257public:
258 using Item_Type = T;
259
261 [[nodiscard]] constexpr size_t capacity() const noexcept
262 {
263 return dim;
264 }
265
268 {
269 return n;
270 }
271
274 {
275 return n == 0;
276 }
277
284 MemArray(size_t _dim = Min_Dim) : ptr(nullptr), n(0)
285 {
286 static_assert(std::is_move_constructible_v<T>, "T must be move constructible");
287 static_assert(std::is_move_assignable_v<T>, "T must be move assignable");
288 init_dim(_dim);
289 allocate();
290 }
291
293 {
294 if (ptr != nullptr)
295 {
296 delete[] ptr;
297 ptr = nullptr;
298 }
299 }
300
302 void swap(MemArray &a) noexcept
303 {
304 std::swap(ptr, a.ptr);
305 std::swap(dim, a.dim);
306 std::swap(n, a.n);
307 std::swap(contract_threshold, a.contract_threshold);
308 }
309
312 requires(std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)
313 : ptr(nullptr), dim(a.dim), n(a.n)
314 {
315 allocate();
316 for (int i = 0; i < n; ++i)
317 ptr[i] = a.ptr[i];
318 }
319
322 {
323 assert(a.ptr);
324 swap(a);
325 }
326
329 requires(std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>)
330 {
331 if (this == &a)
332 return *this;
333
334 assert(a.ptr);
335
336 T *newptr = new T[a.dim]; // allocate a new array
337 for (size_t i = 0; i < a.n; ++i) // copy items to a new array
338 newptr[i] = a.ptr[i];
339
340 if (ptr != nullptr)
341 delete[] ptr;
342 ptr = newptr;
343 dim = a.dim;
344 n = a.n;
346
347 return *this;
348 }
349
352 {
353 swap(a);
354 return *this;
355 }
356
364 {
365 n = 0;
366 }
367
374 {
375 empty();
376 }
377
380 {
381 n = 0;
382 if (dim <= Min_Dim)
383 return;
384
385 assert(ptr);
386 delete[] ptr;
387 ptr = nullptr;
388 dim = Min_Dim;
389 allocate();
390 }
391
394 T &put(const T &item)
395 requires std::is_copy_assignable_v<T>
396 {
397 assert(ptr);
398 expand();
399
400 ptr[n] = item;
401 T &ret = ptr[n++];
402 return ret;
403 }
404
407 T &put(T &&item)
408 {
409 assert(ptr);
410 expand();
411
412 ptr[n] = std::forward<T>(item);
413 T &ret = ptr[n++];
414 return ret;
415 }
416
417private:
418 void open_gap(size_t pos = 0, size_t num_entries = 1)
419 {
422 }
423
424 void close_gap(size_t pos, size_t num_entries = 1)
425 {
428 }
429
430public:
433 T &push(const T &item)
434 requires std::is_copy_assignable_v<T>
435 {
436 assert(ptr);
437 open_gap();
438
439 ptr[0] = item;
440 T &ret = ptr[0];
441 return ret;
442 }
443
446 T &push(T &&item)
447 {
448 assert(ptr);
449 open_gap(0, 1);
450
451 ptr[0] = std::forward<T>(item);
452 T &ret = ptr[0];
453 return ret;
454 }
455
456 T &top() const
457 {
458 ah_underflow_error_if(n == 0) << "top(): MemArray is empty";
459
460 return ptr[0];
461 }
462
465 {
466 ah_underflow_error_if(n == 0) << "remove_first(): MemArray is empty";
467 assert(ptr);
468 T ret = std::move(ptr[0]);
469 this->close_gap(0, 1);
470 return ret;
471 }
472
475 {
476 return remove_first();
477 }
478
480 T &append(const T &item)
481 requires std::is_copy_assignable_v<T>
482 {
483 assert(ptr);
484 return put(item);
485 }
486
488 T &append(T &&item)
489 {
490 assert(ptr);
491 return put(std::forward<T>(item));
492 }
493
495 T &insert(const T &item)
496 requires std::is_copy_assignable_v<T>
497 {
498 assert(ptr);
499 return push(item);
500 }
501
503 T &insert(T &&item)
504 {
505 assert(ptr);
506 return push(std::forward<T>(item));
507 }
508
519 void putn(const size_t more)
520 {
521 assert(ptr);
522 const size_t new_n = n + more;
523 if (new_n <= dim)
524 {
525 n = new_n;
526 return;
527 }
528
529 size_t new_dim = dim;
530 while (new_dim < new_n)
531 new_dim <<= 1; // dim = 2*dim
532
533 T *new_ptr = new T[new_dim];
534 for (size_t i = 0; i < n; ++i)
535 std::swap(ptr[i], new_ptr[i]);
536
537 delete[] ptr;
538 ptr = new_ptr;
539 dim = new_dim;
540 n = new_n;
542 }
543
545 requires std::is_copy_assignable_v<T>
546 {
547 const size_t old_n = n;
548 const size_t num_entries = a.size();
550 for (size_t i = 0; i < num_entries; ++i)
551 ptr[old_n + i] = a.ptr[i];
552
553 return *this;
554 }
555
561 void reserve(const size_t cap)
562 {
563 assert(ptr);
564 if (cap < dim)
565 return;
566
567 size_t k = log2(cap);
568 const size_t new_dim = is_power_of_2(cap) ? cap : 1 << ++k;
569
570 T *new_ptr = new T[new_dim];
571 for (size_t i = 0; i < n; ++i)
572 std::swap(ptr[i], new_ptr[i]);
573
574 delete[] ptr;
575 ptr = new_ptr;
576 dim = new_dim;
578 }
579
582 T get(const size_t i = 1)
583 {
584 assert(ptr);
585 const long idx = n - i;
586 ah_underflow_error_if(idx < 0) << "MemArray::get(): deleted more entries than capacity";
587
588 n = idx;
589 T ret = std::move(ptr[n]);
590
591 contract();
592
593 return ret;
594 }
595
596 T get_ne(const size_t i = 1) noexcept
597 {
598 assert(ptr);
599 const long idx = n - i;
600 n = idx;
601 T ret = std::move(ptr[n]);
602
603 contract();
604
605 return ret;
606 }
607
610 {
611 return get();
612 }
613
615 T &last() const
616 {
617 ah_underflow_error_if(n == 0) << "MemArray::last(): empty array";
618 return ptr[n - 1];
619 }
620
622 T &first() const
623 {
624 ah_underflow_error_if(n == 0) << "MemArray::first(): empty array";
625 return ptr[0];
626 }
627
629 T &get_first() const
630 {
631 return first();
632 }
633
635 T &get_last() const
636 {
637 return last();
638 }
639
642 {
643 for (size_t i = 0, j = n - 1; i < j; ++i, --j)
644 std::swap(ptr[i], ptr[j]);
645 return *this;
646 }
647
650 T &access(const size_t i) const noexcept
651 {
652 assert(ptr);
653 return ptr[i];
654 }
655
658 T &operator[](const size_t i) const
659 {
660 assert(ptr);
661 ah_out_of_range_error_if(i >= n) << "access out of range";
662
663 return ptr[i];
664 }
665
667 T &operator()(const size_t i) const noexcept
668 {
669 assert(ptr);
670 assert(i < dim);
671 return ptr[i];
672 }
673
681 template <class Operation>
683 {
684 assert(ptr);
685 for (int i = 0; i < n; i++)
686 if (not operation(ptr[i]))
687 return false;
688
689 return true;
690 }
691
693 template <class Operation>
695 {
696 return const_cast<MemArray *>(this)->traverse(operation);
697 }
698
700 template <class Operation>
702 {
704 }
705
707 template <class Operation>
709 {
711 }
712
714 {
715 return ptr;
716 }
717
722 struct Iterator : public Array_Iterator<T>
723 {
725 using Base::Base;
726
729 : Array_Iterator<T>(no_exception_ctor, a.ptr, a.dim, a.n)
730 {
731 assert(a.ptr != nullptr);
732 }
733 };
734};
735} // end namespace Aleph
736
737#endif // TPL_MEMARRAY_H
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:368
@ no_exception_ctor
Definition ahDefs.H:72
DRY (Don't Repeat Yourself) utilities and macros.
Iterator traits and STL-compatible iterator wrappers.
General utility functions and helpers.
Iterator wrapper for C++ raw arrays and circular buffers.
Utility functions for array manipulation.
Iterator wrapper for C++ raw arrays.
Definition array_it.H:77
Simple, scalable and fast dynamic array.
T & operator()(const size_t i) const noexcept
void reserve(const size_t cap)
Reserves cap cells into the array.
void open_gap(size_t pos=0, size_t num_entries=1)
T & push(T &&item)
Push a copy of item at the beginning of sequence.
bool traverse(Operation &operation)
Traverse all the elements from index 0 to n - 1 and execute operation on each on them.
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...
size_t size() const noexcept
Return the number of elements.
void putn(const size_t more)
Reserve more additional logical slots in the array.
T get_ne(const size_t i=1) noexcept
void clear() noexcept
Alias for empty().
T & first() const
Return a modifiable reference to the first element.
T & top() const
T & access(const size_t i) const noexcept
Return a modifiable reference to the ith element.
T & append(const T &item)
size_t contract_threshold
void empty_and_release()
Empty the array and release all memory.
static constexpr size_t Min_Dim
MemArray(MemArray &&a) noexcept
Construct an array moved of rvalue a
void allocate()
Allocate memory for the current dimension.
bool traverse(Operation &&operation) const
T * get_ptr() const noexcept
Return the current base of array.
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...
MemArray(const MemArray &a)
Construct a copy of a
T & push(const T &item)
Push a copy of item at the beginning of sequence.
T & append(T &&item)
MemArray & append(const MemArray &a)
MemArray(size_t _dim=Min_Dim)
Construct an array con capacity equal or greater than _dim.
T & insert(T &&item)
void init_dim(size_t d) noexcept
Initialize the dimension of the array to d or to the next two power if d is not a two power.
constexpr size_t capacity() const noexcept
The type of element of array.
MemArray & operator=(const MemArray &a)
Assign by copy a to this
T & insert(const T &item)
T & last() const
Return a modifiable reference to the last element.
bool is_valid() const noexcept
T & get_last() const
void close_gap(size_t pos, size_t num_entries=1)
bool is_empty() const noexcept
Return true is the array is empty.
bool traverse(Operation &&operation)
T & get_first() const
T pop()
pop() the most recently pushed item
void empty() noexcept
Empties the container.
MemArray & reverse()
Reverse the order of items in array.
const size_t & get_dim() const noexcept
Return the current dimension of array.
T get(const size_t i=1)
Remove i elements from the end.
void swap(MemArray &a) noexcept
Swap in constant time this with a
bool traverse(Operation &operation) const
T & operator[](const size_t i) const
Return a reference to the ith element.
T & put(T &&item)
Move item at the end of sequence.
T & put(const T &item)
Put a copy of item at the end of sequence.
T remove_first()
Remove the first item. Gap is closed.
MemArray & operator=(MemArray &&a) noexcept
Assign by moving a to this
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_log2_function > > log2(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4064
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
void open_gap(Tarray &ptr, size_t n, size_t pos=0, size_t num_entries=1)
Open a gap in an array by shifting elements right.
Definition array_utils.H:96
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
void close_gap(T *ptr, size_t n, size_t pos, size_t num_entries=1)
Close a gap in an array by shifting elements left.
Simple iterator on elements of array.
Iterator(const MemArray< T > &a) noexcept
Construct an iterator on array a
static int * k