/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #include "mpiimpl.h" #include #include #define GROUPSIZE 5 /* Insertion sort on array 'a' containing n elements */ static inline void isort(int a[], const int n) { int i; int j; int key; for (j = 1; j < n; ++j) { key = a[j]; i = j - 1; while (i >= 0 && a[i] > key) { a[i+1] = a[i]; i -= 1; } a[i+1] = key; } } /* Partition array 'a' of size n around the value pivot and returns * the index of the pivot point */ static inline int partition(const int pivot, int a[], const int n) { int i = 0; int j = n-1; int tmp; while (1) { while ((j > 0) && (a[j] < pivot)) --j; while ((i < n) && (a[i] >= pivot)) ++i; if (i < j) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; } else { return j; } } } /* This does all of the work for k_select */ static void k_select_r(const int k, int a[], const int n, int *value) { int ngroups; int i; int median_median; int surfeit; int mk; int *medians; assert (k < n); ngroups = (n + GROUPSIZE-1) / GROUPSIZE; medians = MPIU_Malloc(ngroups * sizeof (int)); /* Divide 'a' into groups, sort the elements of each group and pull out the median of each group */ for (i = 0; i < ngroups-1; ++i) { isort(&a[i * GROUPSIZE], GROUPSIZE); medians[i] = a[i*GROUPSIZE + GROUPSIZE/2]; } surfeit = (n - i * GROUPSIZE); isort(&a[i * GROUPSIZE], surfeit); medians[i] = a[i*GROUPSIZE + surfeit/2]; if (ngroups == 1) { *value = a[n - 1 - k]; MPIU_Free(medians); return; } /* use k_select to find the median of medians */ k_select_r((ngroups / 2) - 1 + (ngroups % 2), medians, ngroups, &median_median); MPIU_Free(medians); /* partition array a around the median of medians and return the index of the median of medians */ mk = partition(median_median, a, n); /* if this is the last element, we're done */ if (mk == n - 1) *value = a[mk]; else if (k <= mk) /* call k_select to find the kth element in a[0..mk-1] (the array up to the element before the median of medians) */ k_select_r(k, &a[0], mk + 1, value); else /* call k_select to find the (k-mk)th element in a[mk+1..n] (the array starting from the element after the median of medians) */ k_select_r(k - (mk+1), &a[mk+1], n - (mk+1), value); } /* Returns the value of the kth smallest element in array a of size * n. Allocates an array and calls the recursive function k_select_r * which does all the work */ static void k_select(const int k, int a[], const int n, int *value) { k_select_r(k - 1, a, n, value); } /* silence "no previous prototype" warnings */ int MPIU_Outlier_ratio(int * sizes, int n_sizes, double outlier_frac, double threshold); /* Returns the ratio of the maximum size and the outlier_frac * percentile size. */ int MPIU_Outlier_ratio(int * sizes, int n_sizes, double outlier_frac, double threshold) { int max, k_max, i; double retval; k_select(n_sizes, sizes, n_sizes, &max); max = sizes[0]; for (i = 0; i < n_sizes; i++) if (max < sizes[i]) max = sizes[i]; k_select((int) (n_sizes * outlier_frac), sizes, n_sizes, &k_max); retval = (double) max / k_max; if (retval > threshold) { return 1; } else { return 0; } }