package com.sun.javafx.collections;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
public class SortHelper {
private int[] permutation;
private int[] reversePermutation;
private static final int INSERTIONSORT_THRESHOLD = 7;
public <T extends Comparable<? super T>> int[] sort(List<T> list) {
T[] a = (T[]) Array.newInstance(Comparable.class, list.size());
try {
a = list.toArray(a);
} catch (ArrayStoreException e) {
throw new ClassCastException();
}
int[] result = sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
return result;
}
public <T> int[] sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
int[] result = sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
return result;
}
public <T extends Comparable<? super T>> int[] sort(T[] a) {
return sort(a, null);
}
public <T> int[] sort(T[] a, Comparator<? super T> c) {
T[] aux = (T[]) a.clone();
int[] result = initPermutation(a.length);
if (c==null)
mergeSort(aux, a, 0, a.length, 0);
else
mergeSort(aux, a, 0, a.length, 0, c);
reversePermutation = null;
permutation = null;
return result;
}
public <T> int[] sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
rangeCheck(a.length, fromIndex, toIndex);
T[] aux = (T[])copyOfRange(a, fromIndex, toIndex);
int[] result = initPermutation(a.length);
if (c==null)
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
else
mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
reversePermutation = null;
permutation = null;
return Arrays.copyOfRange(result, fromIndex, toIndex);
}
public int[] sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
int[] aux = (int[])copyOfRange(a, fromIndex, toIndex);
int[] result = initPermutation(a.length);
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
reversePermutation = null;
permutation = null;
return Arrays.copyOfRange(result, fromIndex, toIndex);
}
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex+")");
if (fromIndex < 0)
throw new ArrayIndexOutOfBoundsException(fromIndex);
if (toIndex > arrayLen)
throw new ArrayIndexOutOfBoundsException(toIndex);
}
private static int[] copyOfRange(int[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
int[] copy = new int[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
private static <T> T[] copyOfRange(T[] original, int from, int to) {
return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
}
private static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
private void mergeSort(int[] src,
int[] dest,
int low,
int high,
int off) {
int length = high - low;
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off);
mergeSort(dest, src, mid, high, -off);
if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0) {
dest[i] = src[p];
permutation[reversePermutation[p++]] = i;
} else {
dest[i] = src[q];
permutation[reversePermutation[q++]] = i;
}
}
for (int i = destLow; i < destHigh; ++i) {
reversePermutation[permutation[i]] = i;
}
}
private void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off);
mergeSort(dest, src, mid, high, -off);
if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0) {
dest[i] = src[p];
permutation[reversePermutation[p++]] = i;
} else {
dest[i] = src[q];
permutation[reversePermutation[q++]] = i;
}
}
for (int i = destLow; i < destHigh; ++i) {
reversePermutation[permutation[i]] = i;
}
}
private void mergeSort(Object[] src,
Object[] dest,
int low, int high, int off,
Comparator c) {
int length = high - low;
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off, c);
mergeSort(dest, src, mid, high, -off, c);
if (c.compare(src[mid-1], src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) {
dest[i] = src[p];
permutation[reversePermutation[p++]] = i;
} else {
dest[i] = src[q];
permutation[reversePermutation[q++]] = i;
}
}
for (int i = destLow; i < destHigh; ++i) {
reversePermutation[permutation[i]] = i;
}
}
private void swap(int[] x, int a, int b) {
int t = x[a];
x[a] = x[b];
x[b] = t;
permutation[reversePermutation[a]] = b;
permutation[reversePermutation[b]] = a;
int tp = reversePermutation[a];
reversePermutation[a] = reversePermutation[b];
reversePermutation[b] = tp;
}
private void swap(Object[] x, int a, int b) {
Object t = x[a];
x[a] = x[b];
x[b] = t;
permutation[reversePermutation[a]] = b;
permutation[reversePermutation[b]] = a;
int tp = reversePermutation[a];
reversePermutation[a] = reversePermutation[b];
reversePermutation[b] = tp;
}
private int[] initPermutation(int length) {
permutation = new int[length];
reversePermutation = new int[length];
for (int i = 0; i < length; ++i) {
permutation[i] = reversePermutation[i] = i;
}
return permutation;
}
}