private void sort(T[] a, T[] aux, int lo,
			int hi)
	{ // Sort a[lo..hi].
		if (hi - lo + 1 <= CUTOFF)
		{ // Improvement - 1
			// sort using insertion sort if subarray is small
			Sorter<T> sorter = new InsertionSorter<>();
			sorter.sort(a, lo, hi);
			return;
		}

		int mid = lo + (hi - lo) / 2; // mid has to be calculated relative to lo
		// sort both halves into aux[] so that they can then be merged into a[]
		sort(aux, a, lo, mid); // Sort left half.
		sort(aux, a, mid + 1, hi); // Sort right half.

		// Improvement - 2
		// No need for merge if array is already sorted
		if (lessOrEqual(aux[mid], aux[mid + 1]))
			System.arraycopy(aux, lo, a, lo, hi - lo + 1);
		else
			// merge aux[lo..mid] and aux[mid+1..hi] to a[lo..mid]
			// here aux[] is src and a[] is dst
			mergeWithoutCopy(aux, a, lo, mid, hi);
	}