timsort.js
/**
 * Like mergeLo, except that this method should be called only if
 * len1 >= len2; mergeLo should be called if len1 <= len2.  (Either method
 * may be called if len1 == len2.)
 * @param {TimSort} tim 
 * @param {Number} base1 
 * @param {Number} len1 
 * @param {Number} base2 
 * @param {Number} len2 
 */
Like mergeLo, except that this method should be called only if
len1 >= len2; mergeLo should be called if len1 <= len2.
Like mergeLo except that this method should be called only if len1 > = len2 ; mergeLo should be called if len1 < = len2 .
function mergeHi(tim, base1, len1, base2, len2){
    let a = tim.arr, 
        tmp = ensureCapacity(tim, len2);
    arrayCopy(a, base2, tmp, 0, len2);
    let cursor1 = base1 + len1 - 1,  
        cursor2 = len2 - 1,          
        dest = base2 + len2 - 1;     
    a[dest--] = a[cursor1--];
    if (--len1 == 0) {
        arrayCopy(tmp, 0, a, dest - (len2 - 1), len2);
        return;
    }
    if (len2 == 1) {
        dest -= len1;
        cursor1 -= len1;
        arrayCopy(a, cursor1 + 1, a, dest + 1, len1);
        a[dest] = tmp[cursor2];
        return;
    }
    let c = tim.comparator,  
        minGallop = tim.minGallop;    
outer:
    while (true) {
        let count1 = 0, 
            count2 = 0; 
        do {
            if (c(tmp[cursor2], a[cursor1]) < 0) {
                a[dest--] = a[cursor1--];
                count1++;
                count2 = 0;
                if (--len1 == 0){
                    break outer;
                }
            } else {
                a[dest--] = tmp[cursor2--];
                count2++;
                count1 = 0;
                if (--len2 == 1){
                    break outer;
                }
            }
        } while ((count1 | count2) < minGallop);
        do {
            count1 = len1 - gallopRight(tmp[cursor2], a, base1, len1, len1 - 1, c);
            if (count1 != 0) {
                dest -= count1;
                cursor1 -= count1;
                len1 -= count1;
                arrayCopy(a, cursor1 + 1, a, dest + 1, count1);
                if (len1 == 0){
                    break outer;
                }
            }
            a[dest--] = tmp[cursor2--];
            if (--len2 == 1){
                break outer;
            }
            count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
            if (count2 != 0) {
                dest -= count2;
                cursor2 -= count2;
                len2 -= count2;
                arrayCopy(tmp, cursor2 + 1, a, dest + 1, count2);
                if (len2 <= 1){  
                    break outer;
                }
            }
            a[dest--] = a[cursor1--];
            if (--len1 == 0){
                break outer;
            }
            minGallop--;
        } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
        if (minGallop < 0){
            minGallop = 0;
        }
        minGallop += 2;  
    }  
    tim.minGallop = minGallop < 1 ? 1 : minGallop;  
    if (len2 == 1) {
        dest -= len1;
        cursor1 -= len1;
        arrayCopy(a, cursor1 + 1, a, dest + 1, len1);
        a[dest] = tmp[cursor2];  
    } else if (len2 == 0) {
        raise(true, "IllegalArgumentException: Comparison method violates its general contract! Lo");
    } else {
        arrayCopy(tmp, 0, a, dest - (len2 - 1), len2);
    }
}
function mergeHi ( tim , base1 , len1 , base2 , len2 ) { let a = tim . arr , tmp = ensureCapacity ( tim , len2 ) ; arrayCopy ( a , base2 , tmp , 0 , len2 ) ; let cursor1 = base1 + len1 - 1 , cursor2 = len2 - 1 , dest = base2 + len2 - 1 ; a [ dest -- ] = a [ cursor1 -- ] ; if ( -- len1 == 0 ) { arrayCopy ( tmp , 0 , a , dest - ( len2 - 1 ) , len2 ) ; return ; } if ( len2 == 1 ) { dest -= len1 ; cursor1 -= len1 ; arrayCopy ( a , cursor1 + 1 , a , dest + 1 , len1 ) ; a [ dest ] = tmp [ cursor2 ] ; return ; } let c = tim . comparator , minGallop = tim . minGallop ; outer : while ( true ) { let count1 = 0 , count2 = 0 ; do { if ( c ( tmp [ cursor2 ] , a [ cursor1 ] ) < 0 ) { a [ dest -- ] = a [ cursor1 -- ] ; count1 ++ ; count2 = 0 ; if ( -- len1 == 0 ) { break outer ; } } else { a [ dest -- ] = tmp [ cursor2 -- ] ; count2 ++ ; count1 = 0 ; if ( -- len2 == 1 ) { break outer ; } } } while ( ( count1 | count2 ) < minGallop ) ; do { count1 = len1 - gallopRight ( tmp [ cursor2 ] , a , base1 , len1 , len1 - 1 , c ) ; if ( count1 != 0 ) { dest -= count1 ; cursor1 -= count1 ; len1 -= count1 ; arrayCopy ( a , cursor1 + 1 , a , dest + 1 , count1 ) ; if ( len1 == 0 ) { break outer ; } } a [ dest -- ] = tmp [ cursor2 -- ] ; if ( -- len2 == 1 ) { break outer ; } count2 = len2 - gallopLeft ( a [ cursor1 ] , tmp , 0 , len2 , len2 - 1 , c ) ; if ( count2 != 0 ) { dest -= count2 ; cursor2 -= count2 ; len2 -= count2 ; arrayCopy ( tmp , cursor2 + 1 , a , dest + 1 , count2 ) ; if ( len2 <= 1 ) { break outer ; } } a [ dest -- ] = a [ cursor1 -- ] ; if ( -- len1 == 0 ) { break outer ; } minGallop -- ; } while ( count1 >= MIN_GALLOP | count2 >= MIN_GALLOP ) ; if ( minGallop < 0 ) { minGallop = 0 ; } minGallop += 2 ; } tim . minGallop = minGallop < 1 ? 1 : minGallop ; if ( len2 == 1 ) { dest -= len1 ; cursor1 -= len1 ; arrayCopy ( a , cursor1 + 1 , a , dest + 1 , len1 ) ; a [ dest ] = tmp [ cursor2 ] ; } else if ( len2 == 0 ) { raise ( true , "IllegalArgumentException: Comparison method violates its general contract! Lo" ) ; } else { arrayCopy ( tmp , 0 , a , dest - ( len2 - 1 ) , len2 ) ; } }
Like mergeLo, except that this method should be called only if
 len1 >= len2; mergeLo should be called if len1 <= len2.
Like mergeLo except that this method should be called only if len1 > = len2 ; mergeLo should be called if len1 < = len2 .
//assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
 // Copy second run into temp array
 // For performance
 // Indexes into a
 // Indexes into tmp array
 // Indexes into a
 // Move last element of first run and deal with degenerate cases
 // Use local variable for performance
 //  "    "       "     "      "
 // Number of times in a row that first run won
 // Number of times in a row that second run won
 /*
            * Do the straightforward thing until (if ever) one run
            * appears to win consistently.
            */ //assert len1 > 0 && len2 > 1;
 /*
            * 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.
            */ //assert len1 > 0 && len2 > 1;
 // len2 == 1 || len2 == 0
 // Penalize for leaving gallop mode
 // End of "outer" loop
 // Write back to field
 //assert len1 > 0;
 // Move first elt of run2 to front of merge
 //assert len1 == 0;
 //assert len2 > 0;
