#pragma once
|
|
|
|
#include <gp/utils/iterators/iterator_properties.hpp>
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
namespace gp {
|
|
|
|
struct index_to_1 {
|
|
size_t value;
|
|
|
|
index_to_1(size_t v) : value{v + 1}
|
|
{}
|
|
|
|
void left() {
|
|
value <<= 1;
|
|
}
|
|
|
|
void right() {
|
|
value = (value << 1) + 1;
|
|
}
|
|
|
|
void up() {
|
|
value >>= 1;
|
|
}
|
|
|
|
bool is_right() const {
|
|
return value & 1;
|
|
}
|
|
|
|
bool is_left() const {
|
|
return !(value & 1);
|
|
}
|
|
|
|
bool is_root() const {
|
|
return value == 1;
|
|
}
|
|
|
|
operator size_t() {
|
|
return value - 1;
|
|
}
|
|
};
|
|
|
|
template<typename reflect, typename T, int sign = 1>
|
|
struct flat_tree_iterator {
|
|
reflect& tree;
|
|
size_t index;
|
|
|
|
bool has_right(index_to_1 v) const {
|
|
v.right();
|
|
return (v < tree.data().size()) && (tree.data()[v].has_value());
|
|
}
|
|
|
|
bool has_left(index_to_1 v) const {
|
|
v.left();
|
|
return (v < tree.data().size()) && (tree.data()[v].has_value());
|
|
}
|
|
|
|
flat_tree_iterator& operator++() {
|
|
index = next();
|
|
return *this;
|
|
}
|
|
|
|
flat_tree_iterator operator++(int) {
|
|
auto cpy = *this;
|
|
index = next();
|
|
return cpy;
|
|
}
|
|
|
|
size_t next() const {
|
|
index_to_1 it{index};
|
|
|
|
enum class cases {
|
|
right_climber,
|
|
left_climber,
|
|
descender,
|
|
starter
|
|
};
|
|
|
|
const cases current_case = [&](){
|
|
if(index == (size_t)-1) {
|
|
return cases::starter;
|
|
} else if(has_right(it)) {
|
|
return cases::descender;
|
|
} else if(it.is_left()) {
|
|
return cases::left_climber;
|
|
} else {
|
|
return cases::right_climber;
|
|
}
|
|
}();
|
|
|
|
switch(current_case) {
|
|
case cases::starter: {
|
|
it = index_to_1{0};
|
|
while(has_left(it)) {
|
|
it.left();
|
|
}
|
|
} break;
|
|
case cases::descender: {
|
|
it.right();
|
|
while(has_left(it)) {
|
|
it.left();
|
|
}
|
|
} break;
|
|
case cases::left_climber: {
|
|
it.up();
|
|
} break;
|
|
case cases::right_climber: {
|
|
while(it.is_right()) {
|
|
it.up();
|
|
}
|
|
if(it.is_root()) {
|
|
it.value = -1;
|
|
}
|
|
} break;
|
|
}
|
|
return it;
|
|
}
|
|
|
|
bool operator!=(flat_tree_iterator rhs) {
|
|
return index != rhs.index;
|
|
}
|
|
|
|
T& operator*() {
|
|
return tree.data_[index].value();
|
|
}
|
|
};
|
|
}
|