private static int[] mergeSort(final int[] data) {

        /**
         * Return any data set smaller than 1 element intact, i.e. actual
         * sorting not required.
         **/
        if (data.length == 1) {
            return data;
        }

        /**
         * Find the mid-point in the given array.
         */
        int middle = data.length / 2;

        /**
         * Recursively sort left and right parts of array.
         */
        int[] left = mergeSort(Arrays.copyOfRange(data, 0, middle));
        int[] right = mergeSort(Arrays.copyOfRange(data, middle, data.length));

        /***
         * Create a new result array (not actually required).
         */
        int[] result = new int[data.length];

        /**
         * Merge left and right sorted arrays.
         */
        int resultPointer = 0;
        int leftPointer = 0;
        int rightPointer = 0;

        /**
         * For each element in the result array.
         */
        while (resultPointer < result.length) {

            if (leftPointer == left.length) {
                // Left array finished, so add right element.
                result[resultPointer] = right[rightPointer];
                rightPointer++;

            } else if (rightPointer == right.length) {
                // Right array finished, so add left element.
                result[resultPointer] = left[leftPointer];
                leftPointer++;

            } else if (left[leftPointer] < right[rightPointer]) {
                // Right element larger, so add left element first.
                result[resultPointer] = left[leftPointer];
                leftPointer++;

            } else {
                // Left element larger, so add right element first.
                result[resultPointer] = right[rightPointer];
                rightPointer++;
            }
            mIterations++;
            resultPointer++;
        }

        return result;
    }