void uninit_merge_level4(range<Value_t *> dest, std::vector<range<Iter_t> > &v_input, std::vector<range<Value_t *> > &v_output, Compare comp) { typedef range<Value_t *> range1_t; typedef util::value_iter<Iter_t> type1; static_assert (std::is_same< type1, Value_t >::value, "Incompatible iterators\n"); v_output.clear(); if (v_input.size() == 0) return; if (v_input.size() == 1) { v_output.emplace_back(move_construct(dest, v_input[0])); return; }; uint32_t nrange = v_input.size(); uint32_t pos_ini = 0; while (pos_ini < v_input.size()) { uint32_t nmerge = (nrange + 3) >> 2; uint32_t nelem = (nrange + nmerge - 1) / nmerge; range1_t rz = uninit_full_merge4(dest, &v_input[pos_ini], nelem, comp); v_output.emplace_back(rz); dest.first = rz.last; pos_ini += nelem; nrange -= nelem; }; return; };
static inline D cast(U &&o) { D d; if (!o) return d; auto t = get_dtable(o); d.table_ = t; if (std::is_reference<U>::value) { auto c = get_table<concept_copy_construct::Table>( t->type_info, t, o.table()); if (d.stored_in_heap()) { d.heap_data() = ::operator new(o.table()->size); } c->copy_construct(d.data(), o.data()); } else { if (d.stored_in_heap()) { if (o.stored_in_heap()) { d.heap_data() = o.heap_data(); ((S *)&o)->table_ = nullptr; } else { d.heap_data() = ::operator new(o.table()->size); } } if (o) { t->move_construct(d.data(), (void *)o.data()); } } return d; }
range<Value_t *> uninit_full_merge4(const range<Value_t *> &dest, range<Iter_t> vrange_input[4], uint32_t nrange_input, Compare comp) { typedef util::value_iter<Iter_t> type1; static_assert (std::is_same< type1, Value_t >::value, "Incompatible iterators\n"); size_t ndest = 0; uint32_t i = 0; while (i < nrange_input) { if (vrange_input[i].size() != 0) { ndest += vrange_input[i++].size(); } else { for (uint32_t k = i + 1; k < nrange_input; ++k) { vrange_input[k - 1] = vrange_input[k]; }; --nrange_input; }; }; if (nrange_input == 0) return range<Value_t *>(dest.first, dest.first); if (nrange_input == 1) return move_construct(dest, vrange_input[0]); if (nrange_input == 2) { return merge_construct(dest, vrange_input[0], vrange_input[1], comp); }; //------------------------------------------------------------------------ // Initial sort //------------------------------------------------------------------------ uint32_t pos[4] = { 0, 1, 2, 3 }, npos = nrange_input; //----------------------------------------------------------------------- // thanks to Steven Ross by their suggestion about the optimal // sorting networks //----------------------------------------------------------------------- if (less_range(vrange_input[pos[1]].first, pos[1], vrange_input[pos[0]].first, pos[0], comp)) { std::swap(pos[0], pos[1]); }; if (npos == 4 and less_range(vrange_input[pos[3]].first, pos[3], vrange_input[pos[2]].first, pos[2], comp)) { std::swap(pos[3], pos[2]); }; if (less_range(vrange_input[pos[2]].first, pos[2], vrange_input[pos[0]].first, pos[0], comp)) { std::swap(pos[0], pos[2]); }; if (npos == 4 and less_range(vrange_input[pos[3]].first, pos[3], vrange_input[pos[1]].first, pos[1], comp)) { std::swap(pos[1], pos[3]); }; if (less_range(vrange_input[pos[2]].first, pos[2], vrange_input[pos[1]].first, pos[1], comp)) { std::swap(pos[1], pos[2]); }; Value_t *it_dest = dest.first; while (npos > 2) { util::construct_object(&(*(it_dest++)), std::move(*(vrange_input[pos[0]].first++))); if (vrange_input[pos[0]].size() == 0) { pos[0] = pos[1]; pos[1] = pos[2]; pos[2] = pos[3]; --npos; } else { if (less_range (vrange_input[pos[1]].first, pos[1], vrange_input[pos[0]].first, pos[0], comp)) { std::swap(pos[0], pos[1]); if (less_range (vrange_input[pos[2]].first, pos[2], vrange_input[pos[1]].first, pos[1], comp)) { std::swap(pos[1], pos[2]); if (npos == 4 and less_range(vrange_input[pos[3]].first, pos[3], vrange_input[pos[2]].first, pos[2], comp)) { std::swap(pos[2], pos[3]); }; }; }; }; }; // end while (npos > 2) range<Value_t *> raux1(dest.first, it_dest), raux2(it_dest, dest.last); if (pos[0] < pos[1]) { return concat(raux1, merge_construct(raux2, vrange_input[pos[0]], vrange_input[pos[1]], comp)); } else { return concat(raux1, merge_construct(raux2, vrange_input[pos[1]], vrange_input[pos[0]], comp)); }; };