/*
* Median.java
*
* Created on March 27, 2005, 2:05 PM
*/
package ika.utils;
/**
* Algorithm from N. Wirth's book,<br>
* implementation by N. Devillard in C,<br>
* port to Java by B. Jenny.<br>
* This code is in public domain.<br>
*
* Reference:<br>
* Author: Wirth, Niklaus<br>
* Title: Algorithms + data structures = programs<br>
* Publisher: Englewood Cliffs: Prentice-Hall, 1976<br>
* Physical description: 366 p.<br>
* Series: Prentice-Hall Series in Automatic Computation<br>
*/
public class Median {
/**
* Find the kth smallest element in the array<br>
* Notice: use median() to get the median.<br>
* Important: The passed array will be altered. The order of its
* elements will change!<br>
* @param a Array of elements. The order of the elements will be changed!
* @param k rank k, starting with 0, up to a.length-1
* @return kth element in array a
*/
public static double kth_smallest(double[] a, int k) {
final int n = a.length;
int i,j,l,m;
double x;
l=0;
m = n-1;
while (l<m) {
x=a[k];
i=l;
j=m;
do {
while (a[i]<x)
i++;
while (x<a[j])
j--;
if (i<=j) {
// ELEM_SWAP(a[i],a[j]);
final double temp = a[i];
a[i]=a[j];
a[j]=temp;
i++;
j--;
}
} while (i<=j);
if (j<k) l=i;
if (k<i) m=j;
}
return a[k];
}
/** The same for floats.
*/
public static float kth_smallest(float[] a, int k) {
final int n = a.length;
int i,j,l,m;
float x;
l=0;
m = n-1;
while (l<m) {
x=a[k];
i=l;
j=m;
do {
while (a[i]<x)
i++;
while (x<a[j])
j--;
if (i<=j) {
// ELEM_SWAP(a[i],a[j]);
final float temp = a[i];
a[i]=a[j];
a[j]=temp;
i++;
j--;
}
} while (i<=j);
if (j<k) l=i;
if (k<i) m=j;
}
return a[k];
}
/**
* Find the median of an array.<br>
* Important: The passed array will be altered if preserveOrder is false.
* The order of its elements will change!<br>
* @param a The array of values
* @param preserveOrder If true, the order of the values in a is guaranteed
* to remain the same. Passing true for preserveOrder forces median() to
* allocate a copy of a, and thus slows it down.
* @return The median value of a.
*/
public static double median(double[] a, boolean preserveOrder) {
final int n = a.length;
if (preserveOrder) {
a = (double[])(a.clone());
}
return Median.kth_smallest(a, (n%2==0) ? n/2-1 : n/2);
}
public static float median(float[] a, boolean preserveOrder) {
final int n = a.length;
if (preserveOrder) {
a = (float[])(a.clone());
}
return Median.kth_smallest(a, (n%2==0) ? n/2-1 : n/2);
}
public static float upperQuartile(float[] a) {
return Median.kth_smallest(a, a.length * 3 / 4);
}
public static float lowerQuartile(float[] a) {
return Median.kth_smallest(a, a.length / 4);
}
/**
* A few tests.
*/
/*
public static void main(String[]args) {
double[] a = {1, 2, 3};
System.out.println(Median.median(a, false));
double[] b = {4, 1, 3, 2};
System.out.println(Median.median(b, false));
double[] c = {2, 4, 1, 3};
System.out.println(Median.kth_smallest(c, 0));
System.out.println(Median.kth_smallest(c, 1));
System.out.println(Median.kth_smallest(c, 2));
System.out.println(Median.kth_smallest(c, 3));
System.out.println();
double[] d = {0, -9, 2, -3, 5, -999, 0.1, -6, 11332, -6.366, 456};
System.out.println("Median: " + Median.median(d, true));
MatrixUtils.printVector (d);
System.out.println("Median: " + Median.median(d, false));
MatrixUtils.printVector (d);
}*/
}