1#ifndef UFO_MAP_SEMANTIC_UTIL_HPP
2#define UFO_MAP_SEMANTIC_UTIL_HPP
5#if __cplusplus >= 202002L
15#include <ufo/map/semantic/semantic.hpp>
16#include <ufo/map/types.hpp>
18namespace ufo::semantic
21using size_type = label_t;
22using difference_type = std::ptrdiff_t;
23using reference = Semantic&;
24using const_reference = Semantic
const&;
25using pointer = Semantic*;
26using const_pointer = Semantic
const*;
27using iterator = Semantic*;
28using const_iterator = Semantic
const*;
29using reverse_iterator = std::reverse_iterator<iterator>;
30using const_reverse_iterator = std::reverse_iterator<const_iterator>;
36template <std::
size_t N>
37void clear(std::unique_ptr<Semantic[]>& semantics)
noexcept
46template <std::
size_t N>
47[[nodiscard]]
bool empty(std::unique_ptr<Semantic[]>
const& semantics)
noexcept
49 return nullptr == semantics;
56template <std::
size_t N>
57[[nodiscard]] size_type size(std::unique_ptr<Semantic[]>
const& semantics,
77 if (empty<N>(semantics)) {
87 std::memcpy(&dst, &semantics[index / 2].value,
sizeof(label_t));
90 return semantics[index / 2].label;
95template <std::
size_t N>
96[[nodiscard]] std::array<size_type, N> sizes(std::unique_ptr<Semantic[]>
const& semantics)
98 if (empty<N>(semantics)) {
99 return std::array<size_type, N>{};
104 std::array<size_type, N> s;
108 for (offset_t i = 0; i < N; ++i) {
109 s[i] = size<N>(semantics, i);
114template <std::
size_t N>
115[[nodiscard]] size_type size(std::unique_ptr<Semantic[]>
const& semantics)
117 auto const s = sizes<N>(semantics);
118 return std::accumulate(std::begin(s), std::end(s), size_type(0));
121template <std::
size_t N>
122[[nodiscard]] std::size_t allocSize(std::unique_ptr<Semantic[]>
const& semantics)
124 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
126 return empty<N>(semantics) ? 0 : size<N>(semantics) + N_H;
133template <std::
size_t N>
134[[nodiscard]] std::size_t offset(std::unique_ptr<Semantic[]>
const& semantics,
135 offset_t
const index)
137 auto const s = sizes<N>(semantics);
138 return std::accumulate(std::begin(s), std::begin(s) + index, std::size_t(0));
141template <std::
size_t N>
142[[nodiscard]]
bool empty(std::unique_ptr<Semantic[]>
const& semantics,
143 offset_t
const index)
145 return 0 == size<N>(semantics, index);
152template <std::
size_t N>
153iterator begin(std::unique_ptr<Semantic[]>
const& semantics)
noexcept
155 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
157 return empty<N>(semantics) ? nullptr : semantics.get() + N_H;
160template <std::
size_t N>
161const_iterator cbegin(std::unique_ptr<Semantic[]>
const& semantics)
noexcept
163 return begin<N>(semantics);
166template <std::
size_t N>
167iterator end(std::unique_ptr<Semantic[]>
const& semantics)
noexcept
169 auto const s = allocSize<N>(semantics);
170 return 0 == s ? nullptr : semantics.get() + s;
173template <std::
size_t N>
174const_iterator cend(std::unique_ptr<Semantic[]>
const& semantics)
noexcept
176 return end<N>(semantics);
183template <std::
size_t N>
184iterator begin(std::unique_ptr<Semantic[]>
const& semantics,
185 offset_t
const index)
noexcept
187 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
189 return empty<N>(semantics, index) ? nullptr
190 : semantics.get() + N_H + offset<N>(semantics, index);
193template <std::
size_t N>
194const_iterator cbegin(std::unique_ptr<Semantic[]>
const& semantics,
195 offset_t
const index)
noexcept
197 return begin<N>(semantics, index);
200template <std::
size_t N>
201iterator end(std::unique_ptr<Semantic[]>
const& semantics, offset_t
const index)
noexcept
203 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
205 return empty<N>(semantics, index)
207 : semantics.get() + N_H + offset<N>(semantics, index) +
208 size<N>(semantics, index);
211template <std::
size_t N>
212const_iterator cend(std::unique_ptr<Semantic[]>
const& semantics,
213 offset_t
const index)
noexcept
215 return end<N>(semantics, index);
222template <
class InputIt,
typename = std::enable_if_t<std::is_base_of_v<
223 std::input_iterator_tag,
224 typename std::iterator_traits<InputIt>::iterator_category>>>
225[[nodiscard]] InputIt lower_bound(InputIt first, InputIt last, label_t label)
227 return std::lower_bound(first, last,
228 Semantic(label, std::numeric_limits<value_t>::lowest()));
231template <std::
size_t N>
232[[nodiscard]] iterator lower_bound(std::unique_ptr<Semantic[]>
const& semantics,
233 offset_t index, label_t label)
236 return lower_bound(begin<N>(semantics, index), end<N>(semantics, index), label);
243template <
class InputIt,
typename = std::enable_if_t<std::is_base_of_v<
244 std::input_iterator_tag,
245 typename std::iterator_traits<InputIt>::iterator_category>>>
246[[nodiscard]] InputIt upper_bound(InputIt first, InputIt last, label_t label)
248 return std::upper_bound(first, last,
249 Semantic(label, std::numeric_limits<value_t>::max()));
252template <std::
size_t N>
253[[nodiscard]] iterator upper_bound(std::unique_ptr<Semantic[]>
const& semantics,
254 offset_t index, label_t label)
257 return upper_bound(begin<N>(semantics, index), end<N>(semantics, index), label);
264template <std::
size_t N>
265[[nodiscard]] std::pair<iterator, iterator> equal_range(
266 std::unique_ptr<Semantic[]>
const& semantics, offset_t index, label_t label)
268 return std::make_pair(lower_bound<N>(semantics, index, label),
269 upper_bound<N>(semantics, index, label));
276template <std::
size_t N>
277[[nodiscard]] iterator find(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
280 auto it = lower_bound<N>(semantics, index, label);
281 return end<N>(semantics, index) != it && it->label == label ? it
282 : end<N>(semantics, index);
298template <std::
size_t N>
299[[nodiscard]]
bool contains(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
302 return end<N>(semantics, index) != find<N>(semantics, index, label);
308template <std::
size_t N>
309[[nodiscard]] std::optional<Semantic> at(std::unique_ptr<Semantic[]>
const& semantics,
310 offset_t index, label_t label)
312 iterator it = find<N>(semantics, index, label);
313 return end<N>(semantics, index) != it ? std::optional<Semantic>(*it) :
std::nullopt;
319template <std::
size_t N>
320[[nodiscard]] std::optional<value_t> value(std::unique_ptr<Semantic[]>
const& semantics,
321 offset_t index, label_t label)
323 auto it = find<N>(semantics, index, label);
324 return end<N>(semantics, index) != it ? std::optional<value_t>(it->value)
331template <std::
size_t N>
332[[nodiscard]] size_type count(std::unique_ptr<Semantic[]>
const& semantics,
333 offset_t index, label_t label)
335 return contains<N>(semantics, index, label) ? 1 : 0;
342template <std::
size_t N>
343[[nodiscard]]
bool all(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
344 SemanticRangeSet
const& ranges)
346 if (ranges.empty()) {
348 }
else if (size<N>(semantics, index) < ranges.numValues()) {
352 auto first = cbegin<N>(semantics, index);
353 auto last = cend<N>(semantics, index);
354 for (
auto range : ranges) {
355 auto lower = lower_bound(first, last, range.lower());
356 first = upper_bound(lower, last, range.upper());
357 auto range_dist = range.upper() - range.lower() + 1;
358 auto sem_dist = std::distance(lower, first);
359 if (first == last || range_dist != sem_dist) {
366template <std::
size_t N>
367[[nodiscard]]
bool all(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
370 return all<N>(semantics, index, SemanticRangeSet(range));
373template <std::
size_t N,
class UnaryPredicate>
374[[nodiscard]]
bool all(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
377 return std::all_of(cbegin<N>(semantics, index), cend<N>(semantics, index), p);
380template <std::
size_t N,
class UnaryPredicate>
381[[nodiscard]]
bool all(std::unique_ptr<Semantic[]>
const& semantics, UnaryPredicate p)
383 return std::all_of(cbegin<N>(semantics), cend<N>(semantics), p);
386template <std::
size_t N,
class UnaryPredicate>
387[[nodiscard]]
bool all(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
388 SemanticRangeSet
const& ranges, UnaryPredicate p)
390 if (ranges.empty()) {
392 }
else if (size<N>(semantics, index) < ranges.numValues()) {
396 auto first = cbegin<N>(semantics, index);
397 auto last = cend<N>(semantics, index);
398 for (
auto range : ranges) {
399 auto lower = lower_bound(first, last, range.lower());
400 first = upper_bound(lower, last, range.upper());
401 auto range_dist = range.upper() - range.lower() + 1;
402 auto sem_dist = std::distance(lower, first);
403 if (first == last || range_dist != sem_dist) {
406 for (; lower != first; ++lower) {
415template <std::
size_t N,
class UnaryPredicate>
416[[nodiscard]]
bool all(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
417 SemanticRange range, UnaryPredicate p)
419 return all<N>(semantics, index, SemanticRangeSet(range), p);
426template <std::
size_t N>
427[[nodiscard]]
bool any(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
428 SemanticRangeSet
const& ranges)
430 if (ranges.empty()) {
434 if (size<N>(semantics, index) < ranges.size()) {
435 for (
auto it = cbegin<N>(semantics, index), last = cend<N>(semantics, index);
437 if (ranges.contains(it->label)) {
442 auto first = cbegin<N>(semantics, index);
443 auto last = cend<N>(semantics, index);
444 for (
auto range : ranges) {
445 first = lower_bound(first, last, range.lower());
448 }
else if (first->label <= range.upper()) {
456template <std::
size_t N>
457[[nodiscard]]
bool any(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
460 return any<N>(semantics, index, SemanticRangeSet(range));
463template <std::
size_t N,
class UnaryPredicate>
464[[nodiscard]]
bool any(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
467 return std::any_of(cbegin<N>(semantics, index), cend<N>(semantics, index), p);
470template <std::
size_t N,
class UnaryPredicate>
471[[nodiscard]]
bool any(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
472 SemanticRange range, UnaryPredicate p)
474 return any<N>(semantics, index, SemanticRangeSet(range), p);
477template <std::
size_t N,
class UnaryPredicate>
478[[nodiscard]]
bool any(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
479 SemanticRangeSet
const& ranges, UnaryPredicate p)
481 if (ranges.empty()) {
485 if (size<N>(semantics, index) < ranges.size()) {
486 for (
auto it = cbegin<N>(semantics, index), last = cend<N>(semantics, index);
488 if (ranges.contains(it->label) && p(*it)) {
493 auto first = cbegin<N>(semantics, index);
494 auto last = cend<N>(semantics, index);
495 for (
auto range : ranges) {
496 first = lower_bound(first, last, range.lower());
497 for (; first != last && first->label <= range.upper(); ++first) {
513template <std::
size_t N>
514[[nodiscard]]
bool none(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
515 SemanticRangeSet
const& ranges)
517 return !any<N>(semantics, index, ranges);
520template <std::
size_t N>
521[[nodiscard]]
bool none(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
524 return none<N>(semantics, index, SemanticRangeSet(range));
527template <std::
size_t N,
class UnaryPredicate>
528[[nodiscard]]
bool none(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
531 return std::none_of(cbegin<N>(semantics, index), cend<N>(semantics, index), p);
534template <std::
size_t N,
class UnaryPredicate>
535[[nodiscard]]
bool none(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
536 SemanticRange range, UnaryPredicate p)
538 return none<UnaryPredicate, N>(semantics, index, SemanticRangeSet(range), p);
541template <std::
size_t N,
class UnaryPredicate>
542[[nodiscard]]
bool none(std::unique_ptr<Semantic[]>
const& semantics, offset_t index,
543 SemanticRangeSet
const& ranges, UnaryPredicate p)
545 return !any<N>(semantics, index, ranges, p);
560template <std::
size_t N>
561void setSize(std::unique_ptr<Semantic[]>
const& semantics, offset_t
const index,
562 size_type
const size)
577 std::memcpy(&semantics[index / 2].value, &size,
sizeof(value_t));
579 semantics[index / 2].label =
static_cast<label_t
>(size);
583template <std::
size_t N>
584void resizeLazy(std::unique_ptr<Semantic[]>& semantics,
585 std::array<size_type, N>
const& new_sizes)
587 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
589 auto new_size = std::accumulate(std::begin(new_sizes), std::end(new_sizes), 0);
597 auto const cur_sizes = sizes<N>(semantics);
598 if (cur_sizes == new_sizes) {
602 if (std::accumulate(std::begin(cur_sizes), std::end(cur_sizes), N_H) != new_size) {
603 pointer p_cur = semantics.release();
604 pointer p_new =
static_cast<pointer
>(realloc(p_cur, new_size *
sizeof(Semantic)));
607 semantics.reset(p_cur);
608 throw std::bad_alloc();
611 semantics.reset(p_new);
614 for (offset_t i = 0; N != i; ++i) {
615 setSize<N>(semantics, i, new_sizes[i]);
619template <std::
size_t N>
620void resizeLazy(std::unique_ptr<Semantic[]>& semantics, size_type
const size)
622 std::array<size_type, N> sizes;
624 resizeLazy<N>(semantics, sizes);
627template <std::
size_t N>
628void resizeLazy(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
629 size_type
const new_size)
632 std::array<size_type, N> s = sizes<N>(semantics);
634 resizeLazy<N>(semantics, s);
637template <std::
size_t N>
638void resize(std::unique_ptr<Semantic[]>& semantics,
639 std::array<size_type, N>
const& new_sizes)
641 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
643 auto const new_size = std::accumulate(std::begin(new_sizes), std::end(new_sizes), N_H);
649 auto const cur_sizes = sizes<N>(semantics);
650 if (cur_sizes == new_sizes) {
654 for (
int i = N - 1; 0 <= i; --i) {
656 if (cur_sizes[i] <= new_sizes[i]) {
660 std::move(end<N>(semantics,
static_cast<offset_t
>(i)), end<N>(semantics),
661 begin<N>(semantics,
static_cast<offset_t
>(i)) + new_sizes[i]);
662 setSize<N>(semantics,
static_cast<offset_t
>(i), new_sizes[i]);
665 if (std::accumulate(std::begin(cur_sizes), std::end(cur_sizes), N_H) != new_size) {
666 pointer p_cur = semantics.release();
667 pointer p_new =
static_cast<pointer
>(realloc(p_cur, new_size *
sizeof(Semantic)));
670 semantics.reset(p_cur);
671 throw std::bad_alloc();
674 semantics.reset(p_new);
677 if (0 == std::accumulate(std::begin(cur_sizes), std::end(cur_sizes), N_H) ||
678 std::accumulate(std::begin(cur_sizes), std::end(cur_sizes), 0) == 0) {
679 for (offset_t i = 0; N != i; ++i) {
680 setSize<N>(semantics, i, new_sizes[i]);
684 auto const cur_size =
685 std::accumulate(std::begin(cur_sizes), std::end(cur_sizes), N_H);
686 auto cur_last = semantics.get() + cur_size;
689 for (
int i = N - 1; i >= 0; --i) {
691 auto last_i_old = end<N>(semantics,
static_cast<offset_t
>(i));
693 setSize<N>(semantics,
static_cast<offset_t
>(i), new_sizes[i]);
697 if (cur_sizes[i] >= new_sizes[i]) {
707 auto first_i = begin<N>(semantics,
static_cast<offset_t
>(i));
710 auto start = first_i;
714 if (cur_sizes[i] == 0) {
724 auto new_last = cur_last + (new_sizes[i] - cur_sizes[i]);
725 std::move_backward(start, cur_last, new_last);
731template <std::
size_t N>
732void resize(std::unique_ptr<Semantic[]>& semantics, size_type
const size)
734 std::array<size_type, N> sizes;
736 resize<N>(semantics, sizes);
739template <std::
size_t N>
740void resize(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
741 size_type
const new_size)
744 std::array<size_type, N> s = sizes<N>(semantics);
746 resize<N>(semantics, s);
749template <std::
size_t N>
750void clear(std::unique_ptr<Semantic[]>& semantics, offset_t
const index)
752 resize<N>(semantics, index, 0);
755template <std::size_t N,
class InputIt,
756 typename = std::enable_if_t<std::is_base_of_v<
757 std::input_iterator_tag,
758 typename std::iterator_traits<InputIt>::iterator_category>>>
759size_type numAlreadyExists(std::unique_ptr<Semantic[]>
const& semantics,
760 offset_t
const index, InputIt first, InputIt last)
764 auto first_index = cbegin<N>(semantics, index);
765 auto last_index = cend<N>(semantics, index);
766 for (; first != last && first_index != last_index; ++first) {
768 if constexpr (std::is_same_v<Semantic,
769 typename std::iterator_traits<InputIt>::value_type>) {
770 label = first->label;
774 first_index = lower_bound(first_index, last_index, label);
775 if (first_index != last_index && first_index->label == label) {
799template <std::size_t N,
bool Assign,
class InputIt,
800 typename = std::enable_if_t<std::is_base_of_v<
801 std::input_iterator_tag,
802 typename std::iterator_traits<InputIt>::iterator_category>>>
803void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index,
804 size_type cur_size, size_type new_size, InputIt first,
809 }
else if (0 == cur_size) {
810 std::copy(first, last, begin<N>(semantics, index));
814 if constexpr (!Assign) {
815 if (cur_size == new_size) {
820 auto cur = end<N>(semantics, index);
821 auto first_index = begin<N>(semantics, index);
822 auto last_index = first_index + cur_size;
823 while (first != last && first_index != last_index) {
824 if constexpr (Assign) {
825 if ((last_index - 1)->label == (last - 1)->label) {
826 (--cur)->label = (--last_index)->label;
827 cur->value = (--last)->value;
831 if ((last_index - 1)->label < (last - 1)->label) {
832 *(--cur) = *(--last);
833 if constexpr (!Assign) {
836 if (cur_size == new_size) {
842 *(--cur) = *(--last_index);
847 std::copy(first, last, first_index);
862template <std::size_t N,
bool Assign,
class InputIt,
class UnaryFunction,
863 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
864 typename = std::enable_if_t<std::is_base_of_v<
865 std::input_iterator_tag,
866 typename std::iterator_traits<InputIt>::iterator_category>>>
867void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index,
868 size_type cur_size, size_type new_size, InputIt first,
869 InputIt last, UnaryFunction f)
873 }
else if (0 == cur_size) {
874 for (
auto it = begin<N>(semantics, index); first != last; ++it, ++first) {
876 it->value = f(Semantic(*first));
881 if constexpr (!Assign) {
882 if (cur_size == new_size) {
887 auto cur = end<N>(semantics, index);
888 auto first_index = begin<N>(semantics, index);
889 auto last_index = first_index + cur_size;
890 while (first != last && first_index != last_index) {
891 if constexpr (Assign) {
892 if ((last_index - 1)->label == *(last - 1)) {
893 (--cur)->label = (--last_index)->label;
894 cur->value = f(*cur);
899 if ((last_index - 1)->label < *(last - 1)) {
901 cur->label = *(--last);
902 cur->value = f(Semantic(cur->label));
903 if constexpr (!Assign) {
906 if (cur_size == new_size) {
912 *(--cur) = *(--last_index);
917 for (
auto it = begin<N>(semantics, index); first != last; ++it, ++first) {
919 it->value = f(Semantic(*first));
929template <std::size_t N,
bool Assign,
class UnaryFunction,
930 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
931std::pair<iterator, bool> insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics,
932 offset_t
const index, label_t label,
935 if (empty<N>(semantics, index)) {
936 resize<N>(semantics, index, 1);
937 auto it = begin<N>(semantics, index);
939 it->value = f(Semantic(label));
943 auto it = lower_bound<N>(semantics, index, label);
944 if (end<N>(semantics, index) != it && it->label == label) {
946 if constexpr (Assign) {
953 auto i = std::distance(begin<N>(semantics, index), it);
954 resize<N>(semantics, index, size<N>(semantics, index) + 1);
955 it = begin<N>(semantics, index) + i;
956 auto last_index = end<N>(semantics, index);
957 std::move_backward(it, last_index - 1, last_index);
959 it->value = f(Semantic(label));
964template <std::size_t N,
bool Assign,
class UnaryFunction,
965 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
966void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, label_t label,
969 if (empty<N>(semantics)) {
970 std::array<size_type, N> s;
972 resize<N>(semantics, s);
973 std::fill(begin<N>(semantics), end<N>(semantics),
974 Semantic(label, f(Semantic(label))));
978 std::array<size_type, N> new_sizes = sizes<N>(semantics);
979 std::array<difference_type, N> dist;
980 for (offset_t index = 0; N != index; ++index) {
981 auto it = lower_bound<N>(semantics, index, label);
982 if (end<N>(semantics, index) != it && it->label == label) {
984 if constexpr (Assign) {
990 dist[index] = std::distance(begin<N>(semantics, index), it);
998 resize<N>(semantics, new_sizes);
1000 for (offset_t index = 0; N != index; ++index) {
1001 if (dist[index] < 0) {
1004 auto it = begin<N>(semantics, index) + dist[index];
1005 auto last_index = end<N>(semantics, index);
1006 std::move_backward(it, last_index - 1, last_index);
1008 it->value = f(Semantic(label));
1013template <std::size_t N,
bool Assign,
class InputIt,
1014 typename = std::enable_if_t<std::is_base_of_v<
1015 std::input_iterator_tag,
1016 typename std::iterator_traits<InputIt>::iterator_category>>>
1017void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1018 InputIt first, InputIt last)
1020 std::vector vec(first, last);
1022 std::sort(std::begin(vec), std::end(vec));
1025 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1026 [](
auto a,
auto b) {
return a.label ==
b.label; });
1028 auto f = r_last.base();
1029 auto l = std::end(vec);
1030 auto s =
static_cast<size_type
>(std::distance(f, l));
1032 if (empty<N>(semantics, index)) {
1034 resize<N>(semantics, index, s);
1035 std::copy(f, l, begin<N>(semantics, index));
1037 auto cur_size = size<N>(semantics, index);
1038 auto new_size = cur_size + s - numAlreadyExists<N>(semantics, index, f, l);
1040 resize<N>(semantics, index, new_size);
1043 insertOrAssignImpl<N, Assign>(semantics, index, cur_size, new_size, f, l);
1049template <std::size_t N,
bool Assign,
class InputIt,
1050 typename = std::enable_if_t<std::is_base_of_v<
1051 std::input_iterator_tag,
1052 typename std::iterator_traits<InputIt>::iterator_category>>>
1053void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, InputIt first,
1056 std::vector vec(first, last);
1058 std::sort(std::begin(vec), std::end(vec));
1061 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1062 [](
auto a,
auto b) {
return a.label ==
b.label; });
1064 auto f = r_last.base();
1065 auto l = std::end(vec);
1066 auto s =
static_cast<size_type
>(std::distance(f, l));
1068 std::array<size_type, N> new_sizes;
1071 if (empty<N>(semantics)) {
1072 resize<N>(semantics, new_sizes);
1073 for (offset_t index = 0; N != index; ++index) {
1074 std::copy(f, l, begin<N>(semantics, index));
1077 std::array<size_type, N> cur_sizes = sizes<N>(semantics);
1078 for (offset_t index = 0; N != index; ++index) {
1080 s + cur_sizes[index] - numAlreadyExists<N>(semantics, index, f, l);
1083 resize<N>(semantics, new_sizes);
1086 for (offset_t index = 0; N != index; ++index) {
1087 insertOrAssignImpl<N, Assign>(semantics, index, cur_sizes[index], new_sizes[index],
1094template <std::size_t N,
bool Assign,
class UnaryFunction,
1095 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1096std::pair<iterator, bool> insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics,
1097 offset_t
const index, const_iterator hint,
1098 label_t label, UnaryFunction f)
1100 if (empty<N>(semantics, index)) {
1101 resize<N>(semantics, index, 1);
1102 auto it = begin<N>(semantics, index);
1104 it->value = f(Semantic(label));
1108 auto first_index = begin<N>(semantics, index);
1109 auto last_index = end<N>(semantics, index);
1112 first_index != hint && std::prev(hint, 1)->label < label ? hint : first_index;
1113 auto last = last_index != hint && hint->label >= label ? hint : last_index;
1114 hint = lower_bound(first, last, label);
1116 auto i = std::distance<const_iterator>(first_index, hint);
1118 if (last_index != hint && hint->label == label) {
1120 auto it = first_index + i;
1121 if constexpr (Assign) {
1127 resize<N>(semantics, index, size<N>(semantics, index) + 1);
1128 auto it = begin<N>(semantics, index) + i;
1129 last_index = end<N>(semantics, index);
1130 std::move_backward(it, last_index - 1, last_index);
1132 it->value = f(Semantic(label));
1137template <std::size_t N,
bool Assign,
class InputIt,
class UnaryFunction,
1138 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1139 typename = std::enable_if_t<std::is_base_of_v<
1140 std::input_iterator_tag,
1141 typename std::iterator_traits<InputIt>::iterator_category>>>
1142void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1143 InputIt first, InputIt last, UnaryFunction fun)
1145 std::vector vec(first, last);
1147 std::sort(std::begin(vec), std::end(vec));
1150 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1151 [](
auto a,
auto b) {
return a ==
b; });
1153 auto f = r_last.base();
1154 auto l = std::end(vec);
1155 auto s = std::distance(f, l);
1157 if (empty<N>(semantics, index)) {
1159 resize<N>(semantics, index, s);
1160 for (
auto it = begin<N>(semantics, index); f != l; ++it, ++f) {
1162 it->value = fun(Semantic(*f));
1165 auto cur_size = size<N>(semantics, index);
1166 auto new_size = cur_size + s - numAlreadyExists<N>(semantics, index, f, l);
1168 resize<N>(semantics, index, new_size);
1171 insertOrAssignImpl<N, Assign>(semantics, index, cur_size, new_size, f, l, fun);
1177template <std::size_t N,
bool Assign,
class InputIt,
class UnaryFunction,
1178 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1179 typename = std::enable_if_t<std::is_base_of_v<
1180 std::input_iterator_tag,
1181 typename std::iterator_traits<InputIt>::iterator_category>>>
1182void insertOrAssignImpl(std::unique_ptr<Semantic[]>& semantics, InputIt first,
1183 InputIt last, UnaryFunction fun)
1185 std::vector vec(first, last);
1187 std::sort(std::begin(vec), std::end(vec));
1190 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1191 [](
auto a,
auto b) {
return a ==
b; });
1193 auto f = r_last.base();
1194 auto l = std::end(vec);
1195 auto s = std::distance(f, l);
1197 std::array<size_type, N> new_sizes;
1200 if (empty<N>(semantics)) {
1202 std::vector<Semantic> sem;
1204 for (; f != l; ++first) {
1205 sem.emplace_back(*f, fun(Semantic(*f)));
1207 resize<N>(semantics, new_sizes);
1208 for (offset_t index = 0; N != index; ++index) {
1209 std::copy(std::cbegin(sem), std::cend(sem), begin<N>(semantics, index));
1213 std::array<size_type, N> cur_sizes = sizes<N>(semantics);
1215 for (offset_t index = 0; N != index; ++index) {
1217 cur_sizes[index] + s - numAlreadyExists<N>(semantics, index, f, l);
1221 resize<N>(semantics, new_sizes);
1224 for (offset_t index = 0; N != index; ++index) {
1225 insertOrAssignImpl<N, Assign>(semantics, index, cur_sizes[index], new_sizes[index],
1236template <std::
size_t N>
1237void insert(std::unique_ptr<Semantic[]>& semantics, label_t label, value_t value)
1239 insertOrAssignImpl<N, false>(semantics, label, [value](
auto) {
return value; });
1246template <std::size_t N,
class InputIt,
1247 typename = std::enable_if_t<std::is_base_of_v<
1248 std::input_iterator_tag,
1249 typename std::iterator_traits<InputIt>::iterator_category>>>
1250void insert(std::unique_ptr<Semantic[]>& semantics, InputIt first, InputIt last)
1252 insertOrAssignImpl<N, false>(semantics, first, last);
1256template <std::
size_t N>
1257std::pair<iterator, bool> insert(std::unique_ptr<Semantic[]>& semantics,
1258 offset_t
const index, label_t label, value_t value)
1260 return insertOrAssignImpl<N, false>(semantics, index, label,
1261 [value](
auto) {
return value; });
1264template <std::size_t N,
class InputIt,
1265 typename = std::enable_if_t<std::is_base_of_v<
1266 std::input_iterator_tag,
1267 typename std::iterator_traits<InputIt>::iterator_category>>>
1268void insert(std::unique_ptr<Semantic[]>& semantics, offset_t
const index, InputIt first,
1271 insertOrAssignImpl<N, false>(semantics, index, first, last);
1274template <std::
size_t N>
1275std::pair<iterator, bool> insert(std::unique_ptr<Semantic[]>& semantics,
1276 offset_t
const index, const_iterator hint, label_t label,
1279 return insertOrAssignImpl<N, false>(semantics, index, hint, label,
1280 [value](
auto) {
return value; });
1288template <std::
size_t N>
1289void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, label_t label, value_t value)
1291 insertOrAssignImpl<N, true>(semantics, label, [value](
auto) {
return value; });
1294template <std::size_t N,
class InputIt,
1295 typename = std::enable_if_t<std::is_base_of_v<
1296 std::input_iterator_tag,
1297 typename std::iterator_traits<InputIt>::iterator_category>>>
1298void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, InputIt first, InputIt last)
1300 insertOrAssignImpl<N, true>(semantics, first, last);
1304template <std::size_t N,
class UnaryFunction,
1305 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1306void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, label_t label,
1309 insertOrAssignImpl<N, true>(semantics, label, f);
1313template <std::size_t N,
class InputIt,
class UnaryFunction,
1314 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1315 typename = std::enable_if_t<std::is_base_of_v<
1316 std::input_iterator_tag,
1317 typename std::iterator_traits<InputIt>::iterator_category>>>
1318void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, InputIt first, InputIt last,
1321 insertOrAssignImpl<N, true>(semantics, first, last, f);
1325template <std::
size_t N>
1326std::pair<iterator, bool> insertOrAssign(std::unique_ptr<Semantic[]>& semantics,
1327 offset_t index, label_t label, value_t value)
1329 return insertOrAssignImpl<N, true>(semantics, index, label,
1330 [value](
auto) {
return value; });
1333template <std::size_t N,
class InputIt,
1334 typename = std::enable_if_t<std::is_base_of_v<
1335 std::input_iterator_tag,
1336 typename std::iterator_traits<InputIt>::iterator_category>>>
1337void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, offset_t index, InputIt first,
1340 insertOrAssignImpl<N, true>(semantics, index, first, last);
1343template <std::
size_t N>
1344std::pair<iterator, bool> insertOrAssign(std::unique_ptr<Semantic[]>& semantics,
1345 offset_t index, const_iterator hint,
1346 label_t label, value_t value)
1348 return insertOrAssignImpl<N, true>(semantics, index, hint, label,
1349 [value](
auto) {
return value; });
1352template <std::size_t N,
class UnaryFunction,
1353 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1354std::pair<iterator, bool> insertOrAssign(std::unique_ptr<Semantic[]>& semantics,
1355 offset_t index, label_t label, UnaryFunction f)
1357 return insertOrAssignImpl<N, true>(semantics, index, label, f);
1360template <std::size_t N,
class InputIt,
class UnaryFunction,
1361 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1362 typename = std::enable_if_t<std::is_base_of_v<
1363 std::input_iterator_tag,
1364 typename std::iterator_traits<InputIt>::iterator_category>>>
1365void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, offset_t index, InputIt first,
1366 InputIt last, UnaryFunction f)
1368 insertOrAssignImpl<N, true>(semantics, index, first, last, f);
1378template <std::size_t N,
class UnaryFunction,
1379 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1380void assign(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1381 SemanticRangeSet
const& ranges, UnaryFunction f)
1383 auto first = begin<N>(semantics, index);
1384 auto last = end<N>(semantics, index);
1385 for (
auto range : ranges) {
1386 if (first == last) {
1390 first = lower_bound(first, last, range.lower());
1391 auto upper = upper_bound(first, last, range.upper());
1392 for (; first != upper; ++first) {
1393 first->value = f(*first);
1398template <std::
size_t N>
1399void assign(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1400 SemanticRangeSet
const& ranges, value_t value)
1402 assign<N>(semantics, index, ranges, [value](
auto) {
return value; });
1405template <std::size_t N,
class InputIt,
class UnaryPredicate,
class UnaryFunction,
1406 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1407 class = std::enable_if_t<
std::is_invocable<UnaryPredicate, Semantic>::value>,
1408 typename = std::enable_if_t<std::is_base_of_v<
1409 std::input_iterator_tag,
1410 typename std::iterator_traits<InputIt>::iterator_category>>>
1411void assign(InputIt first, InputIt last, UnaryPredicate p, UnaryFunction f)
1413 for (
auto it = first; it != last; ++it) {
1420template <std::size_t N,
class UnaryPredicate,
class UnaryFunction,
1421 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1422 class = std::enable_if_t<
std::is_invocable<UnaryPredicate, Semantic>::value>>
1423void assign(std::unique_ptr<Semantic[]>& semantics, offset_t index, UnaryPredicate p,
1426 assign<N>(begin<N>(semantics, index), end<N>(semantics, index), p, f);
1431template <std::size_t N,
class UnaryFunction,
1432 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>>
1433void assign(std::unique_ptr<Semantic[]>& semantics, SemanticRangeSet
const& ranges,
1436 for (offset_t i = 0; N != i; ++i) {
1437 assign<N>(semantics, i, ranges, f);
1441template <std::
size_t N>
1442void assign(std::unique_ptr<Semantic[]>& semantics, SemanticRangeSet
const& ranges,
1445 for (offset_t i = 0; N != i; ++i) {
1446 assign<N>(semantics, i, ranges, value);
1450template <std::size_t N,
class UnaryPredicate,
class UnaryFunction,
1451 class = std::enable_if_t<std::is_invocable<UnaryFunction, Semantic>::value>,
1452 class = std::enable_if_t<
std::is_invocable<UnaryPredicate, Semantic>::value>>
1453void assign(std::unique_ptr<Semantic[]>& semantics, UnaryPredicate p, UnaryFunction f)
1455 assign<N>(begin<N>(semantics), end<N>(semantics), p, f);
1463template <std::
size_t N>
1464size_type eraseImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index, label_t label)
1466 auto first = begin<N>(semantics, index);
1467 auto last = end<N>(semantics, index);
1469 first = lower_bound(first, last, label);
1471 if (first == last || first->label != label) {
1475 std::move(first + 1, last, first);
1481template <std::
size_t N>
1482size_type eraseImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index,
1483 SemanticRangeSet ranges)
1485 auto first = begin<N>(semantics, index);
1486 auto last = end<N>(semantics, index);
1489 for (
auto range : ranges) {
1490 if (first == last) {
1494 first = lower_bound(first, last, range.lower());
1495 auto upper = upper_bound(first, last, range.upper());
1497 if (first != upper) {
1498 num +=
static_cast<size_type
>(std::distance(first, upper));
1499 last = std::move(upper, last, first);
1511template <std::
size_t N>
1512[[nodiscard]] offset_t index(std::unique_ptr<Semantic[]>
const& semantics,
1517 auto s = sizes<N>(semantics);
1518 auto dist = std::distance(cbegin<N>(semantics), it);
1520 for (
auto offset = s[0]; (N != i && offset <= static_cast<offset_t>(dist)) || s[i] == 0;
1533template <std::
size_t N>
1534iterator erase(std::unique_ptr<Semantic[]>& semantics, const_iterator first,
1535 const_iterator last)
1537 auto first_index = index<N>(semantics, first);
1538 auto last_index = index<N>(semantics, last);
1540 if (first == last || cend<N>(semantics) == first ||
1541 cend<N>(semantics, first_index) == first) {
1542 return end<N>(semantics);
1543 }
else if (cbegin<N>(semantics) == first && cend<N>(semantics) == last) {
1544 clear<N>(semantics);
1545 return end<N>(semantics);
1548 auto s = sizes<N>(semantics);
1550 std::size_t r_offset = offset<N>(semantics, first_index);
1552 if (first_index == last_index) {
1553 s[first_index] -=
static_cast<size_type
>(std::distance(first, last));
1554 if (0 != s[first_index] && cend<N>(semantics, first_index) != last) {
1555 r_offset = std::distance(cbegin<N>(semantics), first);
1556 auto beg = begin<N>(semantics) + std::distance(cbegin<N>(semantics), last);
1557 auto dst = begin<N>(semantics) + std::distance(cbegin<N>(semantics), first);
1558 std::move(beg, end<N>(semantics, first_index), dst);
1562 r_offset = std::distance(begin<N>(semantics),
1563 begin<N>(semantics, first_index) + s[first_index]);
1568 static_cast<size_type
>(std::distance(first, cend<N>(semantics, first_index)));
1570 r_offset += s[first_index];
1573 for (; ++first_index != last_index;) {
1578 auto dist = std::distance(cbegin<N>(semantics, last_index), last);
1579 s[last_index] -=
static_cast<size_type
>(dist);
1580 if (0 != dist && 0 != s[last_index]) {
1581 auto beg = begin<N>(semantics) + std::distance(cbegin<N>(semantics), last);
1583 std::move(beg, end<N>(semantics, last_index), begin<N>(semantics, last_index));
1584 r_offset += std::distance(begin<N>(semantics, last_index), l);
1588 resize<N>(semantics, s);
1590 return begin<N>(semantics) + r_offset;
1593template <std::
size_t N>
1594size_type erase(std::unique_ptr<Semantic[]>& semantics, label_t label)
1596 if (empty<N>(semantics)) {
1600 auto s = sizes<N>(semantics);
1602 for (offset_t i = 0; N != i; ++i) {
1603 auto t = eraseImpl<N>(semantics, i, label);
1608 resize<N>(semantics, s);
1613template <std::
size_t N>
1614size_type erase(std::unique_ptr<Semantic[]>& semantics, SemanticRangeSet
const& ranges)
1616 if (ranges.empty() || empty<N>(semantics)) {
1620 auto s = sizes<N>(semantics);
1622 for (offset_t i = 0; N != i; ++i) {
1623 auto t = eraseImpl<N>(semantics, i, ranges);
1628 resize<N>(semantics, s);
1633template <std::
size_t N>
1634size_type erase(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1637 auto s = eraseImpl<N>(semantics, index, label);
1638 resize<N>(semantics, index, size<N>(semantics, index) - s);
1642template <std::
size_t N>
1643size_type erase(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1644 SemanticRangeSet
const& ranges)
1646 if (ranges.empty() || empty<N>(semantics, index)) {
1650 auto s = eraseImpl<N>(semantics, index, ranges);
1651 resize<N>(semantics, index, size<N>(semantics, index) - s);
1660template <std::size_t N,
class UnaryPredicate,
1661 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
1662size_type eraseIfImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index,
1665 auto first = begin<N>(semantics, index);
1666 auto last = end<N>(semantics, index);
1668 first = std::find_if(first, last, p);
1670 if (first == last) {
1675 for (
auto it = first; ++it != last;) {
1679 *first++ = std::move(*it);
1686template <std::size_t N,
class UnaryPredicate,
1687 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
1688size_type eraseIfImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index,
1689 SemanticRangeSet ranges, UnaryPredicate p)
1691 auto first = begin<N>(semantics, index);
1692 auto last = end<N>(semantics, index);
1695 for (
auto range : ranges) {
1696 if (first == last) {
1700 first = lower_bound(first, last, range.lower());
1701 auto upper = upper_bound(first, last, range.upper());
1703 first = std::find_if(first, upper, p);
1705 if (first != upper) {
1707 for (
auto it = first; ++it != upper;) {
1711 *first++ = std::move(*it);
1715 if (first != upper) {
1716 last = std::move(upper, last, first);
1728template <std::size_t N,
class UnaryPredicate,
1729 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
1730size_type eraseIf(std::unique_ptr<Semantic[]>& semantics, UnaryPredicate p)
1732 if (empty<N>(semantics)) {
1736 auto s = sizes<N>(semantics);
1738 for (offset_t i = 0; N != i; ++i) {
1739 auto t = eraseIfImpl<N>(semantics, i, p);
1744 resize<N>(semantics, s);
1749template <std::size_t N,
class UnaryPredicate,
1750 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
1751size_type eraseIf(std::unique_ptr<Semantic[]>& semantics, SemanticRangeSet
const& ranges,
1754 if (ranges.empty() || empty<N>(semantics)) {
1758 auto s = sizes<N>(semantics);
1760 for (offset_t i = 0; N != i; ++i) {
1761 auto t = eraseIfImpl<N>(semantics, i, ranges, p);
1766 resize<N>(semantics, s);
1771template <std::size_t N,
class UnaryPredicate,
1772 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
1773size_type eraseIf(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1776 auto s = eraseIfImpl<N>(semantics, index, p);
1777 resize<N>(semantics, index, size<N>(semantics, index) - s);
1781template <std::size_t N,
class UnaryPredicate,
1782 class = std::enable_if_t<std::is_invocable<UnaryPredicate, Semantic>::value>>
1783size_type eraseIf(std::unique_ptr<Semantic[]>& semantics, offset_t
const index,
1784 SemanticRangeSet
const& ranges, UnaryPredicate p)
1786 if (ranges.empty() || empty<N>(semantics, index)) {
1790 auto s = eraseIfImpl<N>(semantics, index, ranges, p);
1791 resize<N>(semantics, index, size<N>(semantics, index) - s);
1811template <std::
size_t N>
1812std::string toString(std::unique_ptr<Semantic[]>
const& semantics, offset_t index)
1814 std::ostringstream result;
1821 auto b = begin<N>(semantics, index);
1822 auto e = end<N>(semantics, index);
1825 for (
auto it =
b; it != e; ++it) {
1828 if ((it + 1) != e) {
1834 return result.str();
1851template <std::
size_t N>
1852std::string toString(std::unique_ptr<Semantic[]>
const& semantics)
1858 std::ostringstream result;
1862 auto s = sizes<N>(semantics);
1863 for (size_type i = 0; i < s.size(); ++i) {
1864 result << toString<N>(semantics,
static_cast<offset_t
>(i));
1865 if (i < s.size() - 1) {
1871 return result.str();
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
constexpr bool contains(A const &a, B const &b)
Checks if a shape contains another shape.
constexpr T sum(Vec< Dim, T > const &v) noexcept
Computes the sum of all elements in a vector.