General Purpose library for Freestanding C++ and POSIX systems
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

128 lignes
2.1 KiB

  1. #pragma once
  2. #include <gp/utils/iterators/iterator_properties.hpp>
  3. #include <cstddef>
  4. #include <cstdint>
  5. namespace gp {
  6. struct index_to_1 {
  7. size_t value;
  8. index_to_1(size_t v) : value{v + 1}
  9. {}
  10. void left() {
  11. value <<= 1;
  12. }
  13. void right() {
  14. value = (value << 1) + 1;
  15. }
  16. void up() {
  17. value >>= 1;
  18. }
  19. bool is_right() const {
  20. return value & 1;
  21. }
  22. bool is_left() const {
  23. return !(value & 1);
  24. }
  25. bool is_root() const {
  26. return value == 1;
  27. }
  28. operator size_t() {
  29. return value - 1;
  30. }
  31. };
  32. template<typename reflect, typename T, int sign = 1>
  33. struct flat_tree_iterator {
  34. reflect& tree;
  35. size_t index;
  36. bool has_right(index_to_1 v) const {
  37. v.right();
  38. return (v < tree.data().size()) && (tree.data()[v].has_value());
  39. }
  40. bool has_left(index_to_1 v) const {
  41. v.left();
  42. return (v < tree.data().size()) && (tree.data()[v].has_value());
  43. }
  44. flat_tree_iterator& operator++() {
  45. index = next();
  46. return *this;
  47. }
  48. flat_tree_iterator operator++(int) {
  49. auto cpy = *this;
  50. index = next();
  51. return cpy;
  52. }
  53. size_t next() const {
  54. index_to_1 it{index};
  55. enum class cases {
  56. right_climber,
  57. left_climber,
  58. descender,
  59. starter
  60. };
  61. const cases current_case = [&](){
  62. if(index == (size_t)-1) {
  63. return cases::starter;
  64. } else if(has_right(it)) {
  65. return cases::descender;
  66. } else if(it.is_left()) {
  67. return cases::left_climber;
  68. } else {
  69. return cases::right_climber;
  70. }
  71. }();
  72. switch(current_case) {
  73. case cases::starter: {
  74. it = index_to_1{0};
  75. while(has_left(it)) {
  76. it.left();
  77. }
  78. } break;
  79. case cases::descender: {
  80. it.right();
  81. while(has_left(it)) {
  82. it.left();
  83. }
  84. } break;
  85. case cases::left_climber: {
  86. it.up();
  87. } break;
  88. case cases::right_climber: {
  89. while(it.is_right()) {
  90. it.up();
  91. }
  92. if(it.is_root()) {
  93. it.value = -1;
  94. }
  95. } break;
  96. }
  97. return it;
  98. }
  99. bool operator!=(flat_tree_iterator rhs) {
  100. return index != rhs.index;
  101. }
  102. T& operator*() {
  103. return tree.data_[index].value();
  104. }
  105. };
  106. }