[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

`