void mergeAt(diff_t const i) { diff_t const stackSize = pending_.size(); assert( stackSize >= 2 ); assert( i >= 0 ); assert( i == stackSize - 2 || i == stackSize - 3 ); iter_t base1 = pending_[i].base; diff_t len1 = pending_[i].len; iter_t base2 = pending_[i + 1].base; diff_t len2 = pending_[i + 1].len; assert( len1 > 0 && len2 > 0 ); assert( base1 + len1 == base2 ); pending_[i].len = len1 + len2; if(i == stackSize - 3) { pending_[i + 1] = pending_[i + 2]; } pending_.pop_back(); diff_t const k = gallopRight(*base2, base1, len1, 0); assert( k >= 0 ); base1 += k; len1 -= k; if(len1 == 0) { return; } len2 = gallopLeft(*(base1 + (len1 - 1)), base2, len2, len2 - 1); assert( len2 >= 0 ); if(len2 == 0) { return; } if(len1 <= len2) { mergeLo(base1, len1, base2, len2); } else { mergeHi(base1, len1, base2, len2); } }
void mergeHi(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2) { assert(len1 > 0 && len2 > 0 && base1 + len1 == base2); copy_to_tmp(base2, len2); iter_t cursor1 = base1 + len1; tmp_iter_t cursor2 = tmp_.begin() + len2; iter_t dest = base2 + len2; *(--dest) = GFX_TIMSORT_MOVE(*(--cursor1)); if (--len1 == 0) { GFX_TIMSORT_MOVE_RANGE(tmp_.begin(), tmp_.begin() + len2, dest - len2); return; } if (len2 == 1) { dest -= len1; cursor1 -= len1; GFX_TIMSORT_MOVE_BACKWARD(cursor1, cursor1 + len1, dest + len1); *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); return; } int minGallop(minGallop_); // outer: while (true) { diff_t count1 = 0; diff_t count2 = 0; bool break_outer = false; do { assert(len1 > 0 && len2 > 1); if (comp_.lt(*(cursor2-1), *(cursor1-1))) { *(--dest) = GFX_TIMSORT_MOVE(*(--cursor1)); ++count1; count2 = 0; if (--len1 == 0) { break_outer = true; break; } } else { *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); ++count2; count1 = 0; if (--len2 == 1) { break_outer = true; break; } } } while ((count1 | count2) < minGallop); if (break_outer) { break; } do { assert(len1 > 0 && len2 > 1); count1 = len1 - gallopRight(*(cursor2-1), base1, len1, len1 - 1); if (count1 != 0) { dest -= count1; cursor1 -= count1; len1 -= count1; GFX_TIMSORT_MOVE_BACKWARD(cursor1, cursor1 + count1, dest + count1); if (len1 == 0) { break_outer = true; break; } } *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); if (--len2 == 1) { break_outer = true; break; } count2 = len2 - gallopLeft(*(cursor1-1), tmp_.begin(), len2, len2 - 1); if (count2 != 0) { dest -= count2; cursor2 -= count2; len2 -= count2; GFX_TIMSORT_MOVE_RANGE(cursor2, cursor2 + count2, dest); if (len2 <= 1) { break_outer = true; break; } } *(--dest) = GFX_TIMSORT_MOVE(*(--cursor1)); if (--len1 == 0) { break_outer = true; break; } minGallop--; } while ((count1 >= MIN_GALLOP) | (count2 >= MIN_GALLOP)); if (break_outer) { break; } if (minGallop < 0) { minGallop = 0; } minGallop += 2; } // end of "outer" loop minGallop_ = std::min(minGallop, 1); if (len2 == 1) { assert(len1 > 0); dest -= len1; GFX_TIMSORT_MOVE_BACKWARD(cursor1 - len1, cursor1, dest + len1); *(--dest) = GFX_TIMSORT_MOVE(*(--cursor2)); } else { assert(len2 != 0 && "Comparison function violates its general contract"); assert(len1 == 0); assert(len2 > 1); GFX_TIMSORT_MOVE_RANGE(tmp_.begin(), tmp_.begin() + len2, dest - len2); } }
void mergeHi(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2) { assert( len1 > 0 && len2 > 0 && base1 + len1 == base2 ); copy_to_tmp(base2, len2); iter_t cursor1 = base1 + (len1 - 1); tmp_iter_t cursor2 = tmp_.begin() + (len2 - 1); iter_t dest = base2 + (len2 - 1); *(dest--) = *(cursor1--); if(--len1 == 0) { std::copy(tmp_.begin(), tmp_.begin() + len2, dest - (len2 - 1)); return; } if(len2 == 1) { dest -= len1; cursor1 -= len1; std::copy(cursor1 + 1, cursor1 + (1 + len1), dest + 1); *dest = *cursor2; return; } int minGallop( minGallop_ ); // outer: while(true) { int count1 = 0; int count2 = 0; bool break_outer = false; do { assert( len1 > 0 && len2 > 1 ); if(comp_.lt(*cursor2, *cursor1)) { *(dest--) = *(cursor1--); ++count1; count2 = 0; if(--len1 == 0) { break_outer = true; break; } } else { *(dest--) = *(cursor2--); ++count2; count1 = 0; if(--len2 == 1) { break_outer = true; break; } } } while( (count1 | count2) < minGallop ); if(break_outer) { break; } do { assert( len1 > 0 && len2 > 1 ); count1 = len1 - gallopRight(*cursor2, base1, len1, len1 - 1); if(count1 != 0) { dest -= count1; cursor1 -= count1; len1 -= count1; std::copy(cursor1 + 1, cursor1 + (1 + count1), dest + 1); if(len1 == 0) { break_outer = true; break; } } *(dest--) = *(cursor2--); if(--len2 == 1) { break_outer = true; break; } count2 = len2 - gallopLeft(*cursor1, tmp_.begin(), len2, len2 - 1); if(count2 != 0) { dest -= count2; cursor2 -= count2; len2 -= count2; std::copy(cursor2 + 1, cursor2 + (1 + count2), dest + 1); if(len2 <= 1) { break_outer = true; break; } } *(dest--) = *(cursor1--); if(--len1 == 0) { break_outer = true; break; } minGallop--; } while( (count1 >= MIN_GALLOP) | (count2 >= MIN_GALLOP) ); if(break_outer) { break; } if(minGallop < 0) { minGallop = 0; } minGallop += 2; } // end of "outer" loop minGallop_ = std::min(minGallop, 1); if(len2 == 1) { assert( len1 > 0 ); dest -= len1; cursor1 -= len1; std::copy(cursor1 + 1, cursor1 + (1 + len1), dest + 1); *dest = *cursor2; } else { assert( len2 != 0 && "Comparision function violates its general contract"); assert( len1 == 0 ); assert( len2 > 1 ); std::copy(tmp_.begin(), tmp_.begin() + len2, dest - (len2 - 1)); } }
void mergeLo(iter_t const base1, diff_t len1, iter_t const base2, diff_t len2) { assert( len1 > 0 && len2 > 0 && base1 + len1 == base2 ); copy_to_tmp(base1, len1); tmp_iter_t cursor1 = tmp_.begin(); iter_t cursor2 = base2; iter_t dest = base1; *(dest++) = *(cursor2++); if(--len2 == 0) { std::copy(cursor1, cursor1 + len1, dest); return; } if(len1 == 1) { std::copy(cursor2, cursor2 + len2, dest); *(dest + len2) = *cursor1; return; } int minGallop(minGallop_); // outer: while(true) { int count1 = 0; int count2 = 0; bool break_outer = false; do { assert( len1 > 1 && len2 > 0 ); if(comp_.lt(*cursor2, *cursor1)) { *(dest++) = *(cursor2++); ++count2; count1 = 0; if(--len2 == 0) { break_outer = true; break; } } else { *(dest++) = *(cursor1++); ++count1; count2 = 0; if(--len1 == 1) { break_outer = true; break; } } } while( (count1 | count2) < minGallop ); if(break_outer) { break; } do { assert( len1 > 1 && len2 > 0 ); count1 = gallopRight(*cursor2, cursor1, len1, 0); if(count1 != 0) { std::copy(cursor1, cursor1 + count1, dest); dest += count1; cursor1 += count1; len1 -= count1; if(len1 <= 1) { break_outer = true; break; } } *(dest++) = *(cursor2++); if(--len2 == 0) { break_outer = true; break; } count2 = gallopLeft(*cursor1, cursor2, len2, 0); if(count2 != 0) { std::copy(cursor2, cursor2 + count2, dest); dest += count2; cursor2 += count2; len2 -= count2; if(len2 == 0) { break_outer = true; break; } } *(dest++) = *(cursor1++); if(--len1 == 1) { break_outer = true; break; } --minGallop; } while( (count1 >= MIN_GALLOP) | (count2 >= MIN_GALLOP) ); if(break_outer) { break; } if(minGallop < 0) { minGallop = 0; } minGallop += 2; } // end of "outer" loop minGallop_ = std::min(minGallop, 1); if(len1 == 1) { assert( len2 > 0 ); std::copy(cursor2, cursor2 + len2, dest); *(dest + len2) = *cursor1; } else { assert( len1 != 0 && "Comparision function violates its general contract"); assert( len2 == 0 ); assert( len1 > 1 ); std::copy(cursor1, cursor1 + len1, dest); } }