[libc++] Add introsort to avoid O(n^2) behavior · llvm/llvm-project@7f28739 (original) (raw)
`@@ -263,12 +263,14 @@ __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __
`
263
263
``
264
264
`template <class _Compare, class _RandomAccessIterator>
`
265
265
`void
`
266
``
`-
__sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
`
``
266
`+
__introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
`
``
267
`+
typename _VSTD::iterator_traits<_RandomAccessIterator>::difference_type __depth)
`
267
268
`{
`
268
269
`typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
`
269
270
`typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
`
270
271
`const difference_type __limit = is_trivially_copy_constructible::value &&
`
271
272
` is_trivially_copy_assignable::value ? 30 : 6;
`
``
273
`+
typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
`
272
274
`while (true)
`
273
275
` {
`
274
276
` __restart:
`
`@@ -298,6 +300,13 @@ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __c
`
298
300
`return;
`
299
301
` }
`
300
302
`// __len > 5
`
``
303
`+
if (__depth == 0)
`
``
304
`+
{
`
``
305
`+
// Fallback to heap sort as Introsort suggests.
`
``
306
`+
_VSTD::__partial_sort<_Comp_ref>(__first, __last, __last, _Comp_ref(__comp));
`
``
307
`+
return;
`
``
308
`+
}
`
``
309
`+
--__depth;
`
301
310
` _RandomAccessIterator __m = __first;
`
302
311
` _RandomAccessIterator __lm1 = __last;
`
303
312
` --__lm1;
`
`@@ -440,19 +449,34 @@ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __c
`
440
449
`// sort smaller range with recursive call and larger with tail recursion elimination
`
441
450
`if (__i - __first < __last - __i)
`
442
451
` {
`
443
``
`-
_VSTD::__sort<_Compare>(__first, __i, __comp);
`
444
``
`-
// _VSTD::__sort<_Compare>(__i+1, __last, __comp);
`
445
``
`-
__first = ++__i;
`
``
452
`+
_VSTD::__introsort<_Compare>(__first, __i, __comp, __depth);
`
``
453
`+
__first = ++__i;
`
446
454
` }
`
447
455
`else
`
448
456
` {
`
449
``
`-
_VSTD::__sort<_Compare>(__i+1, __last, __comp);
`
450
``
`-
// _VSTD::__sort<_Compare>(__first, __i, __comp);
`
451
``
`-
__last = __i;
`
``
457
`+
_VSTD::__introsort<_Compare>(__i + 1, __last, __comp, __depth);
`
``
458
`+
__last = __i;
`
452
459
` }
`
453
460
` }
`
454
461
`}
`
455
462
``
``
463
`+
template
`
``
464
`+
inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) {
`
``
465
`+
_Number __log2 = 0;
`
``
466
`+
while (__n > 1) {
`
``
467
`+
__log2++;
`
``
468
`+
__n >>= 1;
`
``
469
`+
}
`
``
470
`+
return __log2;
`
``
471
`+
}
`
``
472
+
``
473
`+
template <class _Compare, class _RandomAccessIterator>
`
``
474
`+
void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
`
``
475
`+
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
`
``
476
`+
difference_type __depth_limit = 2 * __log2i(__last - __first);
`
``
477
`+
__introsort(__first, __last, __comp, __depth_limit);
`
``
478
`+
}
`
``
479
+
456
480
`template <class _Compare, class _Tp>
`
457
481
`inline _LIBCPP_INLINE_VISIBILITY
`
458
482
`void
`