Algorithm-Cluster

 view release on metacpan or  search on metacpan

src/cluster.c  view on Meta::CPAN

}

/* ************************************************************************ */

double
median(int n, double x[])
/*
Find the median of X(1), ... , X(N), using as much of the quicksort
algorithm as is needed to isolate it.
N.B. On exit, the array X is partially ordered.
Based on Alan J. Miller's median.f90 routine.
*/

{
    int i, j;
    int nr = n / 2;
    int nl = nr - 1;
    int even = 0;
    /* hi & lo are position limits encompassing the median. */
    int lo = 0;
    int hi = n-1;

    if (n == 2*nr) even = 1;
    if (n < 3) {
        if (n < 1) return 0.;
        if (n == 1) return x[0];
        return 0.5*(x[0]+x[1]);
    }

    /* Find median of 1st, middle & last values. */
    do {
        int loop;
        int mid = (lo + hi)/2;
        double result = x[mid];
        double xlo = x[lo];
        double xhi = x[hi];
        if (xhi<xlo) {
            double temp = xlo;
            xlo = xhi;
            xhi = temp;
        }
        if (result>xhi) result = xhi;
        else if (result<xlo) result = xlo;
        /* The basic quicksort algorithm to move all values <= the sort key
         * (XMED) to the left-hand end, and all higher values to the other end.
         */
        i = lo;
        j = hi;
        do {
            while (x[i]<result) i++;
            while (x[j]>result) j--;
            loop = 0;
            if (i<j) {
                double temp = x[i];
                x[i] = x[j];
                x[j] = temp;
                i++;
                j--;
                if (i<=j) loop = 1;
            }
        } while (loop); /* Decide which half the median is in. */

        if (even) {
            if (j == nl && i == nr) {
                /* Special case, n even, j = n/2 & i = j + 1, so the median is
                 * between the two halves of the series. Find max. of the first
                 * half & min. of the second half, then average.
                 */
                int k;
                double xmax = x[0];
                double xmin = x[n-1];
                for (k = lo; k <= j; k++) xmax = max(xmax, x[k]);
                for (k = i; k <= hi; k++) xmin = min(xmin, x[k]);
                return 0.5*(xmin + xmax);
            }
            if (j<nl) lo = i;
            if (i>nr) hi = j;
            if (i == j) {
                if (i == nl) lo = nl;
                if (j == nr) hi = nr;
            }
        }
        else {
            if (j<nr) lo = i;
            if (i>nr) hi = j;
            /* Test whether median has been isolated. */
            if (i == j && i == nr) return result;
        }
    }
    while (lo<hi-1);

    if (even) return (0.5*(x[nl]+x[nr]));
    if (x[lo]>x[hi]) {
        double temp = x[lo];
        x[lo] = x[hi];
        x[hi] = temp;
    }
    return x[nr];
}

/* ********************************************************************** */

static const double* sortdata = NULL; /* used in the quicksort algorithm */

/* ---------------------------------------------------------------------- */

static int
compare(const void* a, const void* b)
/* Helper function for sort. Previously, this was a nested function under
 * sort, which is not allowed under ANSI C.
 */
{
    const int i1 = *(const int*)a;
    const int i2 = *(const int*)b;
    const double term1 = sortdata[i1];
    const double term2 = sortdata[i2];

    if (term1 < term2) return -1;
    if (term1 > term2) return +1;
    return 0;
}



( run in 0.612 second using v1.01-cache-2.11-cpan-e1769b4cff6 )