package com.google.caliper.timsort;
public class SortingAlgorithms {
 Â
//textbook
  public void mergeSort(Integer[] array, int start,int end){
    if(start < end){
        int mid = (start + end) / 2;
        mergeSort(array,start, mid);
        mergeSort(array, mid + 1, end);
        merge(array, start, end);
    }
    }
    public void regMergeSort(Integer[] array, int start,int end){
        if(start < end){
            int mid = (start + end) / 2;
            mergeSort(array,start, mid);
            mergeSort(array, mid + 1, end);
            regMerge(array, start, end);
        }
    public static boolean isSorted(Integer[] array){
   Â
    for(int i = 0; i < array.length - 1; i++){
    if ( array[i] > array[i+1]){
    return false;
    }
    }
   Â
   Â
    return true;
   Â
    }
    private void merge(Integer[] input, int start,int r){
        int mid = (start + r) / 2;
        int i1 = 0;
        int i2 = start;
        int i3 = mid + 1;
        Integer[] temp = new Integer[r - start + 1];
        if(input[mid] < input[r]){
            while(i2 <= mid){
                if(input[i2] < input[i3])
                temp[i1++] = input[i2++];
                else
                    temp[i1++] = input[i3++];
            }
            while ( i3 <= r )
            temp[i1++] = input[i3++];
        }
        else
        {
            while(i3 <= r){
                if(input[i2] < input[i3])
                temp[i1++] = input[i2++];
                else
                    temp[i1++] = input[i3++];
            }
            while ( i2 <= mid )
            temp[i1++] = input[i2++];
        }
        for ( int i = start; i <= r; i++ )
            input[i] = temp[i-start];
    private void regMerge(Integer[] array, int start,int end){
        int mid = (start + end) / 2;
        int i1 = 0;
        int i2 = start;
        int i3 = mid + 1;
        Integer[] temp = new Integer[end - start + 1];
        while ( i2 <= mid && i3 <= end )
            if ( array[i2] < array[i3] )
              temp[i1++] = array[i2++];
            else
              temp[i1++] = array[i3++];
          while ( i2 <= mid )
            temp[i1++] = array[i2++];
          while ( i3 <= end )
            temp[i1++] = array[i3++];
        for ( int i = start; i <= end; i++ )
            array[i] = temp[i-start];
    //My implementation of timsort
    public static Integer[] insertSort(Integer[] list, Integer[] temp){
        int length = list.length - 1;
        int left = length;
        int right = length;
        int lo, hi, m, current, n;
        temp[left] = list[0];
        for(int i = 1; i < length; i++){           Â
            if(list[i] >= temp[right]){
                right = right + 1;
                temp[right] = list[i];
                continue;
            }
            if(list[i] <= temp[left]){
                left = left - 1;
                temp[left] = list[i];
                continue;
            }                       Â
            lo = left;
            hi = right;
            m = 0;
            while(lo < hi){
                // m = (lo + hi) >>> 1;
             m = lo + ((hi - lo) / 2 );
                if(list[i] < temp[m])
                    hi = m;
                else lo = m + 1;
            }
            current = lo - 1;
            if(right - current < current - left){
                /*
                int j = right + 1;
                while(j > current + 1){
                    temp[j] = temp[j - 1];
                    j--;
                }
                right = right + 1;
                temp[current + 1] = list[i];
                */          Â
                right++;
              n = right - current;
              /*
              switch(n ) {
                case 2:  temp[current + 3] = temp[current + 2];
                case 1:  temp[current + 2] = temp[current + 1];
                break;
                  default: System.arraycopy(temp, current + 1, temp, current + 2, n  );
                }            Â
              */
                System.arraycopy(temp, current + 1, temp, current + 2, n  );
                temp[current + 1] = list[i];         Â
            }
            else {
                /*
                int j = left - 1;
                while(j < current){
                    temp[j] = temp[j + 1];
                    j++;
                }
                left = left - 1;
                temp[current] = list[i];
                */
                n = current - (left - 1);
                /*
                switch(n ) {
                case 2:  temp[current - 2] = temp[current - 1];
                case 1:  temp[current - 1] = temp[current];
                break;
                  default: System.arraycopy(temp, left, temp, left - 1, n  );
                }
                */
                System.arraycopy(temp, left, temp, left - 1, n  );
                left--;
                temp[current] = list[i];
            }
        System.arraycopy(temp, left, list, 0, length  );
    /*  Â
        for(int i = 0; i < length; i++){
            list[i] = temp[left];
            left = left + 1;
        }
        */
        return list;
    public static Integer[] binarySort(Integer[] a) {
        int lo = 0;
        int start = lo;
        int hi = a.length;
if (start == lo)
start++;
for ( ; start < hi; start++) {
Integer pivot = a[start];
// Set left (and right) to the index where a[start] (pivot) belongs
int left = lo;
int right = start;
assert left <= right;
/*
* Invariants:
* Â pivot >= all in [lo, left).
* Â pivot < Â all in [right, start).
*/
while (left < right) {
int mid = (left + right) >>> 1;
if (pivot < a[mid])
right = mid;
else
left = mid + 1;
}
/*
* The invariants still hold: pivot >= all in [lo, left) and
* pivot < all in [left, start), so pivot belongs at left. Â Note
* that if there are elements equal to pivot, left points to the
* first slot after them -- that's why this sort is stable.
* Slide elements over to make room to make room for pivot.
*/
int n = start - left; Â // The number of elements to move
// Switch is just an optimization for arraycopy in default case
/*
for(int j = start; j >= left + 1; j--) Â
{ Â
  a[j] = a[j - 1]; Â
} Â
*/
switch(n) {
case 2: Â a[left + 2] = a[left + 1];
case 1: Â a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
return a;
}
    public void kNearSort(Integer[] a) {
        int lo = 0;
        int start = lo;
        int hi = a.length;
        int k = 10;
        int remainingMoves = k;
if (start == lo)
start++;
for ( ; start < hi; start++) {
Integer pivot = a[start];
int left = lo;
int right = start;
assert left <= right;
while (left < right) {
int mid = (left + right) >>> 1;
if (pivot < a[mid])
right = mid;
else
left = mid + 1;
}
int n = start - left; Â // The number of elements to move
remainingMoves = remainingMoves - n;
if(remainingMoves < 1)
    return;
switch(n) {
case 2: Â a[left + 2] = a[left + 1];
case 1: Â a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}