forest_algorithms.hpp (4780B)
1 /**************************************************************************************************/ 2 3 #ifndef STLAB_FOREST_ALGORITHMS_HPP 4 #define STLAB_FOREST_ALGORITHMS_HPP 5 6 /**************************************************************************************************/ 7 8 // stlab 9 #include <stlab/concurrency/optional.hpp> 10 #include <stlab/forest.hpp> 11 12 /**************************************************************************************************/ 13 14 namespace stlab { 15 16 /**************************************************************************************************/ 17 18 namespace forests { 19 20 /**************************************************************************************************/ 21 // "Congruent" would be a nice name here, but in geometry that also implies reflection. 22 template <class Forest1, class Forest2> 23 bool equal_shape(const Forest1& x, const Forest2& y) { 24 if (x.size_valid() && y.size_valid() && x.size() != y.size()) return false; 25 auto pos{y.begin()}; 26 for (auto first(x.begin()), last(x.end()); first != last; ++first, ++pos) { 27 if (first.edge() != pos.edge()) return false; 28 } 29 return true; 30 } 31 32 /**************************************************************************************************/ 33 34 template <class Container> 35 struct transcribe_iterator { 36 using iterator_category = std::output_iterator_tag; 37 using value_type = void; 38 using difference_type = void; 39 using pointer = void; 40 using reference = void; 41 using container_type = Container; 42 43 transcribe_iterator(Container& c, typename Container::iterator i) : _c{&c}, _i{std::move(i)} {} 44 45 constexpr auto& operator*() { return *this; } 46 constexpr auto& operator++() { 47 ++_i; 48 return *this; 49 } 50 constexpr auto operator++(int) { 51 auto result{*this}; 52 ++_i; 53 return result; 54 } 55 56 constexpr auto& operator=(const typename Container::value_type& value) { 57 _i = _c->insert(_i, value); 58 return *this; 59 } 60 61 constexpr auto& operator=(typename Container::value_type&& value) { 62 _i = _c->insert(_i, std::move(value)); 63 return *this; 64 } 65 66 constexpr auto trailing() { _i = trailing_of(_i); } 67 68 private: 69 Container* _c; 70 typename Container::iterator _i; 71 }; 72 73 template <class Container> 74 auto transcriber(Container& c) { 75 return transcribe_iterator<Container>(c, c.begin()); 76 } 77 78 /**************************************************************************************************/ 79 80 template <class I, class O, class P, class UP> 81 auto transcribe(I first, I last, O out, P proj, UP pred) { 82 for (; first != last; ++first, ++out) { 83 if (pred(first)) { 84 out = proj(*first); 85 } else { 86 out.trailing(); 87 } 88 } 89 return out; 90 } 91 92 template <class R, class O, class P, class UP> 93 auto transcribe(const R& range, O out, P proj, UP pred) { 94 return transcribe(std::cbegin(range), std::cend(range), std::move(out), std::move(proj), 95 std::move(pred)); 96 } 97 98 template <class I, class O, class P> 99 auto transcribe(I first, I last, O out, P proj) { 100 return transcribe(std::move(first), std::move(last), std::move(out), std::move(proj), 101 [](const auto& p) { return is_leading(p); }); 102 } 103 104 template <class R, class O, class P> 105 auto transcribe(const R& range, O out, P proj) { 106 return transcribe(std::cbegin(range), std::cend(range), std::move(out), std::move(proj)); 107 } 108 109 /**************************************************************************************************/ 110 111 template <class I, // models ForestFullorderIterator 112 class O> // models OutputIterator 113 auto flatten(I first, I last, O out) { 114 for (; first != last; ++first) { 115 if (is_leading(first)) { 116 *out++ = *first; 117 } else { 118 *out++ = nullopt; 119 } 120 } 121 return out; 122 } 123 124 /**************************************************************************************************/ 125 126 template <class I, // I models ForwardIterator; I::value_type == stlab::optional<T> 127 class F> // F models Forest 128 auto unflatten(I first, I last, F& f) { 129 return forests::transcribe( 130 first, last, transcriber(f), [](const auto& x) { return *x; }, 131 [](const auto& p) { return *p; }); 132 } 133 134 /**************************************************************************************************/ 135 136 } // namespace forests 137 138 /**************************************************************************************************/ 139 140 } // namespace stlab 141 142 /**************************************************************************************************/ 143 144 #endif // STLAB_FOREST_ALGORITHMS_HPP 145 146 /**************************************************************************************************/