Median Search Demo  0.4
Median search demo (lib used by adaptive median image filter)
demo.c
Go to the documentation of this file.
1 
19 static const char rcsid[] =
20  "$Id";
21 
22 #include "medians_1D.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <time.h>
28 #include <string.h>
29 #include <math.h>
30 #include <float.h>
31 
33 #define BIG_NUM (1024*1024)
34 
36 #define MAX_ARRAY_VALUE 1024
37 
39 #define N_METHODS 5
40 
42 #define odd(x) ((x)&1)
43 
44 // Additional required function prototypes
45 void bench(int, size_t);
46 int compare(const void *, const void*);
47 void pixel_qsort(pixelvalue *, int);
48 pixelvalue median_AHU(pixelvalue *, int);
49 pixelvalue select_k(int, pixelvalue *, int);
50 
51 void bench(int verbose, size_t array_size)
52 {
53  int i;
54  int mednum;
55  pixelvalue med[N_METHODS];
56 
57  clock_t chrono;
58  double elapsed;
59 
60  pixelvalue * array_init,
61  * array;
62 
64 
68  srand48(getpid());
69 
70  if (verbose) {
71  printf("generating element values...\n");
72  fflush(stdout);
73  }
74  if (array_size<1) array_size = BIG_NUM;
75 
76  if (verbose) {
77  printf("array size: %ld\n", (long)array_size);
78  } else {
79  printf("%ld\t", (long)array_size);
80  }
81 
82  array_init = malloc(array_size * sizeof(pixelvalue));
83  array = malloc(array_size * sizeof(pixelvalue));
84 
85  if (array_init==NULL || array==NULL) {
86  printf("memory allocation failure: aborting\n");
87  return ;
88  }
89 
90  for (i=0 ; i<array_size; i++) {
91  array_init[i] = (pixelvalue)(lrand48() % MAX_ARRAY_VALUE);
92  }
93  mednum = 0;
94 
96  memcpy(array, array_init, array_size * sizeof(pixelvalue));
97  if (verbose) {
98  printf("quick select :\t");
99  fflush(stdout);
100  }
101  chrono = clock();
102  med[mednum] = quick_select(array, array_size);
103  elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC;
104  if (verbose) {
105  printf("%5.3f sec\t", elapsed);
106  fflush(stdout);
107  printf("med %g\n", (double)med[mednum]);
108  fflush(stdout);
109  } else {
110  printf("%5.3f\t", elapsed);
111  fflush(stdout);
112  }
113  mednum++;
114 
116  memcpy(array, array_init, array_size * sizeof(pixelvalue));
117  if (verbose) {
118  printf("Wirth median :\t");
119  fflush(stdout);
120  }
121  chrono = clock();
122  med[mednum] = wirth(array, array_size);
123  elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC;
124  if (verbose) {
125  printf("%5.3f sec\t", elapsed);
126  fflush(stdout);
127  printf("med %g\n", (double)med[mednum]);
128  fflush(stdout);
129  } else {
130  printf("%5.3f\t", elapsed);
131  fflush(stdout);
132  }
133  mednum++;
134 
136  memcpy(array, array_init, array_size * sizeof(pixelvalue));
137  if (verbose) {
138  printf("AHU median :\t");
139  fflush(stdout);
140  }
141  chrono = clock();
142  med[mednum] = median_AHU(array, array_size);
143  elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC;
144  if (verbose) {
145  printf("%5.3f sec\t", elapsed);
146  fflush(stdout);
147  printf("med %g\n", (double)med[mednum]);
148  fflush(stdout);
149  } else {
150  printf("%5.3f\t", elapsed);
151  fflush(stdout);
152  }
153  mednum++;
154 
156  memcpy(array, array_init, array_size * sizeof(pixelvalue));
157  if (verbose) {
158  printf("torben :\t");
159  fflush(stdout);
160  }
161  chrono = clock();
162  med[mednum] = torben(array, array_size);
163  elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC;
164  if (verbose) {
165  printf("%5.3f sec\t", elapsed);
166  fflush(stdout);
167  printf("med %g\n", (double)med[mednum]);
168  fflush(stdout);
169  } else {
170  printf("%5.3f\t", elapsed);
171  fflush(stdout);
172  }
173  mednum++;
174 
176  memcpy(array, array_init, array_size * sizeof(pixelvalue));
177  if (verbose) {
178  printf("fast pixel sort :\t");
179  fflush(stdout);
180  }
181  chrono = clock();
182  pixel_qsort(array, array_size);
183  elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC;
184 
185  if (odd(array_size)) {
186  med[mednum] = array[array_size/2];
187  } else {
188  med[mednum] = array[(array_size/2) -1];
189  }
190 
191  if (verbose) {
192  printf("%5.3f sec\t", elapsed);
193  fflush(stdout);
194  printf("med %g\n", (double)med[mednum]);
195  fflush(stdout);
196  } else {
197  printf("%5.3f\t", elapsed);
198  fflush(stdout);
199  }
200  mednum++;
201 
202  free(array);
203  free(array_init);
204 
205  for (i=1 ; i<N_METHODS ; i++) {
206  if (fabs(med[i-1] - med[i]) > 10 * FLT_EPSILON) {
207  printf("diverging median values!\n");
208  fflush(stdout);
209  }
210  }
211  printf("\n");
212  fflush(stdout);
213  return;
214 }
215 
217 int compare(const void *f1, const void *f2)
218 { return ( *(pixelvalue*)f1 > *(pixelvalue*)f2) ? 1 : -1 ; }
219 
220 
231 #define PIX_SWAP(a,b) { pixelvalue temp=(a);(a)=(b);(b)=temp; }
232 #define PIX_STACK_SIZE 50
233 
234 void pixel_qsort(pixelvalue *pix_arr, int npix)
235 {
236  int i,
237  ir,
238  j,
239  k,
240  l;
241  int * i_stack;
242  int j_stack;
243  pixelvalue a;
244 
245  ir = npix;
246  l = 1;
247  j_stack = 0;
248  i_stack = malloc(PIX_STACK_SIZE * sizeof(pixelvalue));
249  for (;;) {
250  if (ir-l < 7) {
251  for (j=l+1 ; j<=ir ; j++) {
252  a = pix_arr[j-1];
253  for (i=j-1 ; i>=1 ; i--) {
254  if (pix_arr[i-1] <= a) break;
255  pix_arr[i] = pix_arr[i-1];
256  }
257  pix_arr[i] = a;
258  }
259  if (j_stack == 0) break;
260  ir = i_stack[j_stack-- -1];
261  l = i_stack[j_stack-- -1];
262  } else {
263  k = (l+ir) >> 1;
264  PIX_SWAP(pix_arr[k-1], pix_arr[l])
265  if (pix_arr[l] > pix_arr[ir-1]) {
266  PIX_SWAP(pix_arr[l], pix_arr[ir-1])
267  }
268  if (pix_arr[l-1] > pix_arr[ir-1]) {
269  PIX_SWAP(pix_arr[l-1], pix_arr[ir-1])
270  }
271  if (pix_arr[l] > pix_arr[l-1]) {
272  PIX_SWAP(pix_arr[l], pix_arr[l-1])
273  }
274  i = l+1;
275  j = ir;
276  a = pix_arr[l-1];
277  for (;;) {
278  do i++; while (pix_arr[i-1] < a);
279  do j--; while (pix_arr[j-1] > a);
280  if (j < i) break;
281  PIX_SWAP(pix_arr[i-1], pix_arr[j-1]);
282  }
283  pix_arr[l-1] = pix_arr[j-1];
284  pix_arr[j-1] = a;
285  j_stack += 2;
286  if (j_stack > PIX_STACK_SIZE) {
287  printf("stack too small in pixel_qsort: aborting");
288  exit(-2001) ;
289  }
290  if (ir-i+1 >= j-l) {
291  i_stack[j_stack-1] = ir;
292  i_stack[j_stack-2] = i;
293  ir = j-1;
294  } else {
295  i_stack[j_stack-1] = j-1;
296  i_stack[j_stack-2] = l;
297  l = i;
298  }
299  }
300  }
301  free(i_stack);
302 }
303 #undef PIX_STACK_SIZE
304 #undef PIX_SWAP
305 
306 
316 pixelvalue select_k(int k, pixelvalue * list, int n)
317 {
318  int n1 = 0,
319  n2 = 0,
320  n3 = 0;
321  pixelvalue * S;
322  int i, j;
323  pixelvalue p;
324 
325  if (n==1) return list[0];
326  p = list[(n>>1)];
327  for (i=0 ; i<n ; i++) {
328  if (list[i]<p) {
329  n1++;
330  } else if (fabs(list[i] - p) < 10 * FLT_EPSILON) {
331  n2++;
332  } else {
333  n3++;
334  }
335  }
336  if (n1>=k) {
337  S = malloc(n1*sizeof(pixelvalue));
338  j = 0;
339  for (i=0 ; i<n ; i++) {
340  if (list[i]<p) S[j++] = list[i];
341  }
342  p = select_k(k, S, n1);
343  free(S);
344  } else {
345  if ((n1+n2)<k) {
346  S = malloc(n3 * sizeof(pixelvalue));
347  j = 0;
348  for (i=0 ; i<n ; i++) {
349  if (list[i]>p) S[j++] = list[i];
350  }
351  p = select_k(k-n1-n2, S, n3);
352  free(S);
353  }
354  }
355  return p;
356 }
357 
358 
360 pixelvalue median_AHU(pixelvalue * list, int n)
361 {
362  if (odd(n)) {
363  return select_k((n/2)+1, list, n);
364  } else {
365  return select_k((n/2), list, n);
366  }
367 }
368 
369 
371 int main(int argc, char * argv[])
372 {
373  int i;
374  int from, to, step;
375  int count;
376 
377  if (argc<2) {
378  printf("usage:\n");
379  printf("%s <n>\n", argv[0]);
380  printf("\tif n=1 the output is verbose for one attempt\n");
381  printf("\tif n>1 the output reads:\n");
382  printf("\t# of elements | method1 | method2 | ...\n");
383  printf("\n");
384  printf("%s <from> <to> <step>\n", argv[0]);
385  printf("\twill loop over the number of elements in input\n");
386  printf("\n");
387  exit(EXIT_FAILURE);
388  }
389 
390  if (argc==2) {
391  count = atoi(argv[1]);
392  if (count==1) {
393  bench(1, BIG_NUM);
394  } else {
395  printf("Size\tQS\tWirth\tAHU\tTorben\tpixel sort\n");
396  for (i=0 ; i<atoi(argv[1]) ; i++) {
397  bench(0, BIG_NUM);
398  }
399  }
400  } else if (argc==4) {
401  from = atoi(argv[1]);
402  to = atoi(argv[2]);
403  step = atoi(argv[3]);
404  for (count=from ; count<=to ; count+=step) {
405  bench(0, count);
406  }
407  return EXIT_SUCCESS;
408  }
409  return EXIT_SUCCESS;
410 }
int main(int argc, char *argv[])
Main driver demo for median search routines.
Definition: demo.c:371
int compare(const void *, const void *)
This function is only useful to the qsort() routine.
Definition: demo.c:217
pixelvalue select_k(int, pixelvalue *, int)
Called by median_AHU()
Definition: demo.c:316
static const char rcsid[]
Definition: demo.c:19
pixelvalue wirth(pixelvalue a[], int n)
Function wrapper for kth_smallest to get Wirth's median.
Definition: medians_1D.c:163
#define BIG_NUM
Number of elements in the target array.
Definition: demo.c:33
#define odd(x)
Macro to determine an integer's oddness.
Definition: demo.c:42
pixelvalue median_AHU(pixelvalue *, int)
This function uses select_k to find the median.
Definition: demo.c:360
void pixel_qsort(pixelvalue *, int)
Old and supposedly optimized quicksort algorithm.
Definition: demo.c:234
#define PIX_SWAP(a, b)
Definition: demo.c:231
pixelvalue torben(pixelvalue m[], int n)
Function implementing Torben's algorithm.
Definition: medians_1D.c:178
#define MAX_ARRAY_VALUE
Random test data; generated values are in [0...MAX_ARRAY_VALUE-1].
Definition: demo.c:36
void bench(int, size_t)
Definition: demo.c:51
#define PIX_STACK_SIZE
Definition: demo.c:232
#define N_METHODS
Number of search methods tested.
Definition: demo.c:39
pixelvalue quick_select(pixelvalue a[], int n)
Function implementing quickselect algorithm.
Definition: medians_1D.c:70