Median Search Demo  0.4
Median search demo (lib used by adaptive median image filter)
demo.c File Reference

A benchmark demo driver for medians_1D and a couple of other methods. More...

#include "medians_1D.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <float.h>
Include dependency graph for demo.c:

Go to the source code of this file.

Macros

#define BIG_NUM   (1024*1024)
 Number of elements in the target array. More...
 
#define MAX_ARRAY_VALUE   1024
 Random test data; generated values are in [0...MAX_ARRAY_VALUE-1]. More...
 
#define N_METHODS   5
 Number of search methods tested. More...
 
#define odd(x)   ((x)&1)
 Macro to determine an integer's oddness. More...
 
#define PIX_SWAP(a, b)   { pixelvalue temp=(a);(a)=(b);(b)=temp; }
 
#define PIX_STACK_SIZE   50
 

Functions

void bench (int, size_t)
 
int compare (const void *f1, const void *f2)
 This function is only useful to the qsort() routine. More...
 
void pixel_qsort (pixelvalue *, int)
 Old and supposedly optimized quicksort algorithm. More...
 
pixelvalue median_AHU (pixelvalue *list, int n)
 This function uses select_k to find the median. More...
 
pixelvalue select_k (int, pixelvalue *, int)
 Called by median_AHU() More...
 
int main (int argc, char *argv[])
 Main driver demo for median search routines. More...
 

Variables

static const char rcsid []
 

Detailed Description

A benchmark demo driver for medians_1D and a couple of other methods.

Comparison of qsort-based and optimized median search methods for a 1-D data array. The data type is flexible.

Original code by Nicolas Devillard ndevi.nosp@m.lla@.nosp@m.free..nosp@m.fr August 1998. Modified by Stephen Arnold steph.nosp@m.en.a.nosp@m.rnold.nosp@m.@acm.nosp@m..org August 2005. This code is now licensed under the LGPLv3. See the LICENSE file for details.

A note about this benchmarking method:

The reported times indicate the actual time spent on CPU, they are quite dependent on CPU load. However, the test is quite fast and it is reasonable to assume a constant machine load throughout the test.

Definition in file demo.c.

Macro Definition Documentation

#define BIG_NUM   (1024*1024)

Number of elements in the target array.

Definition at line 33 of file demo.c.

Referenced by bench(), and main().

#define MAX_ARRAY_VALUE   1024

Random test data; generated values are in [0...MAX_ARRAY_VALUE-1].

Definition at line 36 of file demo.c.

Referenced by bench().

#define N_METHODS   5

Number of search methods tested.

Definition at line 39 of file demo.c.

Referenced by bench().

#define odd (   x)    ((x)&1)

Macro to determine an integer's oddness.

Definition at line 42 of file demo.c.

Referenced by bench(), and median_AHU().

#define PIX_STACK_SIZE   50

Definition at line 232 of file demo.c.

Referenced by pixel_qsort().

#define PIX_SWAP (   a,
 
)    { pixelvalue temp=(a);(a)=(b);(b)=temp; }

Definition at line 231 of file demo.c.

Referenced by pixel_qsort().

Function Documentation

void bench ( int  verbose,
size_t  array_size 
)

Random number seed

Initialize random generator with PID. This is the only Unix-ish thing; can be replaced with an alternate scheme.

benchmark the quickselect sort

benchmark wirth function

benchmark AHU sort

benchmark torben's method

benchmark the eclipse fast pixel sort

Definition at line 51 of file demo.c.

References BIG_NUM, MAX_ARRAY_VALUE, median_AHU(), N_METHODS, odd, pixel_qsort(), quick_select(), torben(), and wirth().

Referenced by main().

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 }
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
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
#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

Here is the call graph for this function:

Here is the caller graph for this function:

int compare ( const void *  f1,
const void *  f2 
)

This function is only useful to the qsort() routine.

Definition at line 217 of file demo.c.

218 { return ( *(pixelvalue*)f1 > *(pixelvalue*)f2) ? 1 : -1 ; }
int main ( int  argc,
char *  argv[] 
)

Main driver demo for median search routines.

Definition at line 371 of file demo.c.

References bench(), and BIG_NUM.

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 }
#define BIG_NUM
Number of elements in the target array.
Definition: demo.c:33
void bench(int, size_t)
Definition: demo.c:51

Here is the call graph for this function:

pixelvalue median_AHU ( pixelvalue *  list,
int  n 
)

This function uses select_k to find the median.

Definition at line 360 of file demo.c.

References odd, and select_k().

Referenced by bench().

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 }
pixelvalue select_k(int, pixelvalue *, int)
Called by median_AHU()
Definition: demo.c:316
#define odd(x)
Macro to determine an integer's oddness.
Definition: demo.c:42

Here is the call graph for this function:

Here is the caller graph for this function:

void pixel_qsort ( pixelvalue *  pix_arr,
int  npix 
)

Old and supposedly optimized quicksort algorithm.

Function : pixel_qsort()

  • In : pixel array, size of the array
  • Out : void
  • Job : sort out the array of pixels
  • Note : optimized implementation, unreadable.

Definition at line 234 of file demo.c.

References PIX_STACK_SIZE, and PIX_SWAP.

Referenced by bench().

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 }
#define PIX_SWAP(a, b)
Definition: demo.c:231
#define PIX_STACK_SIZE
Definition: demo.c:232

Here is the caller graph for this function:

pixelvalue select_k ( int  k,
pixelvalue *  list,
int  n 
)

Called by median_AHU()

Function : select_k()

  • In : element to search for, list of pixelvalues, # of values
  • Out : pixelvalue
  • Job : find out the kth smallest value of the list
  • Note : recursively called by median_AHU()

Definition at line 316 of file demo.c.

Referenced by median_AHU().

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 }
pixelvalue select_k(int, pixelvalue *, int)
Called by median_AHU()
Definition: demo.c:316

Here is the caller graph for this function:

Variable Documentation

const char rcsid[]
static
Initial value:
=
"$Id"

Definition at line 19 of file demo.c.