27template<
typename Index_,
typename Position_>
33 Index_ root_children = 0;
37 Node(Index_
id) : id(
id) {}
44 Index_ children_start = 0;
45 Index_ children_end = 0;
50 Index_ duplicates_start = 0;
51 Index_ duplicates_end = 0;
54 std::vector<Node> nodes;
59 std::vector<Position_> starts, ends;
62 std::vector<Index_> duplicates;
74using ArrayElement =
typename std::remove_const<typename std::remove_reference<decltype(std::declval<Array_>()[0])>::type>::type;
79template<
class Container_,
typename Size_>
80void safe_resize(Container_& container, Size_ size) {
81 typedef decltype(container.size()) Csize;
82 constexpr Csize max_csize = std::numeric_limits<Csize>::max();
83 constexpr Size_ max_size = std::numeric_limits<Size_>::max();
84 if constexpr(
static_cast<typename std::make_unsigned<Size_>::type
>(max_size) >
static_cast<typename std::make_unsigned<Csize>::type
>(max_csize)) {
85 if (
static_cast<typename std::make_unsigned<Size_>::type
>(size) >
static_cast<typename std::make_unsigned<Csize>::type
>(max_csize)) {
86 throw std::runtime_error(
"failed to resize container to specified size");
89 container.resize(size);
92template<
typename Iterator_,
typename Size_>
93void check_safe_ptrdiff(Size_ size) {
94 typedef decltype(std::declval<Iterator_>() - std::declval<Iterator_>()) Diff;
95 constexpr Diff max_diff = std::numeric_limits<Diff>::max();
96 constexpr Size_ max_size = std::numeric_limits<Size_>::max();
97 if constexpr(
static_cast<typename std::make_unsigned<Size_>::type
>(max_size) >
static_cast<typename std::make_unsigned<Diff>::type
>(max_diff)) {
98 if (
static_cast<typename std::make_unsigned<Size_>::type
>(size) >
static_cast<typename std::make_unsigned<Diff>::type
>(max_diff)) {
99 throw std::runtime_error(
"potential integer overflow from iterator subtraction");
104template<
typename Index_,
class StartArray_,
class EndArray_>
105Nclist<Index_, ArrayElement<StartArray_> > build_internal(std::vector<Index_> of_interest,
const StartArray_& starts,
const EndArray_& ends) {
107 static_assert(std::is_same<Position, ArrayElement<EndArray_> >::value);
110 auto cmp = [&](Index_ l, Index_ r) ->
bool {
111 if (starts[l] == starts[r]) {
112 return ends[l] > ends[r];
114 return starts[l] < starts[r];
117 if (!std::is_sorted(of_interest.begin(), of_interest.end(), cmp)) {
118 std::sort(of_interest.begin(), of_interest.end(), cmp);
121 auto num_intervals = of_interest.size();
122 typedef typename Nclist<Index_, Position>::Node WorkingNode;
123 std::vector<WorkingNode> working_list;
124 working_list.reserve(num_intervals);
148 std::vector<Index_> working_children;
149 safe_resize(working_children, num_intervals);
150 Index_ children_used = 0, children_tmp_boundary = num_intervals;
151 std::vector<Index_> working_duplicates;
152 safe_resize(working_duplicates, num_intervals);
153 Index_ duplicates_used = 0, duplicates_tmp_boundary = num_intervals;
157 Level(Index_ offset, Position end) : offset(offset), end(end) {}
160 Index_ num_children = 0;
161 Index_ num_duplicates = 0;
163 std::vector<Level> levels(1);
165 Index_ num_children_to_copy = 0;
166 Index_ num_duplicates_to_copy = 0;
167 auto process_level = [&](
const Level& curlevel) ->
void {
168 auto& original_node = working_list[curlevel.offset];
170 if (curlevel.num_children) {
171 original_node.children_start = children_used + num_children_to_copy;
172 num_children_to_copy += curlevel.num_children;
173 original_node.children_end = children_used + num_children_to_copy;
176 if (curlevel.num_duplicates) {
177 original_node.duplicates_start = duplicates_used + num_duplicates_to_copy;
178 num_duplicates_to_copy += curlevel.num_duplicates;
179 original_node.duplicates_end = duplicates_used + num_duplicates_to_copy;
183 auto left_shift_indices = [&]() ->
void {
184 if (num_children_to_copy) {
185 if (children_used != children_tmp_boundary) {
186 std::copy_n(working_children.begin() + children_tmp_boundary, num_children_to_copy, working_children.begin() + children_used);
188 children_used += num_children_to_copy;
189 children_tmp_boundary += num_children_to_copy;
192 if (num_duplicates_to_copy) {
193 if (duplicates_used != duplicates_tmp_boundary) {
194 std::copy_n(working_duplicates.begin() + duplicates_tmp_boundary, num_duplicates_to_copy, working_duplicates.begin() + duplicates_used);
196 duplicates_used += num_duplicates_to_copy;
197 duplicates_tmp_boundary += num_duplicates_to_copy;
202 for (
const auto& curid : of_interest) {
203 auto curend = ends[curid];
205 if (levels.size() > 1) {
206 auto last_end = levels.back().end;
207 if (last_end < curend) {
208 num_children_to_copy = 0;
209 num_duplicates_to_copy = 0;
211 const auto& curlevel = levels.back();
212 process_level(curlevel);
214 }
while (levels.size() > 1 && levels.back().end < curend);
215 left_shift_indices();
217 }
else if (last_end == curend) {
218 if (starts[curid] == starts[last_id]) {
219 ++(levels.back().num_duplicates);
220 --duplicates_tmp_boundary;
221 working_duplicates[duplicates_tmp_boundary] = curid;
227 auto used = working_list.size();
228 working_list.emplace_back(curid);
229 ++(levels.back().num_children);
230 --children_tmp_boundary;
231 working_children[children_tmp_boundary] = used;
232 levels.emplace_back(used, curend);
237 num_children_to_copy = 0;
238 num_duplicates_to_copy = 0;
239 while (levels.size() > 1) {
240 const auto& curlevel = levels.back();
241 process_level(curlevel);
244 left_shift_indices();
247 of_interest.shrink_to_fit();
252 Nclist<Index_, Position> output;
253 safe_resize(output.nodes, working_list.size());
254 safe_resize(output.starts, working_list.size());
255 safe_resize(output.ends, working_list.size());
256 output.duplicates.reserve(duplicates_used);
264 check_safe_ptrdiff<
decltype(output.starts.begin())>(
static_cast<Index_
>(working_list.size()));
268 Level2(Index_ working_at, Index_ working_start, Index_ output_offset) : working_at(working_at), working_start(working_start), output_offset(output_offset) {}
270 Index_ working_start;
271 Index_ output_offset;
273 std::vector<Level2> history;
275 output.root_children = levels.front().num_children;
276 Index_ output_children_used = output.root_children;
277 history.emplace_back(working_children.size(), children_tmp_boundary, 0);
280 auto& current_state = history.back();
281 if (current_state.working_at == current_state.working_start) {
283 if (history.empty()) {
292 --(current_state.working_at);
293 auto current_working_at = current_state.working_at;
294 auto current_output_offset = current_state.output_offset;
295 ++(current_state.output_offset);
297 auto child = working_children[current_working_at];
298 auto& current = output.nodes[current_output_offset];
299 current = working_list[child];
304 output.starts[current_output_offset] = starts[current.id];
305 output.ends[current_output_offset] = ends[current.id];
307 auto duplicates_old_start = current.duplicates_start, duplicates_old_end = current.duplicates_end;
308 if (duplicates_old_start != duplicates_old_end) {
309 current.duplicates_start = output.duplicates.size();
310 output.duplicates.insert(
311 output.duplicates.end(),
312 working_duplicates.rbegin() + (num_intervals - duplicates_old_end),
313 working_duplicates.rbegin() + (num_intervals - duplicates_old_start)
315 current.duplicates_end = output.duplicates.size();
318 auto children_old_start = current.children_start, children_old_end = current.children_end;
319 if (children_old_start != children_old_end) {
320 current.children_start = output_children_used;
321 output_children_used += children_old_end - children_old_start;
322 current.children_end = output_children_used;
323 history.emplace_back(children_old_end, children_old_start, current.children_start);
349template<
typename Index_,
class StartArray_,
class EndArray_>
351 std::vector<Index_> of_interest(subset, subset + num_subset);
352 return build_internal(std::move(of_interest), starts, ends);
371template<
typename Index_,
class StartArray_,
class EndArray_>
373 std::vector<Index_> of_interest(num_intervals);
374 std::iota(of_interest.begin(), of_interest.end(),
static_cast<Index_
>(0));
375 return build_internal(std::move(of_interest), starts, ends);
392template<
typename Index_,
typename Position_>
409template<
typename Index_,
typename Position_>