UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
semantic_util.hpp
1#ifndef UFO_MAP_SEMANTIC_UTIL_HPP
2#define UFO_MAP_SEMANTIC_UTIL_HPP
3
4#include <algorithm>
5#if __cplusplus >= 202002L
6#include <bit>
7#endif
8#include <cassert>
9#include <cstddef>
10#include <cstring>
11#include <iterator>
12#include <memory>
13#include <optional>
14#include <sstream>
15#include <ufo/map/semantic/semantic.hpp>
16#include <ufo/map/types.hpp>
17
18namespace ufo::semantic
19{
20
21using size_type = label_t;
22using difference_type = std::ptrdiff_t;
23using reference = Semantic&; // TODO: Make label const
24using const_reference = Semantic const&;
25using pointer = Semantic*;
26using const_pointer = Semantic const*;
27using iterator = Semantic*; // TODO: Make label const
28using const_iterator = Semantic const*;
29using reverse_iterator = std::reverse_iterator<iterator>;
30using const_reverse_iterator = std::reverse_iterator<const_iterator>;
31
32//
33// Clear
34//
35
36template <std::size_t N>
37void clear(std::unique_ptr<Semantic[]>& semantics) noexcept
38{
39 semantics.reset();
40}
41
42//
43// Empty
44//
45
46template <std::size_t N>
47[[nodiscard]] bool empty(std::unique_ptr<Semantic[]> const& semantics) noexcept
48{
49 return nullptr == semantics;
50}
51
52//
53// Size
54//
55
56template <std::size_t N>
57[[nodiscard]] size_type size(std::unique_ptr<Semantic[]> const& semantics,
58 offset_t const index)
59{
60 // TODO: ignore 2 msb that are used for change detection
61 // return 0 == size<N>(semantics, index)
62
63 // even index stored in label
64 // odd index stored in value
65
66 // this gives a compiler warning in release mode, therefore memcpy
67 // dereferencing type-punned pointer will break strict-aliasing rules
68 // [-Werror=strict-aliasing] semantics[index / 2].value = reinterpret_cast<value_t
69 // const&>(size);
70 // return empty<N>(semantics) ? 0
71 // : (index % 2 ? reinterpret_cast<label_t const&>(
72 // semantics[index / 2].value) // odd
73 // index
74 // : semantics[index / 2].label); // even
75 // index
76
77 if (empty<N>(semantics)) {
78 return 0;
79 } else {
80 if (index % 2) {
81 // std::size_t size;
82 // std::memcpy(&size, &semantics[index / 2].value, sizeof(value_t));
83 // size = reinterpret_cast<label_t const&>(semantics[index / 2].value);
84 // return size;
85 // return std::bit_cast<label_t>(semantics[index / 2].value);
86 label_t dst;
87 std::memcpy(&dst, &semantics[index / 2].value, sizeof(label_t));
88 return dst;
89 } else {
90 return semantics[index / 2].label;
91 }
92 }
93}
94
95template <std::size_t N>
96[[nodiscard]] std::array<size_type, N> sizes(std::unique_ptr<Semantic[]> const& semantics)
97{
98 if (empty<N>(semantics)) {
99 return std::array<size_type, N>{};
100 }
101
102 // static constexpr std::size_t N_H = 1 + (N - 1) / 2;
103
104 std::array<size_type, N> s;
105 // std::copy(semantics.get(), semantics.get() + N_H,
106 // reinterpret_cast<Semantic *>(s.data())); // FIXME stack smashing detected
107
108 for (offset_t i = 0; i < N; ++i) {
109 s[i] = size<N>(semantics, i);
110 }
111 return s;
112}
113
114template <std::size_t N>
115[[nodiscard]] size_type size(std::unique_ptr<Semantic[]> const& semantics)
116{
117 auto const s = sizes<N>(semantics);
118 return std::accumulate(std::begin(s), std::end(s), size_type(0));
119}
120
121template <std::size_t N>
122[[nodiscard]] std::size_t allocSize(std::unique_ptr<Semantic[]> const& semantics)
123{
124 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
125
126 return empty<N>(semantics) ? 0 : size<N>(semantics) + N_H;
127}
128
129//
130// Offset
131//
132
133template <std::size_t N>
134[[nodiscard]] std::size_t offset(std::unique_ptr<Semantic[]> const& semantics,
135 offset_t const index)
136{
137 auto const s = sizes<N>(semantics);
138 return std::accumulate(std::begin(s), std::begin(s) + index, std::size_t(0));
139}
140
141template <std::size_t N>
142[[nodiscard]] bool empty(std::unique_ptr<Semantic[]> const& semantics,
143 offset_t const index)
144{
145 return 0 == size<N>(semantics, index);
146}
147
148//
149// Iterators
150//
151
152template <std::size_t N>
153iterator begin(std::unique_ptr<Semantic[]> const& semantics) noexcept
154{
155 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
156
157 return empty<N>(semantics) ? nullptr : semantics.get() + N_H;
158}
159
160template <std::size_t N>
161const_iterator cbegin(std::unique_ptr<Semantic[]> const& semantics) noexcept
162{
163 return begin<N>(semantics);
164}
165
166template <std::size_t N>
167iterator end(std::unique_ptr<Semantic[]> const& semantics) noexcept
168{
169 auto const s = allocSize<N>(semantics);
170 return 0 == s ? nullptr : semantics.get() + s;
171}
172
173template <std::size_t N>
174const_iterator cend(std::unique_ptr<Semantic[]> const& semantics) noexcept
175{
176 return end<N>(semantics);
177}
178
179//
180// Index iterators
181//
182
183template <std::size_t N>
184iterator begin(std::unique_ptr<Semantic[]> const& semantics,
185 offset_t const index) noexcept
186{
187 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
188
189 return empty<N>(semantics, index) ? nullptr
190 : semantics.get() + N_H + offset<N>(semantics, index);
191}
192
193template <std::size_t N>
194const_iterator cbegin(std::unique_ptr<Semantic[]> const& semantics,
195 offset_t const index) noexcept
196{
197 return begin<N>(semantics, index);
198}
199
200template <std::size_t N>
201iterator end(std::unique_ptr<Semantic[]> const& semantics, offset_t const index) noexcept
202{
203 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
204
205 return empty<N>(semantics, index)
206 ? nullptr
207 : semantics.get() + N_H + offset<N>(semantics, index) +
208 size<N>(semantics, index);
209}
210
211template <std::size_t N>
212const_iterator cend(std::unique_ptr<Semantic[]> const& semantics,
213 offset_t const index) noexcept
214{
215 return end<N>(semantics, index);
216}
217
218//
219// Lower bound
220//
221
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)
226{
227 return std::lower_bound(first, last,
228 Semantic(label, std::numeric_limits<value_t>::lowest()));
229}
230
231template <std::size_t N>
232[[nodiscard]] iterator lower_bound(std::unique_ptr<Semantic[]> const& semantics,
233 offset_t index, label_t label)
234{
235 // return std::lower_bound(begin<N>(semantics, index), end<N>(semantics, index), label);
236 return lower_bound(begin<N>(semantics, index), end<N>(semantics, index), label);
237}
238
239//
240// Upper bound
241//
242
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)
247{
248 return std::upper_bound(first, last,
249 Semantic(label, std::numeric_limits<value_t>::max()));
250}
251
252template <std::size_t N>
253[[nodiscard]] iterator upper_bound(std::unique_ptr<Semantic[]> const& semantics,
254 offset_t index, label_t label)
255{
256 // return std::upper_bound(begin<N>(semantics, index), end<N>(semantics, index), label);
257 return upper_bound(begin<N>(semantics, index), end<N>(semantics, index), label);
258}
259
260//
261// Equal range
262//
263
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)
267{
268 return std::make_pair(lower_bound<N>(semantics, index, label),
269 upper_bound<N>(semantics, index, label));
270}
271
272//
273// Find
274//
275
276template <std::size_t N>
277[[nodiscard]] iterator find(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
278 label_t label)
279{
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);
283}
284
285// template<std::size_t N>
286// [[nodiscard]] const_iterator find(std::unique_ptr<Semantic[]> const& semantics,
287// offset_t index, label_t label)
288// {
289// auto it = lower_bound<N>(semantics, index, label);
290// return end<N>(semantics, index) != it && it->label == label ? it : end<N>(semantics,
291// index);
292// }
293
294//
295// Contains
296//
297
298template <std::size_t N>
299[[nodiscard]] bool contains(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
300 label_t label)
301{
302 return end<N>(semantics, index) != find<N>(semantics, index, label);
303}
304
305//
306// At
307//
308template <std::size_t N>
309[[nodiscard]] std::optional<Semantic> at(std::unique_ptr<Semantic[]> const& semantics,
310 offset_t index, label_t label)
311{
312 iterator it = find<N>(semantics, index, label);
313 return end<N>(semantics, index) != it ? std::optional<Semantic>(*it) : std::nullopt;
314}
315
316//
317// Value
318//
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)
322{
323 auto it = find<N>(semantics, index, label);
324 return end<N>(semantics, index) != it ? std::optional<value_t>(it->value)
325 : std::nullopt;
326}
327
328//
329// Count
330//
331template <std::size_t N>
332[[nodiscard]] size_type count(std::unique_ptr<Semantic[]> const& semantics,
333 offset_t index, label_t label)
334{
335 return contains<N>(semantics, index, label) ? 1 : 0;
336}
337
338//
339// All
340//
341
342template <std::size_t N>
343[[nodiscard]] bool all(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
344 SemanticRangeSet const& ranges)
345{
346 if (ranges.empty()) {
347 return true;
348 } else if (size<N>(semantics, index) < ranges.numValues()) {
349 return false;
350 }
351
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) {
360 return false;
361 }
362 }
363 return true;
364}
365
366template <std::size_t N>
367[[nodiscard]] bool all(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
368 SemanticRange range)
369{
370 return all<N>(semantics, index, SemanticRangeSet(range));
371}
372
373template <std::size_t N, class UnaryPredicate>
374[[nodiscard]] bool all(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
375 UnaryPredicate p)
376{
377 return std::all_of(cbegin<N>(semantics, index), cend<N>(semantics, index), p);
378}
379
380template <std::size_t N, class UnaryPredicate>
381[[nodiscard]] bool all(std::unique_ptr<Semantic[]> const& semantics, UnaryPredicate p)
382{
383 return std::all_of(cbegin<N>(semantics), cend<N>(semantics), p);
384}
385
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)
389{
390 if (ranges.empty()) {
391 return true;
392 } else if (size<N>(semantics, index) < ranges.numValues()) {
393 return false;
394 }
395
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) {
404 return false;
405 }
406 for (; lower != first; ++lower) {
407 if (!p(*lower)) {
408 return false;
409 }
410 }
411 }
412 return true;
413}
414
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)
418{
419 return all<N>(semantics, index, SemanticRangeSet(range), p);
420}
421
422//
423// Any
424//
425
426template <std::size_t N>
427[[nodiscard]] bool any(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
428 SemanticRangeSet const& ranges)
429{
430 if (ranges.empty()) {
431 return true;
432 }
433
434 if (size<N>(semantics, index) < ranges.size()) {
435 for (auto it = cbegin<N>(semantics, index), last = cend<N>(semantics, index);
436 it != last; ++it) {
437 if (ranges.contains(it->label)) {
438 return true;
439 }
440 }
441 } else {
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());
446 if (first == last) {
447 return false;
448 } else if (first->label <= range.upper()) {
449 return true;
450 }
451 }
452 }
453 return false;
454}
455
456template <std::size_t N>
457[[nodiscard]] bool any(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
458 SemanticRange range)
459{
460 return any<N>(semantics, index, SemanticRangeSet(range));
461}
462
463template <std::size_t N, class UnaryPredicate>
464[[nodiscard]] bool any(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
465 UnaryPredicate p)
466{
467 return std::any_of(cbegin<N>(semantics, index), cend<N>(semantics, index), p);
468}
469
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)
473{
474 return any<N>(semantics, index, SemanticRangeSet(range), p);
475}
476
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)
480{
481 if (ranges.empty()) {
482 return true;
483 }
484
485 if (size<N>(semantics, index) < ranges.size()) {
486 for (auto it = cbegin<N>(semantics, index), last = cend<N>(semantics, index);
487 it != last; ++it) {
488 if (ranges.contains(it->label) && p(*it)) {
489 return true;
490 }
491 }
492 } else {
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) {
498 if (p(*first)) {
499 return true;
500 }
501 }
502 if (first == last) {
503 return false;
504 }
505 }
506 }
507}
508
509//
510// None
511//
512
513template <std::size_t N>
514[[nodiscard]] bool none(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
515 SemanticRangeSet const& ranges)
516{
517 return !any<N>(semantics, index, ranges);
518}
519
520template <std::size_t N>
521[[nodiscard]] bool none(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
522 SemanticRange range)
523{
524 return none<N>(semantics, index, SemanticRangeSet(range));
525}
526
527template <std::size_t N, class UnaryPredicate>
528[[nodiscard]] bool none(std::unique_ptr<Semantic[]> const& semantics, offset_t index,
529 UnaryPredicate p)
530{
531 return std::none_of(cbegin<N>(semantics, index), cend<N>(semantics, index), p);
532}
533
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)
537{
538 return none<UnaryPredicate, N>(semantics, index, SemanticRangeSet(range), p);
539}
540
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)
544{
545 return !any<N>(semantics, index, ranges, p);
546}
547
548//
549// Resize
550//
551
560template <std::size_t N>
561void setSize(std::unique_ptr<Semantic[]> const& semantics, offset_t const index,
562 size_type const size)
563{
564 // even index stored in label
565 // odd index stored in value
566 if (index % 2) {
567 // this gives a compiler warning in release mode, therefore memcpy
568 // dereferencing type-punned pointer will break strict-aliasing rules
569 // [-Werror=strict-aliasing]
570
571 // semantics[index / 2].value = reinterpret_cast<value_t const&>(size);
572
573 // value_t v;
574 // std::memcpy(&v, &size, sizeof(value_t));
575 // semantics[index / 2].value = v;
576 // semantics[index / 2].value = std::bit_cast<value_t>(size);
577 std::memcpy(&semantics[index / 2].value, &size, sizeof(value_t));
578 } else {
579 semantics[index / 2].label = static_cast<label_t>(size);
580 }
581}
582
583template <std::size_t N>
584void resizeLazy(std::unique_ptr<Semantic[]>& semantics,
585 std::array<size_type, N> const& new_sizes)
586{
587 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
588
589 auto new_size = std::accumulate(std::begin(new_sizes), std::end(new_sizes), 0);
590 if (0 == new_size) {
591 clear<N>(semantics);
592 return;
593 }
594
595 new_size += N_H;
596
597 auto const cur_sizes = sizes<N>(semantics);
598 if (cur_sizes == new_sizes) {
599 return;
600 }
601
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)));
605
606 if (!p_new) {
607 semantics.reset(p_cur);
608 throw std::bad_alloc();
609 }
610
611 semantics.reset(p_new);
612 }
613
614 for (offset_t i = 0; N != i; ++i) {
615 setSize<N>(semantics, i, new_sizes[i]);
616 }
617}
618
619template <std::size_t N>
620void resizeLazy(std::unique_ptr<Semantic[]>& semantics, size_type const size)
621{
622 std::array<size_type, N> sizes;
623 sizes.fill(size);
624 resizeLazy<N>(semantics, sizes);
625}
626
627template <std::size_t N>
628void resizeLazy(std::unique_ptr<Semantic[]>& semantics, offset_t const index,
629 size_type const new_size)
630{
631 // FIXME: Optimize
632 std::array<size_type, N> s = sizes<N>(semantics);
633 s[index] = new_size;
634 resizeLazy<N>(semantics, s);
635}
636
637template <std::size_t N>
638void resize(std::unique_ptr<Semantic[]>& semantics,
639 std::array<size_type, N> const& new_sizes)
640{
641 static constexpr std::size_t N_H = 1 + (N - 1) / 2;
642
643 auto const new_size = std::accumulate(std::begin(new_sizes), std::end(new_sizes), N_H);
644 if (0 == new_size) {
645 clear<N>(semantics);
646 return;
647 }
648
649 auto const cur_sizes = sizes<N>(semantics);
650 if (cur_sizes == new_sizes) {
651 return;
652 }
653
654 for (int i = N - 1; 0 <= i; --i) {
655 // Reduce the indices that should be reduced
656 if (cur_sizes[i] <= new_sizes[i]) {
657 continue;
658 }
659
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]);
663 }
664
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)));
668
669 if (!p_new) {
670 semantics.reset(p_cur);
671 throw std::bad_alloc();
672 }
673
674 semantics.reset(p_new);
675 }
676
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]);
681 }
682 } else {
683 // Increase the indices that should be increased
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;
687
688 // auto last = semantics.get() + new_size;
689 for (int i = N - 1; i >= 0; --i) {
690 // auto first_i_old = begin<N>(semantics, i);
691 auto last_i_old = end<N>(semantics, static_cast<offset_t>(i));
692
693 setSize<N>(semantics, static_cast<offset_t>(i), new_sizes[i]);
694
695 // if (0 == new_sizes[i] || 0 == cur_sizes[i]) {
696 // if (0 == new_sizes[i]) {
697 if (cur_sizes[i] >= new_sizes[i]) {
698 continue;
699 }
700
701 // move if new size is bigger than old size
702
703 // auto first_i = begin<N>(semantics, i);
704 // auto last_i = end<N>(semantics, i);
705 // last = last != last_i ? std::move_backward(first_i, last_i, last) : first_i;
706
707 auto first_i = begin<N>(semantics, static_cast<offset_t>(i));
708 // auto last_i = end<N>(semantics, i);
709
710 auto start = first_i;
711
712 // if old size = 0, use start_i after new size
713 // else use end_i of old size
714 if (cur_sizes[i] == 0) {
715 start = first_i;
716 } else {
717 start = last_i_old;
718 }
719 // if (cur_sizes[i] > 0) {
720 // start = last_i_old;
721 // }
722 // cur_last = std::move_backward(start, cur_last, cur_last +
723 // (new_sizes[i]-cur_sizes[i]));
724 auto new_last = cur_last + (new_sizes[i] - cur_sizes[i]);
725 std::move_backward(start, cur_last, new_last);
726 cur_last = new_last;
727 }
728 }
729}
730
731template <std::size_t N>
732void resize(std::unique_ptr<Semantic[]>& semantics, size_type const size)
733{
734 std::array<size_type, N> sizes;
735 sizes.fill(size);
736 resize<N>(semantics, sizes);
737}
738
739template <std::size_t N>
740void resize(std::unique_ptr<Semantic[]>& semantics, offset_t const index,
741 size_type const new_size)
742{
743 // FIXME: Optimize
744 std::array<size_type, N> s = sizes<N>(semantics);
745 s[index] = new_size;
746 resize<N>(semantics, s);
747}
748
749template <std::size_t N>
750void clear(std::unique_ptr<Semantic[]>& semantics, offset_t const index)
751{
752 resize<N>(semantics, index, 0);
753}
754
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)
761{
762 size_type num = 0;
763
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) {
767 label_t label;
768 if constexpr (std::is_same_v<Semantic,
769 typename std::iterator_traits<InputIt>::value_type>) {
770 label = first->label;
771 } else {
772 label = *first;
773 }
774 first_index = lower_bound(first_index, last_index, label);
775 if (first_index != last_index && first_index->label == label) {
776 ++num;
777 }
778 }
779
780 return num;
781}
782
783//
784// Insert or assign helper
785//
786
787// just insert, no allocation
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,
805 InputIt last)
806{
807 if (0 == new_size) {
808 return;
809 } else if (0 == cur_size) {
810 std::copy(first, last, begin<N>(semantics, index));
811 return;
812 }
813
814 if constexpr (!Assign) {
815 if (cur_size == new_size) {
816 return;
817 }
818 }
819
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;
828 continue;
829 }
830 }
831 if ((last_index - 1)->label < (last - 1)->label) {
832 *(--cur) = *(--last);
833 if constexpr (!Assign) {
834 ++cur_size;
835 // FIXME: Does this actually improve performance?
836 if (cur_size == new_size) {
837 return;
838 }
839 }
840 } else {
841 // FIXME: Can this be a move? What happens if it is the same?
842 *(--cur) = *(--last_index);
843 }
844 }
845
846 // Copy the remaining to the beginning
847 std::copy(first, last, first_index);
848}
849
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)
870{
871 if (0 == new_size) {
872 return;
873 } else if (0 == cur_size) {
874 for (auto it = begin<N>(semantics, index); first != last; ++it, ++first) {
875 it->label = *first;
876 it->value = f(Semantic(*first));
877 }
878 return;
879 }
880
881 if constexpr (!Assign) {
882 if (cur_size == new_size) {
883 return;
884 }
885 }
886
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);
895 --last;
896 continue;
897 }
898 }
899 if ((last_index - 1)->label < *(last - 1)) {
900 --cur;
901 cur->label = *(--last);
902 cur->value = f(Semantic(cur->label));
903 if constexpr (!Assign) {
904 ++cur_size;
905 // FIXME: Does this actually improve performance?
906 if (cur_size == new_size) {
907 return;
908 }
909 }
910 } else {
911 // FIXME: Can this be a move? What happens if it is the same?
912 *(--cur) = *(--last_index);
913 }
914 }
915
916 // Copy the remaining to the beginning
917 for (auto it = begin<N>(semantics, index); first != last; ++it, ++first) {
918 it->label = *first;
919 it->value = f(Semantic(*first));
920 }
921}
922
923// Allocates space for the element and inserts the element at the correct position
924// Assign: if true value of semantic is overwritten if label is already present,
925// if false nothing happens
926// UnaryFunction: function that is applied to Semantic with label
927//
928// return iterator to element and a bool if insertion happened
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,
933 UnaryFunction f)
934{
935 if (empty<N>(semantics, index)) {
936 resize<N>(semantics, index, 1);
937 auto it = begin<N>(semantics, index);
938 it->label = label;
939 it->value = f(Semantic(label));
940 return {it, true};
941 }
942
943 auto it = lower_bound<N>(semantics, index, label);
944 if (end<N>(semantics, index) != it && it->label == label) {
945 // Label already exists
946 if constexpr (Assign) {
947 it->value = f(*it);
948 }
949 return {it, false};
950 }
951
952 // insert at right position
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);
958 it->label = label;
959 it->value = f(Semantic(label));
960 return {it, true};
961}
962
963// allocate the space and insert/assign to all nodes
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,
967 UnaryFunction f)
968{
969 if (empty<N>(semantics)) {
970 std::array<size_type, N> s;
971 s.fill(1);
972 resize<N>(semantics, s);
973 std::fill(begin<N>(semantics), end<N>(semantics),
974 Semantic(label, f(Semantic(label))));
975 return;
976 }
977
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) {
983 // Label already exists
984 if constexpr (Assign) {
985 it->value = f(*it);
986 }
987 dist[index] = -1; // don't need to insert this label
988 } else {
989 ++new_sizes[index];
990 dist[index] = std::distance(begin<N>(semantics, index), it);
991 }
992 }
993
994 // if (0 == std::accumulate(std::begin(dist), std::end(dist), 0)) {
995 // return;
996 // }
997
998 resize<N>(semantics, new_sizes);
999
1000 for (offset_t index = 0; N != index; ++index) {
1001 if (dist[index] < 0) {
1002 continue; // don't need to insert this label, was already assigned
1003 }
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);
1007 it->label = label;
1008 it->value = f(Semantic(label));
1009 }
1010}
1011
1012// allocate the space and insert/assign to index, iterators
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)
1019{
1020 std::vector vec(first, last);
1021
1022 std::sort(std::begin(vec), std::end(vec));
1023
1024 // Erase duplicate labels, saving highest value for each label
1025 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1026 [](auto a, auto b) { return a.label == b.label; });
1027
1028 auto f = r_last.base();
1029 auto l = std::end(vec);
1030 auto s = static_cast<size_type>(std::distance(f, l));
1031
1032 if (empty<N>(semantics, index)) {
1033 // Optimized insert
1034 resize<N>(semantics, index, s);
1035 std::copy(f, l, begin<N>(semantics, index));
1036 } else {
1037 auto cur_size = size<N>(semantics, index);
1038 auto new_size = cur_size + s - numAlreadyExists<N>(semantics, index, f, l);
1039
1040 resize<N>(semantics, index, new_size);
1041
1042 // Do insert where memory already has been allocated
1043 insertOrAssignImpl<N, Assign>(semantics, index, cur_size, new_size, f, l);
1044 }
1045}
1046
1047// allocate the space and insert/assign to all nodes, iterators
1048// allocate all space for all nodes at the same time, then insert
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,
1054 InputIt last)
1055{
1056 std::vector vec(first, last);
1057
1058 std::sort(std::begin(vec), std::end(vec));
1059
1060 // Erase duplicate labels, saving highest value for each label
1061 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1062 [](auto a, auto b) { return a.label == b.label; });
1063
1064 auto f = r_last.base();
1065 auto l = std::end(vec);
1066 auto s = static_cast<size_type>(std::distance(f, l));
1067
1068 std::array<size_type, N> new_sizes;
1069 new_sizes.fill(s);
1070
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));
1075 }
1076 } else {
1077 std::array<size_type, N> cur_sizes = sizes<N>(semantics);
1078 for (offset_t index = 0; N != index; ++index) {
1079 new_sizes[index] =
1080 s + cur_sizes[index] - numAlreadyExists<N>(semantics, index, f, l);
1081 }
1082
1083 resize<N>(semantics, new_sizes);
1084
1085 // Do insert where memory already has been allocated
1086 for (offset_t index = 0; N != index; ++index) {
1087 insertOrAssignImpl<N, Assign>(semantics, index, cur_sizes[index], new_sizes[index],
1088 f, l);
1089 }
1090 }
1091}
1092
1093// allocate and insert/assign with hint
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)
1099{
1100 if (empty<N>(semantics, index)) {
1101 resize<N>(semantics, index, 1);
1102 auto it = begin<N>(semantics, index);
1103 it->label = label;
1104 it->value = f(Semantic(label));
1105 return {it, true};
1106 }
1107
1108 auto first_index = begin<N>(semantics, index);
1109 auto last_index = end<N>(semantics, index);
1110
1111 auto first =
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);
1115
1116 auto i = std::distance<const_iterator>(first_index, hint);
1117
1118 if (last_index != hint && hint->label == label) {
1119 // Label already exists
1120 auto it = first_index + i;
1121 if constexpr (Assign) {
1122 it->value = f(*it);
1123 }
1124 return {it, false};
1125 }
1126
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);
1131 it->label = label;
1132 it->value = f(Semantic(label));
1133 return {it, true};
1134}
1135
1136// InputIt to label_t
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)
1144{
1145 std::vector vec(first, last);
1146
1147 std::sort(std::begin(vec), std::end(vec));
1148
1149 // Erase duplicate labels, saving highest value for each label
1150 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1151 [](auto a, auto b) { return a == b; });
1152
1153 auto f = r_last.base();
1154 auto l = std::end(vec);
1155 auto s = std::distance(f, l);
1156
1157 if (empty<N>(semantics, index)) {
1158 // Optimized insert
1159 resize<N>(semantics, index, s);
1160 for (auto it = begin<N>(semantics, index); f != l; ++it, ++f) {
1161 it->label = *f;
1162 it->value = fun(Semantic(*f));
1163 }
1164 } else {
1165 auto cur_size = size<N>(semantics, index);
1166 auto new_size = cur_size + s - numAlreadyExists<N>(semantics, index, f, l);
1167
1168 resize<N>(semantics, index, new_size);
1169
1170 // Do insert where memory already has been allocated
1171 insertOrAssignImpl<N, Assign>(semantics, index, cur_size, new_size, f, l, fun);
1172 }
1173}
1174
1175// TODO: enable if InputIt is iterator, otherwise this function is called instead of
1176// insertOrAssign(index, label, f)
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)
1184{
1185 std::vector vec(first, last);
1186
1187 std::sort(std::begin(vec), std::end(vec));
1188
1189 // Erase duplicate labels
1190 auto r_last = std::unique(std::rbegin(vec), std::rend(vec),
1191 [](auto a, auto b) { return a == b; });
1192
1193 auto f = r_last.base();
1194 auto l = std::end(vec);
1195 auto s = std::distance(f, l);
1196
1197 std::array<size_type, N> new_sizes;
1198 new_sizes.fill(s);
1199
1200 if (empty<N>(semantics)) {
1201 // Optimized insert
1202 std::vector<Semantic> sem;
1203 sem.reserve(s);
1204 for (; f != l; ++first) {
1205 sem.emplace_back(*f, fun(Semantic(*f)));
1206 }
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));
1210 }
1211 } else {
1212 // Calculate how many elements already exists per index
1213 std::array<size_type, N> cur_sizes = sizes<N>(semantics);
1214
1215 for (offset_t index = 0; N != index; ++index) {
1216 new_sizes[index] =
1217 cur_sizes[index] + s - numAlreadyExists<N>(semantics, index, f, l);
1218 // new_sizes[index] -= numAlreadyExists<N>(semantics, index, f, l);
1219 }
1220
1221 resize<N>(semantics, new_sizes);
1222
1223 // Do insert where memory already has been allocated
1224 for (offset_t index = 0; N != index; ++index) {
1225 insertOrAssignImpl<N, Assign>(semantics, index, cur_sizes[index], new_sizes[index],
1226 f, l, fun);
1227 }
1228 }
1229}
1230
1231//
1232// Insert
1233//
1234
1235// all
1236template <std::size_t N>
1237void insert(std::unique_ptr<Semantic[]>& semantics, label_t label, value_t value)
1238{
1239 insertOrAssignImpl<N, false>(semantics, label, [value](auto) { return value; });
1240}
1241
1242// template<std::size_t N>
1243// void insert(std::unique_ptr<Semantic[]> & semantics, Semantic semantic) { return
1244// insert<N>(semantic.label, semantic.value); }
1245
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)
1251{
1252 insertOrAssignImpl<N, false>(semantics, first, last);
1253}
1254
1255// index
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)
1259{
1260 return insertOrAssignImpl<N, false>(semantics, index, label,
1261 [value](auto) { return value; });
1262}
1263
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,
1269 InputIt last)
1270{
1271 insertOrAssignImpl<N, false>(semantics, index, first, last);
1272}
1273
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,
1277 value_t value)
1278{
1279 return insertOrAssignImpl<N, false>(semantics, index, hint, label,
1280 [value](auto) { return value; });
1281}
1282
1283//
1284// InsertOrAssign
1285//
1286
1287// all
1288template <std::size_t N>
1289void insertOrAssign(std::unique_ptr<Semantic[]>& semantics, label_t label, value_t value)
1290{
1291 insertOrAssignImpl<N, true>(semantics, label, [value](auto) { return value; });
1292}
1293
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)
1299{
1300 insertOrAssignImpl<N, true>(semantics, first, last);
1301}
1302
1303// InputIt to sematic
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,
1307 UnaryFunction f)
1308{
1309 insertOrAssignImpl<N, true>(semantics, label, f);
1310}
1311
1312// InputIt to label
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,
1319 UnaryFunction f)
1320{
1321 insertOrAssignImpl<N, true>(semantics, first, last, f);
1322}
1323
1324// index
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)
1328{
1329 return insertOrAssignImpl<N, true>(semantics, index, label,
1330 [value](auto) { return value; });
1331}
1332
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,
1338 InputIt last)
1339{
1340 insertOrAssignImpl<N, true>(semantics, index, first, last);
1341}
1342
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)
1347{
1348 return insertOrAssignImpl<N, true>(semantics, index, hint, label,
1349 [value](auto) { return value; });
1350}
1351
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)
1356{
1357 return insertOrAssignImpl<N, true>(semantics, index, label, f);
1358}
1359
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)
1367{
1368 insertOrAssignImpl<N, true>(semantics, index, first, last, f);
1369}
1370
1371//
1372// Assign
1373//
1374
1375// index
1376// apply function f to each label of node with index which occurs in the SemanticRangeSet
1377// ranges
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)
1382{
1383 auto first = begin<N>(semantics, index);
1384 auto last = end<N>(semantics, index);
1385 for (auto range : ranges) {
1386 if (first == last) {
1387 break;
1388 }
1389
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);
1394 }
1395 }
1396}
1397
1398template <std::size_t N>
1399void assign(std::unique_ptr<Semantic[]>& semantics, offset_t const index,
1400 SemanticRangeSet const& ranges, value_t value)
1401{
1402 assign<N>(semantics, index, ranges, [value](auto) { return value; });
1403}
1404
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)
1412{
1413 for (auto it = first; it != last; ++it) {
1414 if (p(*it)) {
1415 it->value = f(*it);
1416 }
1417 }
1418}
1419
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,
1424 UnaryFunction f)
1425{
1426 assign<N>(begin<N>(semantics, index), end<N>(semantics, index), p, f);
1427}
1428
1429// all
1430// apply function f to each label of all nodes which occurs in the SemanticRangeSet
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,
1434 UnaryFunction f)
1435{
1436 for (offset_t i = 0; N != i; ++i) {
1437 assign<N>(semantics, i, ranges, f);
1438 }
1439}
1440
1441template <std::size_t N>
1442void assign(std::unique_ptr<Semantic[]>& semantics, SemanticRangeSet const& ranges,
1443 value_t value)
1444{
1445 for (offset_t i = 0; N != i; ++i) {
1446 assign<N>(semantics, i, ranges, value);
1447 }
1448}
1449
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)
1454{
1455 assign<N>(begin<N>(semantics), end<N>(semantics), p, f);
1456}
1457
1458//
1459// Erase Impl
1460//
1461
1462// just removes, no resize
1463template <std::size_t N>
1464size_type eraseImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index, label_t label)
1465{
1466 auto first = begin<N>(semantics, index);
1467 auto last = end<N>(semantics, index);
1468
1469 first = lower_bound(first, last, label);
1470
1471 if (first == last || first->label != label) {
1472 return 0;
1473 }
1474
1475 std::move(first + 1, last, first);
1476
1477 return 1;
1478}
1479
1480// just removes, no resize
1481template <std::size_t N>
1482size_type eraseImpl(std::unique_ptr<Semantic[]>& semantics, offset_t index,
1483 SemanticRangeSet ranges)
1484{
1485 auto first = begin<N>(semantics, index);
1486 auto last = end<N>(semantics, index);
1487
1488 size_type num = 0;
1489 for (auto range : ranges) {
1490 if (first == last) {
1491 break;
1492 }
1493
1494 first = lower_bound(first, last, range.lower());
1495 auto upper = upper_bound(first, last, range.upper());
1496
1497 if (first != upper) {
1498 num += static_cast<size_type>(std::distance(first, upper));
1499 last = std::move(upper, last, first);
1500 }
1501 }
1502
1503 return num;
1504}
1505
1506//
1507// Index
1508//
1509
1510// get index to which it belongs
1511template <std::size_t N>
1512[[nodiscard]] offset_t index(std::unique_ptr<Semantic[]> const& semantics,
1513 const_iterator it)
1514{
1515 assert(it);
1516
1517 auto s = sizes<N>(semantics);
1518 auto dist = std::distance(cbegin<N>(semantics), it);
1519 offset_t i = 0;
1520 for (auto offset = s[0]; (N != i && offset <= static_cast<offset_t>(dist)) || s[i] == 0;
1521 ++i) {
1522 offset += s[i];
1523 }
1524 return i;
1525}
1526
1527//
1528// Erase
1529//
1530
1531// Removes the elements in the range [first; last)
1532// return Iterator following the last removed element, end() if nothing removed?
1533template <std::size_t N>
1534iterator erase(std::unique_ptr<Semantic[]>& semantics, const_iterator first,
1535 const_iterator last)
1536{
1537 auto first_index = index<N>(semantics, first);
1538 auto last_index = index<N>(semantics, last);
1539
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);
1546 }
1547
1548 auto s = sizes<N>(semantics);
1549
1550 std::size_t r_offset = offset<N>(semantics, first_index);
1551
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);
1559 // r_offset = std::distance(begin<N>(semantics), l);
1560 } else {
1561 // r_offset = std::distance(begin<N>(semantics), begin<N>(semantics, first_index));
1562 r_offset = std::distance(begin<N>(semantics),
1563 begin<N>(semantics, first_index) + s[first_index]);
1564 }
1565 } else {
1566 // Handle first
1567 s[first_index] -=
1568 static_cast<size_type>(std::distance(first, cend<N>(semantics, first_index)));
1569
1570 r_offset += s[first_index];
1571
1572 // Handle middle
1573 for (; ++first_index != last_index;) {
1574 s[first_index] = 0;
1575 }
1576
1577 // Handle last
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);
1582 auto l =
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);
1585 }
1586 }
1587
1588 resize<N>(semantics, s);
1589
1590 return begin<N>(semantics) + r_offset;
1591}
1592
1593template <std::size_t N>
1594size_type erase(std::unique_ptr<Semantic[]>& semantics, label_t label)
1595{
1596 if (empty<N>(semantics)) {
1597 return 0;
1598 }
1599
1600 auto s = sizes<N>(semantics);
1601 size_type sum = 0;
1602 for (offset_t i = 0; N != i; ++i) {
1603 auto t = eraseImpl<N>(semantics, i, label);
1604 s[i] -= t;
1605 sum += t;
1606 }
1607
1608 resize<N>(semantics, s);
1609
1610 return sum;
1611}
1612
1613template <std::size_t N>
1614size_type erase(std::unique_ptr<Semantic[]>& semantics, SemanticRangeSet const& ranges)
1615{
1616 if (ranges.empty() || empty<N>(semantics)) {
1617 return 0;
1618 }
1619
1620 auto s = sizes<N>(semantics);
1621 size_type sum = 0;
1622 for (offset_t i = 0; N != i; ++i) {
1623 auto t = eraseImpl<N>(semantics, i, ranges);
1624 s[i] -= t;
1625 sum += t;
1626 }
1627
1628 resize<N>(semantics, s);
1629
1630 return sum;
1631}
1632
1633template <std::size_t N>
1634size_type erase(std::unique_ptr<Semantic[]>& semantics, offset_t const index,
1635 label_t label)
1636{
1637 auto s = eraseImpl<N>(semantics, index, label);
1638 resize<N>(semantics, index, size<N>(semantics, index) - s);
1639 return s;
1640}
1641
1642template <std::size_t N>
1643size_type erase(std::unique_ptr<Semantic[]>& semantics, offset_t const index,
1644 SemanticRangeSet const& ranges)
1645{
1646 if (ranges.empty() || empty<N>(semantics, index)) {
1647 return 0;
1648 }
1649
1650 auto s = eraseImpl<N>(semantics, index, ranges);
1651 resize<N>(semantics, index, size<N>(semantics, index) - s);
1652 return s;
1653}
1654
1655//
1656// Erase if Impl
1657//
1658
1659// just removes, no resize
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,
1663 UnaryPredicate p)
1664{
1665 auto first = begin<N>(semantics, index);
1666 auto last = end<N>(semantics, index);
1667
1668 first = std::find_if(first, last, p);
1669
1670 if (first == last) {
1671 return 0;
1672 }
1673
1674 size_type num = 1;
1675 for (auto it = first; ++it != last;) {
1676 if (p(*it)) {
1677 ++num;
1678 } else {
1679 *first++ = std::move(*it);
1680 }
1681 }
1682
1683 return num;
1684}
1685
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)
1690{
1691 auto first = begin<N>(semantics, index);
1692 auto last = end<N>(semantics, index);
1693
1694 size_type num = 0;
1695 for (auto range : ranges) {
1696 if (first == last) {
1697 break;
1698 }
1699
1700 first = lower_bound(first, last, range.lower());
1701 auto upper = upper_bound(first, last, range.upper());
1702
1703 first = std::find_if(first, upper, p);
1704
1705 if (first != upper) {
1706 ++num;
1707 for (auto it = first; ++it != upper;) {
1708 if (p(*it)) {
1709 ++num;
1710 } else {
1711 *first++ = std::move(*it);
1712 }
1713 }
1714
1715 if (first != upper) {
1716 last = std::move(upper, last, first);
1717 }
1718 }
1719 }
1720
1721 return num;
1722}
1723
1724//
1725// Erase if
1726//
1727
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)
1731{
1732 if (empty<N>(semantics)) {
1733 return 0;
1734 }
1735
1736 auto s = sizes<N>(semantics);
1737 size_type sum = 0;
1738 for (offset_t i = 0; N != i; ++i) {
1739 auto t = eraseIfImpl<N>(semantics, i, p);
1740 s[i] -= t;
1741 sum += t;
1742 }
1743
1744 resize<N>(semantics, s);
1745
1746 return sum;
1747}
1748
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,
1752 UnaryPredicate p)
1753{
1754 if (ranges.empty() || empty<N>(semantics)) {
1755 return 0;
1756 }
1757
1758 auto s = sizes<N>(semantics);
1759 size_type sum = 0;
1760 for (offset_t i = 0; N != i; ++i) {
1761 auto t = eraseIfImpl<N>(semantics, i, ranges, p);
1762 s[i] -= t;
1763 sum += t;
1764 }
1765
1766 resize<N>(semantics, s);
1767
1768 return sum;
1769}
1770
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,
1774 UnaryPredicate p)
1775{
1776 auto s = eraseIfImpl<N>(semantics, index, p);
1777 resize<N>(semantics, index, size<N>(semantics, index) - s);
1778 return s;
1779}
1780
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)
1785{
1786 if (ranges.empty() || empty<N>(semantics, index)) {
1787 return 0;
1788 }
1789
1790 auto s = eraseIfImpl<N>(semantics, index, ranges, p);
1791 resize<N>(semantics, index, size<N>(semantics, index) - s);
1792 return s;
1793}
1794
1795//
1796// to string
1797//
1798
1799// template <std::size_t N>
1800// std::string toString(std::unique_ptr<Semantic[]> const& semantics, offset_t index)
1801// {
1802// std::ostringstream result;
1803
1804// for (auto it = begin<N>(semantics, index); it != end<N>(semantics, index); ++it) {
1805// result << it->label << ":" << it->value << " \n";
1806// }
1807
1808// return result.str();
1809// }
1810
1811template <std::size_t N>
1812std::string toString(std::unique_ptr<Semantic[]> const& semantics, offset_t index)
1813{
1814 std::ostringstream result;
1815 result << "{";
1816
1817 // if (semantic::empty<N>(semantics, index)) {
1818 // return {};
1819 // } else
1820 // {
1821 auto b = begin<N>(semantics, index);
1822 auto e = end<N>(semantics, index);
1823
1824 // for (auto it = begin<N>(semantics, index); it != end<N>(semantics, index); ++it) {
1825 for (auto it = b; it != e; ++it) {
1826 // result << it->label << ":" << it->value;
1827 result << *it;
1828 if ((it + 1) != e) {
1829 result << " | ";
1830 }
1831 }
1832 // }
1833 result << "}";
1834 return result.str();
1835}
1836
1837// template <std::size_t N>
1838// std::string toString(std::unique_ptr<Semantic[]> const& semantics)
1839// {
1840// std::ostringstream result;
1841// result << N << " Nodes\n";
1842
1843// auto s = sizes<N>(semantics);
1844// for (std::size_t i = 0; i < s.size(); ++i) {
1845// result << "Node " << i << ": " << s[i] << "\n";
1846// result << toString<N>(semantics, static_cast<offset_t>(i));
1847// }
1848// return result.str();
1849// }
1850
1851template <std::size_t N>
1852std::string toString(std::unique_ptr<Semantic[]> const& semantics)
1853{
1854 // if (semantic::empty<N>(semantics)) {
1855 // return {};
1856 // }
1857
1858 std::ostringstream result;
1859
1860 result << "{";
1861
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) {
1866 result << "} {";
1867 }
1868 }
1869
1870 result << "}";
1871 return result.str();
1872}
1873
1874} // namespace ufo::semantic
1875
1876#endif // UFO_MAP_SEMANTIC_UTIL_H
STL namespace.
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
Definition lab.hpp:326
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
Definition lab.hpp:310
constexpr bool contains(A const &a, B const &b)
Checks if a shape contains another shape.
Definition contains.hpp:63
constexpr T sum(Vec< Dim, T > const &v) noexcept
Computes the sum of all elements in a vector.
Definition vec.hpp:1309