private int splitData(int startIndex, int endIndex) {
			// find pivot element with median-of-three heuristic
			int middleIndex = (startIndex + endIndex) >> 1;
			int lastButOneIndex = endIndex - 2;
			swap(middleIndex, lastButOneIndex);
			compareAndSwap(startIndex, lastButOneIndex);
			compareAndSwap(startIndex, endIndex - 1);
			compareAndSwap(endIndex - 1, lastButOneIndex);
			int pivotIndex = endIndex - 1;

			// We already no that the first element is lower or equal to the
			// pivot.
			int lowPointer = startIndex;

			// We also know that the element right before the pivot is greater
			// or equal to the pivot.
			int highPointer = lastButOneIndex;

			// Now exchange elements until the pointers meet
			while (true) {
				while (++lowPointer < highPointer)
					if (compare(lowPointer, pivotIndex) > 0)
						break;
				while (--highPointer > lowPointer) {
					if (compare(pivotIndex, highPointer) > 0)
						break;
				}
				if (lowPointer < highPointer)
					swap(lowPointer, highPointer);
				else
					break;
			}

			// find where the pointers have crossed and bias towards the
			// upper half since we need to swap with the pivot element
			int boarderIndex = (lowPointer + highPointer + 1) >> 1;
			swap(boarderIndex, pivotIndex);

			// Verification code.
			// T pivot = data[boarderIndex];
			// for (int i = startIndex; i < boarderIndex; i++) {
			// T elem = data[i];
			// if (comparator.compare(elem, pivot) > 0) {
			// System.err.println("First half error on sorting size "
			// + (endIndex - startIndex));
			// }
			// }
			// for (int i = boarderIndex + 1; i < endIndex; i++) {
			// T elem = data[i];
			// if (comparator.compare(elem, pivot) < 0) {
			// System.err.println("Second half error on sorting size "
			// + (endIndex - startIndex));
			// }
			// }

			return boarderIndex;
		}