template void CoSort__(CoWork& cw, I l, I h, const Less& less) { const int PARALLEL_THRESHOLD = 80; for(;;) { int count = int(h - l); if(count < 2) return; if(count < 8) { // Final optimized SelectSort FinalSort__(l, h, less); return; } int pass = 4; for(;;) { I middle = l + (count >> 1); // get the middle element OrderIter2__(l, middle, less); // sort l, middle, h-1 to find median of 3 OrderIter2__(middle, h - 1, less); OrderIter2__(l, middle, less); // median is now in middle IterSwap(l + 1, middle); // move median pivot to l + 1 I ii = l + 1; for(I i = l + 2; i != h - 1; ++i) // do partitioning; already l <= pivot <= h - 1 if(less(*i, *(l + 1))) IterSwap(++ii, i); IterSwap(ii, l + 1); // put pivot back in between partitions I iih = ii; while(iih + 1 != h && !less(*ii, *(iih + 1))) // Find middle range of elements equal to pivot ++iih; if(pass > 5 || min(ii - l, h - iih) > (max(ii - l, h - iih) >> pass)) { // partition sizes ok or we have done max attempts if(ii - l < h - iih - 1) { // schedule or recurse on smaller partition, tail on larger if(ii - l < PARALLEL_THRESHOLD) // too small to run in parallel? Sort__(l, ii, less); // resolve in this thread else cw & [=, &cw] { CoSort__(cw, l, ii, less); }; // schedule for parallel execution l = iih + 1; } else { if(h - iih - 1 < PARALLEL_THRESHOLD) // too small to run in parallel? Sort__(iih + 1, h, less); // resolve in this thread else cw & [=, &cw] { CoSort__(cw, iih + 1, h, less); }; // schedule for parallel execution h = ii; } break; } IterSwap(l, l + (int)Random(count)); // try some other random elements for median pivot IterSwap(middle, l + (int)Random(count)); IterSwap(h - 1, l + (int)Random(count)); pass++; } } } template void CoSort__(I l, I h, const Less& less) { CoWork cw; CoSort__(cw, l, h, less); } template void CoSort(Range& c, const Less& less) { CoSort__(c.begin(), c.end(), less); } template void CoSort(Range&& c, const Less& less) { CoSort(c, less); } template void CoSort(Range& c) { CoSort__(c.begin(), c.end(), std::less>()); } template void CoSort(Range&& c) { CoSort(c); } template void CoStableSort(Range& r, const Less& less) { auto begin = r.begin(); auto end = r.end(); typedef ValueTypeOf VT; typedef decltype(begin) I; int count = (int)(uintptr_t)(end - begin); Buffer h(count); for(int i = 0; i < count; i++) h[i] = i; CoSort__(StableSortIterator__(begin, ~h), StableSortIterator__(end, ~h + count), StableSortLess__(less)); } template void CoStableSort(Range&& r, const Less& less) { CoStableSort(r, less); } template void CoStableSort(Range& r) { CoStableSort(r, std::less>()); } template void CoStableSort(Range&& r) { CoStableSort(r); } template void CoIndexSort(MasterRange& r, Range2& r2, const Less& less) { ASSERT(r.GetCount() == r2.GetCount()); typedef decltype(r.begin()) I; typedef decltype(r2.begin()) I2; typedef ValueTypeOf VT; if(r.GetCount() == 0) return; CoSort__(IndexSortIterator__(r.begin(), r2.begin()), IndexSortIterator__(r.end(), r2.end()), less); } template void CoIndexSort(MasterRange&& r, Range2&& r2, const Less& less) { CoIndexSort(r, r2, less); } template void CoIndexSort(MasterRange& r, Range2& r2) { CoIndexSort(r, r2, std::less>()); } template void CoIndexSort(MasterRange&& r, Range2&& r2) { CoIndexSort(r, r2); } template void CoStableIndexSort(MasterRange& r, Range2& r2, const Less& less) { ASSERT(r.GetCount() == r2.GetCount()); typedef decltype(r.begin()) I; typedef decltype(r2.begin()) I2; typedef ValueTypeOf VT; if(r.GetCount() == 0) return; CoStableSort(SubRange(IndexSortIterator__(r.begin(), r2.begin()), IndexSortIterator__(r.end(), r2.end())).Write(), less); } template void CoStableIndexSort(MasterRange&& r, Range2&& r2, const Less& less) { CoStableIndexSort(r, r2, less); } template void CoStableIndexSort(MasterRange& r, Range2& r2) { CoStableIndexSort(r, r2, std::less>()); } template void CoStableIndexSort(MasterRange&& r, Range2&& r2) { CoStableIndexSort(r, r2); } template void CoIndexSort2(MasterRange& r, Range2& r2, Range3& r3, const Less& less) { ASSERT(r.GetCount() == r2.GetCount()); ASSERT(r.GetCount() == r3.GetCount()); if(r.GetCount() == 0) return; typedef decltype(r.begin()) I; typedef decltype(r2.begin()) I2; typedef decltype(r3.begin()) I3; typedef ValueTypeOf VT; CoSort__(IndexSort2Iterator__(r.begin(), r2.begin(), r3.begin()), IndexSort2Iterator__(r.end(), r2.end(), r3.end()), less); } template void CoIndexSort2(MasterRange&& r, Range2&& r2, Range3&& r3, const Less& less) { CoIndexSort2(r, r2, r3, less); } template void CoIndexSort2(MasterRange& r, Range2& r2, Range3& r3) { CoIndexSort2(r, r2, r3, std::less>()); } template void CoIndexSort2(MasterRange&& r, Range2&& r2, Range3&& r3) { CoIndexSort2(r, r2, r3); } template void CoStableIndexSort2(MasterRange& r, Range2& r2, Range3& r3, const Less& less) { ASSERT(r.GetCount() == r2.GetCount()); ASSERT(r.GetCount() == r3.GetCount()); if(r.GetCount() == 0) return; typedef decltype(r.begin()) I; typedef decltype(r2.begin()) I2; typedef decltype(r3.begin()) I3; typedef ValueTypeOf VT; CoStableSort(SubRange(IndexSort2Iterator__(r.begin(), r2.begin(), r3.begin()), IndexSort2Iterator__(r.end(), r2.end(), r3.end())).Write(), less); } template void CoStableIndexSort2(MasterRange&& r, Range2&& r2, Range3&& r3, const Less& less) { CoStableIndexSort2(r, r2, r3, less); } template void CoStableIndexSort2(MasterRange& r, Range2& r2, Range3& r3) { CoStableIndexSort2(r, r2, r3, std::less>()); } template void CoStableIndexSort2(MasterRange&& r, Range2&& r2, Range3&& r3) { CoStableIndexSort2(r, r2, r3); } template void CoIndexSort3(MasterRange& r, Range2& r2, Range3& r3, Range4& r4, const Less& less) { ASSERT(r.GetCount() == r2.GetCount()); ASSERT(r.GetCount() == r3.GetCount()); ASSERT(r.GetCount() == r4.GetCount()); if(r.GetCount() == 0) return; typedef decltype(r.begin()) I; typedef decltype(r2.begin()) I2; typedef decltype(r3.begin()) I3; typedef decltype(r4.begin()) I4; typedef ValueTypeOf VT; CoSort__(IndexSort3Iterator__(r.begin(), r2.begin(), r3.begin(), r4.begin()), IndexSort3Iterator__(r.end(), r2.end(), r3.end(), r4.end()), less); } template void CoIndexSort3(MasterRange&& r, Range2&& r2, Range3&& r3, Range4&& r4, const Less& less) { CoIndexSort3(r, r2, r3, r4, less); } template void CoIndexSort3(MasterRange& r, Range2& r2, Range3& r3, Range4& r4) { CoIndexSort3(r, r2, r3, r4, std::less>()); } template void CoIndexSort3(MasterRange&& r, Range2&& r2, Range3&& r3, Range4&& r4) { CoIndexSort3(r, r2, r3, r4); } template void CoStableIndexSort3(MasterRange& r, Range2& r2, Range3& r3, Range4& r4, const Less& less) { ASSERT(r.GetCount() == r2.GetCount()); ASSERT(r.GetCount() == r3.GetCount()); ASSERT(r.GetCount() == r4.GetCount()); if(r.GetCount() == 0) return; typedef decltype(r.begin()) I; typedef decltype(r2.begin()) I2; typedef decltype(r3.begin()) I3; typedef decltype(r4.begin()) I4; typedef ValueTypeOf VT; CoStableSort(SubRange(IndexSort3Iterator__(r.begin(), r2.begin(), r3.begin(), r4.begin()), IndexSort3Iterator__(r.end(), r2.end(), r3.end(), r4.end())).Write(), less); } template void CoStableIndexSort3(MasterRange&& r, Range2&& r2, Range3&& r3, Range4&& r4, const Less& less) { CoStableIndexSort3(r, r2, r3, r4, less); } template void CoStableIndexSort3(MasterRange& r, Range2& r2, Range3& r3, Range4& r4) { CoStableIndexSort3(r, r2, r3, r4, std::less>()); } template void CoStableIndexSort3(MasterRange&& r, Range2&& r2, Range3&& r4, Range4&& r3) { CoStableIndexSort3(r, r2, r3, r4); } template Vector CoGetSortOrder(Range& r, const Less& less) { auto begin = r.begin(); Vector index; index.SetCount(r.GetCount()); for(int i = index.GetCount(); --i >= 0; index[i] = i) ; typedef SortOrderIterator__> It; CoSort__(It(index.begin(), begin), It(index.end(), begin), less); return index; } template inline Vector CoGetSortOrder(const Range& r) { return CoGetSortOrder(r, std::less>()); } template Vector CoGetStableSortOrder(Range& r, const Less& less) { Vector index; index.SetCount(r.GetCount()); for(int i = index.GetCount(); --i >= 0; index[i] = i) ; auto begin = r.begin(); typedef ValueTypeOf VT; typedef StableSortOrderIterator__ It; CoSort__(It(index.begin(), begin), It(index.end(), begin), StableSortLess__(less)); return index; } template inline Vector CoGetStableSortOrder(const Range& r) { return CoGetSortOrder(r, std::less>()); } template void CoSortByKey(Map& map, const Less& less) { typename Map::KeyContainer k = map.PickKeys(); typename Map::ValueContainer v = map.PickValues(); CoIndexSort(k, v, less); map = Map(pick(k), pick(v)); } template void CoSortByKey(Map& map) { CoSortByKey(map, std::less()); } template void CoSortByValue(Map& map, const Less& less) { typename Map::KeyContainer k = map.PickKeys(); typename Map::ValueContainer v = map.PickValues(); CoIndexSort(v, k, less); map = Map(pick(k), pick(v)); } template void CoSortByValue(Map& map) { CoSortByValue(map, std::less>()); } template void CoStableSortByKey(Map& map, const Less& less) { typename Map::KeyContainer k = map.PickKeys(); typename Map::ValueContainer v = map.PickValues(); CoStableIndexSort(k, v, less); map = Map(pick(k), pick(v)); } template void CoStableSortByKey(Map& map) { CoStableSortByKey(map, std::less()); } template void CoStableSortByValue(Map& map, const Less& less) { typename Map::KeyContainer k = map.PickKeys(); typename Map::ValueContainer v = map.PickValues(); CoStableIndexSort(v, k, less); map = Map(pick(k), pick(v)); } template void CoStableSortByValue(Map& map) { CoStableSortByValue(map, std::less>()); } template void CoSortIndex(Index& index, const Less& less) { typename Index::ValueContainer k = index.PickKeys(); CoSort(k, less); index = Index(pick(k)); } template void CoSortIndex(Index& index) { CoSortIndex(index, std::less>()); } template void CoStableSortIndex(Index& index, const Less& less) { typename Index::ValueContainer k = index.PickKeys(); CoStableSort(k, less); index = Index(pick(k)); } template void CoStableSortIndex(Index& index) { CoStableSortIndex(index, std::less>()); }