/*
 * Copyright (c) 2012-2018, Peter Abeles. All Rights Reserved.
 *
 * This file is part of DDogleg (http://ddogleg.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ddogleg.sorting;


/**
 * <p>
 * QuickSelect searches for the k-th largest item in the list.  While doing this search
 * it will sort the list partially.  all the items below k will have a value less than it
 * and all the items more than k will have a value greater than it.  However the values
 * above and below can be unsorted.  QuickSelect is faster than QuickSort of you don't
 * need a fully sorted list.
 * </p>
 * <p>
 * An implementation of the quick select algorithm from Numerical Recipes Third Edition
 * that is specified for arrays of doubles.  See page 433.
 * </p>
 *
 * <p>DO NOT MODIFY. AUTOGENERATED CODE. GenerateQuickSelect</p>
 *
 * @author Peter Abeles
 */
public class QuickSelect {

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convenience the 'k' element is returned.
	 *
	 * @param data The unsorted list
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static Comparable select( Comparable[]data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		Comparable a;
		int l = 0;
		int ir = n-1;

		Comparable temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir].compareTo(data[l]) < 0 ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l].compareTo(data[ir]) > 0 ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1].compareTo( data[ir] ) > 0 ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l].compareTo(data[lp1]) > 0 ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i].compareTo(a) < 0);
					do j--; while (data[j].compareTo(a) > 0);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convenience the 'k' element is returned.
	 *
	 * @param data The unsorted list.  Not modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @param indexes (output) Sorted list of indexes.
	 * @return the 'k'th largest element
	 */
	public static Comparable select( Comparable[]data , int k , int maxIndex , int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]].compareTo(data[indexes[l]]) < 0 ) {

					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]].compareTo(data[indexes[ir]]) > 0 ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]].compareTo( data[indexes[ir]] ) > 0 ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]].compareTo(data[indexes[lp1]]) > 0 ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]].compareTo(data[a]) < 0);
					do j--; while (data[indexes[j]].compareTo(data[a]) > 0);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convinience the 'k' element is returned.
	 *
	 * @param data The unsorted list. Is modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static float select( float []data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		float a;
		int l = 0;
		int ir = n-1;

		float temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir] < data[l] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l] > data[ir] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1] > data[ir] ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l] > data[lp1] ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i]<a);
					do j--; while (data[j]>a);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * <p>
	 * Returns the original index of the 'k' largest element in the list.
	 * </p>
	 * 
	 * <p>
	 * Note: There is additional overhead since the values of indexes needs to be set
	 * </p>
	 * 
	 * @param indexes Temporary storage and is overwritten
	 */
	public static int selectIndex( float []data , int k , int maxIndex ,  int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]] < data[indexes[l]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return indexes[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]] > data[indexes[ir]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]] > data[indexes[ir]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]] > data[indexes[lp1]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]]<data[a]);
					do j--; while (data[indexes[j]]>data[a]);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convinience the 'k' element is returned.
	 *
	 * @param data The unsorted list. Is modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static double select( double []data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		double a;
		int l = 0;
		int ir = n-1;

		double temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir] < data[l] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l] > data[ir] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1] > data[ir] ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l] > data[lp1] ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i]<a);
					do j--; while (data[j]>a);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * <p>
	 * Returns the original index of the 'k' largest element in the list.
	 * </p>
	 * 
	 * <p>
	 * Note: There is additional overhead since the values of indexes needs to be set
	 * </p>
	 * 
	 * @param indexes Temporary storage and is overwritten
	 */
	public static int selectIndex( double []data , int k , int maxIndex ,  int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]] < data[indexes[l]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return indexes[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]] > data[indexes[ir]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]] > data[indexes[ir]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]] > data[indexes[lp1]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]]<data[a]);
					do j--; while (data[indexes[j]]>data[a]);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convinience the 'k' element is returned.
	 *
	 * @param data The unsorted list. Is modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static long select( long []data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		long a;
		int l = 0;
		int ir = n-1;

		long temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir] < data[l] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l] > data[ir] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1] > data[ir] ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l] > data[lp1] ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i]<a);
					do j--; while (data[j]>a);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * <p>
	 * Returns the original index of the 'k' largest element in the list.
	 * </p>
	 * 
	 * <p>
	 * Note: There is additional overhead since the values of indexes needs to be set
	 * </p>
	 * 
	 * @param indexes Temporary storage and is overwritten
	 */
	public static int selectIndex( long []data , int k , int maxIndex ,  int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]] < data[indexes[l]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return indexes[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]] > data[indexes[ir]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]] > data[indexes[ir]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]] > data[indexes[lp1]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]]<data[a]);
					do j--; while (data[indexes[j]]>data[a]);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convinience the 'k' element is returned.
	 *
	 * @param data The unsorted list. Is modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static int select( int []data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir] < data[l] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l] > data[ir] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1] > data[ir] ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l] > data[lp1] ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i]<a);
					do j--; while (data[j]>a);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * <p>
	 * Returns the original index of the 'k' largest element in the list.
	 * </p>
	 * 
	 * <p>
	 * Note: There is additional overhead since the values of indexes needs to be set
	 * </p>
	 * 
	 * @param indexes Temporary storage and is overwritten
	 */
	public static int selectIndex( int []data , int k , int maxIndex ,  int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]] < data[indexes[l]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return indexes[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]] > data[indexes[ir]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]] > data[indexes[ir]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]] > data[indexes[lp1]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]]<data[a]);
					do j--; while (data[indexes[j]]>data[a]);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convinience the 'k' element is returned.
	 *
	 * @param data The unsorted list. Is modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static short select( short []data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		short a;
		int l = 0;
		int ir = n-1;

		short temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir] < data[l] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l] > data[ir] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1] > data[ir] ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l] > data[lp1] ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i]<a);
					do j--; while (data[j]>a);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * <p>
	 * Returns the original index of the 'k' largest element in the list.
	 * </p>
	 * 
	 * <p>
	 * Note: There is additional overhead since the values of indexes needs to be set
	 * </p>
	 * 
	 * @param indexes Temporary storage and is overwritten
	 */
	public static int selectIndex( short []data , int k , int maxIndex ,  int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]] < data[indexes[l]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return indexes[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]] > data[indexes[ir]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]] > data[indexes[ir]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]] > data[indexes[lp1]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]]<data[a]);
					do j--; while (data[indexes[j]]>data[a]);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * Sorts the array such that the values in the array up to and including
	 * 'k' are sorted the least to greatest.  This implies that the array
	 * itself is modified. For convinience the 'k' element is returned.
	 *
	 * @param data The unsorted list. Is modified.
	 * @param k The element of the sorted list that is to be found
	 * @param maxIndex Only element up to this value are considered
	 * @return the 'k'th largest element
	 */
	public static byte select( byte []data , int k , int maxIndex ) {

		int i,j,mid;
		int n = maxIndex;
		byte a;
		int l = 0;
		int ir = n-1;

		byte temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[ir] < data[l] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}
				return data[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = data[mid];
				data[mid] = data[lp1];
				data[lp1] = temp;

				if( data[l] > data[ir] ) {
					temp = data[l];
					data[l] = data[ir];
					data[ir] = temp;
				}

				if( data[lp1] > data[ir] ) {
					temp = data[lp1];
					data[lp1] = data[ir];
					data[ir] = temp;
				}

				if( data[l] > data[lp1] ) {
					temp = data[lp1];
					data[lp1] = data[l];
					data[l] = temp;
				}

				i=lp1;
				j=ir;
				a=data[lp1];

				for(;;) {
					do i++; while(data[i]<a);
					do j--; while (data[j]>a);
					if( j < i) break;
					temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
				data[lp1] = data[j];
				data[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}

	/**
	 * <p>
	 * Returns the original index of the 'k' largest element in the list.
	 * </p>
	 * 
	 * <p>
	 * Note: There is additional overhead since the values of indexes needs to be set
	 * </p>
	 * 
	 * @param indexes Temporary storage and is overwritten
	 */
	public static int selectIndex( byte []data , int k , int maxIndex ,  int []indexes) {

		for( int i = 0; i < maxIndex; i++ ) {
			indexes[i] = i;
		}

		int i,j,mid;
		int n = maxIndex;
		int a;
		int l = 0;
		int ir = n-1;

		int temp;

		for(;;) {
			if( ir <= l+1 ) {
				if( ir == l+1 && data[indexes[ir]] < data[indexes[l]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}
				return indexes[k];
			} else {
				mid = (l+ir) >> 1;

				int lp1 = l+1;
				temp = indexes[mid];
				indexes[mid] = indexes[lp1];
				indexes[lp1] = temp;

				if( data[indexes[l]] > data[indexes[ir]] ) {
					temp = indexes[l];
					indexes[l] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[lp1]] > data[indexes[ir]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[ir];
					indexes[ir] = temp;
				}

				if( data[indexes[l]] > data[indexes[lp1]] ) {
					temp = indexes[lp1];
					indexes[lp1] = indexes[l];
					indexes[l] = temp;
				}

				i=lp1;
				j=ir;
				a=indexes[lp1];

				for(;;) {
					do i++; while(data[indexes[i]]<data[a]);
					do j--; while (data[indexes[j]]>data[a]);
					if( j < i) break;
					temp = indexes[i];
					indexes[i] = indexes[j];
					indexes[j] = temp;
				}
				indexes[lp1] = indexes[j];
				indexes[j] = a;
				if( j >= k ) ir=j-1;
				if( j <= k ) l=i;
			}
		}
	}


}
