Skip to content

Commit 7105bff

Browse files
committed
Optimise the 1-element case for mergeLo/MergeHi
1 parent 5c46b9e commit 7105bff

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

include/gfx/timsort.hpp

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -397,25 +397,40 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
397397
return std::upper_bound(base + (lastOfs + 1), base + ofs, key, compare) - base;
398398
}
399399

400+
static void rotateLeft(iter_t first, iter_t last)
401+
{
402+
value_t tmp = GFX_TIMSORT_MOVE(*first);
403+
iter_t last_1 = GFX_TIMSORT_MOVE_RANGE(first + 1, last, first);
404+
*last_1 = GFX_TIMSORT_MOVE(tmp);
405+
}
406+
407+
static void rotateRight(iter_t first, iter_t last)
408+
{
409+
iter_t last_1 = last - 1;
410+
value_t tmp = GFX_TIMSORT_MOVE(*last_1);
411+
GFX_TIMSORT_MOVE_BACKWARD(first, last_1, last);
412+
*first = GFX_TIMSORT_MOVE(tmp);
413+
}
414+
415+
400416
void mergeLo(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2, Compare compare) {
401417
GFX_TIMSORT_ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2);
402418

419+
if (len1 == 1) {
420+
return rotateLeft(base1, base2 + len2);
421+
}
422+
if (len2 == 1) {
423+
return rotateRight(base1, base2 + len2);
424+
}
425+
403426
copy_to_tmp(base1, len1);
404427

405428
tmp_iter_t cursor1 = tmp_.begin();
406429
iter_t cursor2 = base2;
407430
iter_t dest = base1;
408431

409432
*(dest++) = GFX_TIMSORT_MOVE(*(cursor2++));
410-
if (--len2 == 0) {
411-
GFX_TIMSORT_MOVE_RANGE(cursor1, cursor1 + len1, dest);
412-
return;
413-
}
414-
if (len1 == 1) {
415-
GFX_TIMSORT_MOVE_RANGE(cursor2, cursor2 + len2, dest);
416-
*(dest + len2) = GFX_TIMSORT_MOVE(*cursor1);
417-
return;
418-
}
433+
--len2;
419434

420435
int minGallop(minGallop_);
421436

@@ -506,24 +521,21 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
506521
void mergeHi(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2, Compare compare) {
507522
GFX_TIMSORT_ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2);
508523

524+
if (len1 == 1) {
525+
return rotateLeft(base1, base2 + len2);
526+
}
527+
if (len2 == 1) {
528+
return rotateRight(base1, base2 + len2);
529+
}
530+
509531
copy_to_tmp(base2, len2);
510532

511533
iter_t cursor1 = base1 + len1;
512534
tmp_iter_t cursor2 = tmp_.begin() + (len2 - 1);
513535
iter_t dest = base2 + (len2 - 1);
514536

515537
*(dest--) = GFX_TIMSORT_MOVE(*(--cursor1));
516-
if (--len1 == 0) {
517-
GFX_TIMSORT_MOVE_RANGE(tmp_.begin(), tmp_.begin() + len2, dest - (len2 - 1));
518-
return;
519-
}
520-
if (len2 == 1) {
521-
dest -= len1;
522-
cursor1 -= len1;
523-
GFX_TIMSORT_MOVE_BACKWARD(cursor1, cursor1 + len1, dest + (1 + len1));
524-
*dest = GFX_TIMSORT_MOVE(*cursor2);
525-
return;
526-
}
538+
--len1;
527539

528540
int minGallop(minGallop_);
529541

0 commit comments

Comments
 (0)