def merge_lo(ms, keys, values, ssa, na, ssb, nb):
        """
        Merge the na elements starting at ssa with the nb elements starting at
        ssb = ssa + na in a stable way, in-place.  na and nb must be > 0,
        and should have na <= nb. See listsort.txt for more info.

        An updated MergeState is returned (with possibly a different min_gallop
        or larger temp arrays).

        NOTE: compared to CPython's timsort, the requirement that
            "Must also have that keys[ssa + na - 1] belongs at the end of the merge"

        is removed. This makes the code a bit simpler and easier to reason about.
        """
        assert na > 0 and nb > 0 and na <= nb
        assert ssb == ssa + na
        # First copy [ssa, ssa + na) into the temp space
        ms = merge_getmem(ms, na)
        sortslice_copy(ms.keys, ms.values, 0,
                       keys, values, ssa,
                       na)
        a_keys = ms.keys
        a_values = ms.values
        b_keys = keys
        b_values = values
        dest = ssa
        ssa = 0

        _has_values = has_values(a_keys, a_values)
        min_gallop = ms.min_gallop

        # Now start merging into the space left from [ssa, ...)

        while nb > 0 and na > 0:
            # Do the straightforward thing until (if ever) one run
            # appears to win consistently.
            acount = 0
            bcount = 0

            while True:
                if LT(b_keys[ssb], a_keys[ssa]):
                    keys[dest] = b_keys[ssb]
                    if _has_values:
                        values[dest] = b_values[ssb]
                    dest += 1
                    ssb += 1
                    nb -= 1
                    if nb == 0:
                        break
                    # It's a B run
                    bcount += 1
                    acount = 0
                    if bcount >= min_gallop:
                        break
                else:
                    keys[dest] = a_keys[ssa]
                    if _has_values:
                        values[dest] = a_values[ssa]
                    dest += 1
                    ssa += 1
                    na -= 1
                    if na == 0:
                        break
                    # It's a A run
                    acount += 1
                    bcount = 0
                    if acount >= min_gallop:
                        break

            # One run is winning so consistently that galloping may
            # be a huge win.  So try that, and continue galloping until
            # (if ever) neither run appears to be winning consistently
            # anymore.
            if DO_GALLOP and na > 0 and nb > 0:
                min_gallop += 1

                while acount >= MIN_GALLOP or bcount >= MIN_GALLOP:
                    # As long as we gallop without leaving this loop, make
                    # the heuristic more likely
                    min_gallop -= min_gallop > 1

                    # Gallop in A to find where keys[ssb] should end up
                    k = gallop_right(b_keys[ssb], a_keys, ssa, ssa + na, ssa)
                    # k is an index, make it a size
                    k -= ssa
                    acount = k
                    if k > 0:
                        # Copy everything from A before k
                        sortslice_copy(keys, values, dest,
                                       a_keys, a_values, ssa,
                                       k)
                        dest += k
                        ssa += k
                        na -= k
                        if na == 0:
                            # Finished merging
                            break
                    # Copy keys[ssb]
                    keys[dest] = b_keys[ssb]
                    if _has_values:
                        values[dest] = b_values[ssb]
                    dest += 1
                    ssb += 1
                    nb -= 1
                    if nb == 0:
                        # Finished merging
                        break

                    # Gallop in B to find where keys[ssa] should end up
                    k = gallop_left(a_keys[ssa], b_keys, ssb, ssb + nb, ssb)
                    # k is an index, make it a size
                    k -= ssb
                    bcount = k
                    if k > 0:
                        # Copy everything from B before k
                        # NOTE: source and dest are the same buffer, but the
                        # destination index is below the source index
                        sortslice_copy(keys, values, dest,
                                       b_keys, b_values, ssb,
                                       k)
                        dest += k
                        ssb += k
                        nb -= k
                        if nb == 0:
                            # Finished merging
                            break
                    # Copy keys[ssa]
                    keys[dest] = a_keys[ssa]
                    if _has_values:
                        values[dest] = a_values[ssa]
                    dest += 1
                    ssa += 1
                    na -= 1
                    if na == 0:
                        # Finished merging
                        break

                # Penalize it for leaving galloping mode
                min_gallop += 1

        # Merge finished, now handle the remaining areas
        if nb == 0:
            # Only A remaining to copy at the end of the destination area
            sortslice_copy(keys, values, dest,
                           a_keys, a_values, ssa,
                           na)
        else:
            assert na == 0
            assert dest == ssb
            # B's tail is already at the right place, do nothing

        return merge_adjust_gallop(ms, min_gallop)

        Merge the na elements starting at ssa with the nb elements starting at
        ssb = ssa + na in a stable way, in-place.  na and nb must be > 0,
        and should have na <= nb. See listsort.txt for more info.

        An updated MergeState is returned (with possibly a different min_gallop
        or larger temp arrays).

        NOTE: compared to CPython's timsort, the requirement that
            "Must also have that keys[ssa + na - 1] belongs at the end of the merge"

        is removed. This makes the code a bit simpler and easier to reason about.
        
numba/misc/timsort.py