20#define CONTAINER_SANITY_CHECKS
23#define MAIA_CONTAINER_ENSURE(condition, message, at) \
25 TERMM(1, std::string("\n\n") + (message) + "\n\n AT: " + at); \
30#define MAIA_CONTAINER_ENSURE_VALID_ID(id) \
32 MAIA_CONTAINER_ENSURE(this->isValidId((id)), \
33 "id = " + std::to_string((id)) + " out-of-bounds [0, " + std::to_string(this->size()) \
34 + ") and is not the dummy cell at \"capacity() - 1\" = " \
35 + std::to_string(this->capacity() - 1), \
41#ifdef CONTAINER_SANITY_CHECKS
42#define ENSURE_VALID_ID(id) \
44 MAIA_CONTAINER_ENSURE_VALID_ID(id); \
46#define ENSURE_CONDITION(condition, message) \
48 MAIA_CONTAINER_ENSURE(condition, message, AT_); \
51#define ENSURE_VALID_ID(id) \
54#define ENSURE_CONDITION(condition, message) \
76template <
class Derived,
template <
class>
class Invalid>
101 copy(source, from, from + 1, to);
127 virtual void resize() { TERMM(1,
"not implemented"); };
130 template <
typename Container_,
typename T =
typename Container_::value_type>
132 const T value = Invalid<T>::value()) {
133 std::fill(c.data() + begin * solverSize, c.data() + end * solverSize, value);
137 template <
typename Container_,
typename Functor>
138 void copyData(
const Container_& source, Container_& target, Functor&& f,
const MInt begin,
const MInt end,
139 const MInt dest,
const MInt solverSize = 1) {
140 f(source.data() + begin * solverSize, source.data() + end * solverSize, target.data() + dest * solverSize);
146 Derived&
derived() {
return static_cast<Derived&
>(*this); }
147 const Derived&
derived()
const {
return static_cast<const Derived&
>(*this); }
150 template <MBool left>
152 template <
class It1,
class It2, MBool l = left>
153 typename std::enable_if<l, It2>::type
operator()(It1 first, It1 last, It2 dest) {
154 return std::copy(first, last, dest);
156 template <
class It1,
class It2, MBool l = left>
157 typename std::enable_if<!l, It2>::type
operator()(It1 first, It1 last, It2 dest) {
158 return std::copy_backward(first, last, dest);
167 rawCopy(source, from, from + 1, to);
186template <
class Derived,
template <
class>
class Invalid>
188 ENSURE_CONDITION(capacity_ >= 0,
"Capacity must be non-negative");
190 m_capacity = capacity_;
198template <
class Derived,
template <
class>
class Invalid>
200 ENSURE_CONDITION(capacity_ >= 0,
"Capacity must be non-negative");
201 ENSURE_CONDITION(capacity_ >= m_capacity,
"So far only resize to a larger size is tested.");
203 if(capacity_ == m_capacity)
return;
205 m_capacity = capacity_;
212template <
class Derived,
template <
class>
class Invalid>
214 ENSURE_CONDITION(size_ >= 0,
"Size must be non-negative");
215 ENSURE_CONDITION(size_ <= capacity(),
"Size must not exceed capacity");
222template <
class Derived,
template <
class>
class Invalid>
224 ENSURE_CONDITION(count >= 0,
"Count must be non-negative");
226 if(size() + count > capacity()) {
227 std::cerr <<
"Container capacity exceeded: is:" + std::to_string(capacity())
228 +
", desired: " + std::to_string(size() + count)
231 const MInt newCapacity = 1.1 * (size() + count);
232 std::cerr <<
"New container capacity is: " << newCapacity << std::endl;
233 resize(size() + count);
235 derived().invalidate(size(), size() + count);
241template <
class Derived,
template <
class>
class Invalid>
243 ENSURE_CONDITION(count >= 0,
"Count must be non-negative");
244 ENSURE_CONDITION(size() - count >= 0,
"New size below zero");
246 removeAndShift(size() - count, size());
251template <
class Derived,
template <
class>
class Invalid>
254 ENSURE_CONDITION(begin >= 0 && begin < source.size(),
"Begin position outside valid range");
255 ENSURE_CONDITION(end - 1 < source.size(),
"End position outside valid range");
257 ENSURE_CONDITION(to + (end - begin) <= size(),
"Target range outside valid size");
260 if(end <= begin || (&source ==
this && begin == to)) {
264 rawCopy(source, begin, end, to);
269template <
class Derived,
template <
class>
class Invalid>
271 ENSURE_VALID_ID(begin);
272 ENSURE_VALID_ID(end - 1);
274 ENSURE_CONDITION(to + (end - begin) - 1 < size(),
"Target range outside valid size");
277 if(end <= begin || begin == to) {
281 rawCopy(derived(), begin, end, to);
282 derived().moveConnectivity(begin, end, to);
283 derived().invalidate(begin, end);
288template <
class Derived,
template <
class>
class Invalid>
299 rawCopy(derived(),
a, dummy());
300 derived().moveConnectivity(
a, dummy());
303 rawCopy(derived(),
b,
a);
304 derived().moveConnectivity(
b,
a);
307 rawCopy(derived(), dummy(),
b);
308 derived().moveConnectivity(dummy(),
b);
311 derived().invalidate(dummy(), dummy() + 1);
317template <
class Derived,
template <
class>
class Invalid>
319 ENSURE_CONDITION(isValidId(
id) ||
id == size(),
"Id must refer to a valid node or be equal to size()");
320 ENSURE_CONDITION(count >= 0,
"Count must be non-negative");
321 ENSURE_CONDITION(count + size() <= capacity(),
"New size exceeds capacity");
329 move(
id, size() - count,
id + count);
334template <
class Derived,
template <
class>
class Invalid>
336 ENSURE_VALID_ID(begin);
337 ENSURE_VALID_ID(end - 1);
344 derived().deleteConnectivity(begin, end);
345 derived().invalidate(begin, end);
351template <
class Derived,
template <
class>
class Invalid>
353 ENSURE_VALID_ID(begin);
354 ENSURE_VALID_ID(end - 1);
361 derived().deleteConnectivity(begin, end);
362 derived().invalidate(begin, end);
364 move(end, size(), begin);
366 const MInt count = end - begin;
373template <
class Derived,
template <
class>
class Invalid>
375 ENSURE_VALID_ID(begin);
376 ENSURE_VALID_ID(end - 1);
383 derived().deleteConnectivity(begin, end);
384 derived().invalidate(begin, end);
385 const MInt count = end - begin;
387 move(std::max(end, size() - count), size(), begin);
394template <
class Derived,
template <
class>
class Invalid>
396 derived().invalidate(0, size());
402template <
class Derived,
template <
class>
class Invalid>
406 if(to < begin || to >= end) {
408 derived().rawCopyGeneric(
Copy<true>{}, source, begin, end, to);
411 const MInt count = end - begin;
412 derived().rawCopyGeneric(
Copy<false>{}, source, begin, end, to + count);
418template <
class Derived,
template <
class>
class Invalid>
424 Storage<T>(std::max((m_capacity + 1) * n, 1), Invalid<T>::value()).swap(c);
434template <
class Derived,
template <
class>
class Invalid>
437 c.resize(std::max((m_capacity + 1) * n, 1), Invalid<T>::value());
442template <
class Derived,
template <
class>
class Invalid>
447 if(!((
id >= 0 &&
id < size()) ||
id == capacity() - 1)) {
448 std::cerr <<
"id = " <<
id << std::endl
449 <<
"size() = " << size() << std::endl
450 <<
"capacity() = " << capacity() << std::endl;
452 return ((
id >= 0 &&
id < size()) ||
id == capacity() - 1);
460#undef CONTAINER_SANITY_CHECKS
461#undef ENSURE_VALID_ID
462#undef ENSURE_CONDITION
void resize(const MInt capacity)
Resize the container capacity.
void move(const MInt begin, const MInt end, const MInt to)
Move nodes to another location and update parent/child/neighbor information accordingly.
void removeAndShift(const MInt id)
void moveConnectivity(const MInt NotUsed(begin), const MInt NotUsed(end), const MInt NotUsed(to))
void deleteConnectivity(const MInt NotUsed(begin), const MInt NotUsed(end))
void move(const MInt from, const MInt to)
void rawCopy(const T &source, const MInt begin, const MInt end, const MInt to)
Copy range of nodes [begin, end) to range starting at 'to'.
void removeAndFill(const MInt begin, const MInt end)
const Derived & derived() const
void insert(const MInt id)
void clear()
Clear tree by invalidating all nodes and setting size to zero.
void moveConnectivity(const MInt from, const MInt to)
MBool isValidId(const MInt id) const
Return whether given id refers to a valid node (auxiliary method).
void copyData(const Container_ &source, Container_ &target, Functor &&f, const MInt begin, const MInt end, const MInt dest, const MInt solverSize=1)
Copy [begin, end) range with given solver size from source to dest position of target.
constexpr MInt dummy() const
void removeAndShift(const MInt begin, const MInt end)
void erase(const MInt begin, const MInt end)
Erase nodes in range [begin, end) and update parent/child/neighbor information.
constexpr MInt size() const
Return size (i.e., currently used number of nodes)
void copy(const MInt from, const MInt to)
void fill_invalid(Container_ &c, const MInt begin, const MInt end, const MInt solverSize=1, const T value=Invalid< T >::value())
void copy(const T &source, const MInt from, const MInt to)
void shrink(const MInt count)
Remove nodes from end of tree.
void resetStorage(const MInt n, Storage< T > &c)
Create new container with given size and replace original one.
constexpr MInt capacity() const
Return capacity (i.e., maximum number of nodes)
void resizeStorage(const MInt n, Storage< T > &c)
Resize container with given size.
void erase(const MInt id)
void reset(const MInt capacity)
Reset tree, re-create data structures with given capacity, and set size to zero.
void append(const MInt count)
Append nodes to end of tree.
void rawCopy(const T &source, const MInt from, const MInt to)
void removeAndFill(const MInt id)
void copy(const T &source, const MInt begin, const MInt end, const MInt to)
Copy nodes to another location without changing any parent/child/neighbor information.
constexpr Container()=default
Default c'tor does nothing.
void insert(const MInt begin, const MInt count)
void copy(const MInt begin, const MInt end, const MInt to)
void size(const MInt size_)
Resize tree WITHOUT CONSIDERING ANY NODE CONSISTENCY! Use at own risk and remove ASAP....
void swap(const MInt a, const MInt b)
Swap two nodes and update parent/child/neighbor information accordingly.
Namespace for auxiliary functions/classes.
std::enable_if<!l, It2 >::type operator()(It1 first, It1 last, It2 dest)
std::enable_if< l, It2 >::type operator()(It1 first, It1 last, It2 dest)