00001
00018 static const char rcsid[] =
00019 "$Id";
00020
00021 #include "medians_1D.h"
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <time.h>
00027 #include <string.h>
00028 #include <math.h>
00029 #include <float.h>
00030
00032 #define BIG_NUM (1024*1024)
00033
00035 #define MAX_ARRAY_VALUE 1024
00036
00038 #define N_METHODS 5
00039
00041 #define odd(x) ((x)&1)
00042
00043
00044 void bench(int, size_t);
00045 int compare(const void *, const void*);
00046 void pixel_qsort(pixelvalue *, int);
00047 pixelvalue median_AHU(pixelvalue *, int);
00048 pixelvalue select_k(int, pixelvalue *, int);
00049
00050 void bench(int verbose, size_t array_size)
00051 {
00052 int i ;
00053 int mednum ;
00054 pixelvalue med[N_METHODS] ;
00055
00056 clock_t chrono ;
00057 double elapsed ;
00058
00059 pixelvalue * array_init,
00060 * array ;
00061
00063
00067 srand48(getpid()) ;
00068
00069 if (verbose) {
00070 printf("generating element values...\n") ;
00071 fflush(stdout) ;
00072 }
00073 if (array_size<1) array_size = BIG_NUM ;
00074
00075 if (verbose) {
00076 printf("array size: %ld\n", (long)array_size) ;
00077 } else {
00078 printf("%ld\t", (long)array_size) ;
00079 }
00080
00081 array_init = malloc(array_size * sizeof(pixelvalue)) ;
00082 array = malloc(array_size * sizeof(pixelvalue)) ;
00083
00084 if (array_init==NULL || array==NULL) {
00085 printf("memory allocation failure: aborting\n") ;
00086 return ;
00087 }
00088
00089 for (i=0 ; i<array_size; i++) {
00090 array_init[i] = (pixelvalue)(lrand48() % MAX_ARRAY_VALUE) ;
00091 }
00092 mednum = 0 ;
00093
00095 memcpy(array, array_init, array_size * sizeof(pixelvalue)) ;
00096 if (verbose) {
00097 printf("quick select :\t") ;
00098 fflush(stdout) ;
00099 }
00100 chrono = clock() ;
00101 med[mednum] = quick_select(array, array_size) ;
00102 elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC ;
00103 if (verbose) {
00104 printf("%5.3f sec\t", elapsed) ;
00105 fflush(stdout) ;
00106 printf("med %g\n", (double)med[mednum]) ;
00107 fflush(stdout) ;
00108 } else {
00109 printf("%5.3f\t", elapsed) ;
00110 fflush(stdout) ;
00111 }
00112 mednum++ ;
00113
00115 memcpy(array, array_init, array_size * sizeof(pixelvalue)) ;
00116 if (verbose) {
00117 printf("Wirth median :\t") ;
00118 fflush(stdout) ;
00119 }
00120 chrono = clock() ;
00121 med[mednum] = wirth(array, array_size) ;
00122 elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC ;
00123 if (verbose) {
00124 printf("%5.3f sec\t", elapsed) ;
00125 fflush(stdout) ;
00126 printf("med %g\n", (double)med[mednum]) ;
00127 fflush(stdout) ;
00128 } else {
00129 printf("%5.3f\t", elapsed) ;
00130 fflush(stdout) ;
00131 }
00132 mednum++ ;
00133
00135 memcpy(array, array_init, array_size * sizeof(pixelvalue)) ;
00136 if (verbose) {
00137 printf("AHU median :\t") ;
00138 fflush(stdout) ;
00139 }
00140 chrono = clock() ;
00141 med[mednum] = median_AHU(array, array_size) ;
00142 elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC ;
00143 if (verbose) {
00144 printf("%5.3f sec\t", elapsed) ;
00145 fflush(stdout) ;
00146 printf("med %g\n", (double)med[mednum]) ;
00147 fflush(stdout) ;
00148 } else {
00149 printf("%5.3f\t", elapsed) ;
00150 fflush(stdout) ;
00151 }
00152 mednum++ ;
00153
00155 memcpy(array, array_init, array_size * sizeof(pixelvalue)) ;
00156 if (verbose) {
00157 printf("torben :\t") ;
00158 fflush(stdout) ;
00159 }
00160 chrono = clock() ;
00161 med[mednum] = torben(array, array_size) ;
00162 elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC ;
00163 if (verbose) {
00164 printf("%5.3f sec\t", elapsed) ;
00165 fflush(stdout) ;
00166 printf("med %g\n", (double)med[mednum]) ;
00167 fflush(stdout) ;
00168 } else {
00169 printf("%5.3f\t", elapsed) ;
00170 fflush(stdout) ;
00171 }
00172 mednum++ ;
00173
00175 memcpy(array, array_init, array_size * sizeof(pixelvalue)) ;
00176 if (verbose) {
00177 printf("fast pixel sort :\t") ;
00178 fflush(stdout) ;
00179 }
00180 chrono = clock() ;
00181 pixel_qsort(array, array_size) ;
00182 elapsed = (double)(clock() - chrono) / (double)CLOCKS_PER_SEC ;
00183
00184 if (odd(array_size)) {
00185 med[mednum] = array[array_size/2] ;
00186 } else {
00187 med[mednum] = array[(array_size/2) -1] ;
00188 }
00189
00190 if (verbose) {
00191 printf("%5.3f sec\t", elapsed) ;
00192 fflush(stdout) ;
00193 printf("med %g\n", (double)med[mednum]) ;
00194 fflush(stdout) ;
00195 } else {
00196 printf("%5.3f\t", elapsed) ;
00197 fflush(stdout) ;
00198 }
00199 mednum++ ;
00200
00201 free(array) ;
00202 free(array_init) ;
00203
00204 for (i=1 ; i<N_METHODS ; i++) {
00205 if (fabs(med[i-1] - med[i]) > 10 * FLT_EPSILON) {
00206 printf("diverging median values!\n") ;
00207 fflush(stdout) ;
00208 }
00209 }
00210 printf("\n") ;
00211 fflush(stdout) ;
00212 return ;
00213 }
00214
00216 int compare(const void *f1, const void *f2)
00217 { return ( *(pixelvalue*)f1 > *(pixelvalue*)f2) ? 1 : -1 ; }
00218
00219
00230 #define PIX_SWAP(a,b) { pixelvalue temp=(a);(a)=(b);(b)=temp; }
00231 #define PIX_STACK_SIZE 50
00232
00233 void pixel_qsort(pixelvalue *pix_arr, int npix)
00234 {
00235 int i,
00236 ir,
00237 j,
00238 k,
00239 l;
00240 int * i_stack ;
00241 int j_stack ;
00242 pixelvalue a ;
00243
00244 ir = npix ;
00245 l = 1 ;
00246 j_stack = 0 ;
00247 i_stack = malloc(PIX_STACK_SIZE * sizeof(pixelvalue)) ;
00248 for (;;) {
00249 if (ir-l < 7) {
00250 for (j=l+1 ; j<=ir ; j++) {
00251 a = pix_arr[j-1];
00252 for (i=j-1 ; i>=1 ; i--) {
00253 if (pix_arr[i-1] <= a) break;
00254 pix_arr[i] = pix_arr[i-1];
00255 }
00256 pix_arr[i] = a;
00257 }
00258 if (j_stack == 0) break;
00259 ir = i_stack[j_stack-- -1];
00260 l = i_stack[j_stack-- -1];
00261 } else {
00262 k = (l+ir) >> 1;
00263 PIX_SWAP(pix_arr[k-1], pix_arr[l])
00264 if (pix_arr[l] > pix_arr[ir-1]) {
00265 PIX_SWAP(pix_arr[l], pix_arr[ir-1])
00266 }
00267 if (pix_arr[l-1] > pix_arr[ir-1]) {
00268 PIX_SWAP(pix_arr[l-1], pix_arr[ir-1])
00269 }
00270 if (pix_arr[l] > pix_arr[l-1]) {
00271 PIX_SWAP(pix_arr[l], pix_arr[l-1])
00272 }
00273 i = l+1;
00274 j = ir;
00275 a = pix_arr[l-1];
00276 for (;;) {
00277 do i++; while (pix_arr[i-1] < a);
00278 do j--; while (pix_arr[j-1] > a);
00279 if (j < i) break;
00280 PIX_SWAP(pix_arr[i-1], pix_arr[j-1]);
00281 }
00282 pix_arr[l-1] = pix_arr[j-1];
00283 pix_arr[j-1] = a;
00284 j_stack += 2;
00285 if (j_stack > PIX_STACK_SIZE) {
00286 printf("stack too small in pixel_qsort: aborting");
00287 exit(-2001) ;
00288 }
00289 if (ir-i+1 >= j-l) {
00290 i_stack[j_stack-1] = ir;
00291 i_stack[j_stack-2] = i;
00292 ir = j-1;
00293 } else {
00294 i_stack[j_stack-1] = j-1;
00295 i_stack[j_stack-2] = l;
00296 l = i;
00297 }
00298 }
00299 }
00300 free(i_stack) ;
00301 }
00302 #undef PIX_STACK_SIZE
00303 #undef PIX_SWAP
00304
00305
00315 pixelvalue select_k(int k, pixelvalue * list, int n)
00316 {
00317 int n1 = 0,
00318 n2 = 0,
00319 n3 = 0 ;
00320 pixelvalue * S ;
00321 int i, j ;
00322 pixelvalue p ;
00323
00324 if (n==1) return list[0] ;
00325 p = list[(n>>1)] ;
00326 for (i=0 ; i<n ; i++) {
00327 if (list[i]<p) {
00328 n1++ ;
00329 } else if (fabs(list[i] - p) < 10 * FLT_EPSILON) {
00330 n2++ ;
00331 } else {
00332 n3++ ;
00333 }
00334 }
00335 if (n1>=k) {
00336 S = malloc(n1*sizeof(pixelvalue)) ;
00337 j = 0 ;
00338 for (i=0 ; i<n ; i++) {
00339 if (list[i]<p) S[j++] = list[i] ;
00340 }
00341 p = select_k(k, S, n1) ;
00342 free(S) ;
00343 } else {
00344 if ((n1+n2)<k) {
00345 S = malloc(n3 * sizeof(pixelvalue)) ;
00346 j = 0 ;
00347 for (i=0 ; i<n ; i++) {
00348 if (list[i]>p) S[j++] = list[i] ;
00349 }
00350 p = select_k(k-n1-n2, S, n3) ;
00351 free(S) ;
00352 }
00353 }
00354 return p ;
00355 }
00356
00357
00359 pixelvalue median_AHU(pixelvalue * list, int n)
00360 {
00361 if (odd(n)) {
00362 return select_k((n/2)+1, list, n) ;
00363 } else {
00364 return select_k((n/2), list, n) ;
00365 }
00366 }
00367
00368
00370 int main(int argc, char * argv[])
00371 {
00372 int i ;
00373 int from, to, step ;
00374 int count ;
00375
00376 if (argc<2) {
00377 printf("usage:\n") ;
00378 printf("%s <n>\n", argv[0]) ;
00379 printf("\tif n=1 the output is verbose for one attempt\n") ;
00380 printf("\tif n>1 the output reads:\n") ;
00381 printf("\t# of elements | method1 | method2 | ...\n") ;
00382 printf("\n") ;
00383 printf("%s <from> <to> <step>\n", argv[0]) ;
00384 printf("\twill loop over the number of elements in input\n") ;
00385 printf("\n") ;
00386 return 0 ;
00387 }
00388
00389 if (argc==2) {
00390 count = atoi(argv[1]) ;
00391 if (count==1) {
00392 bench(1, BIG_NUM) ;
00393 } else {
00394 printf("Size\tQS\tWirth\tAHU\tTorben\tpixel sort\n") ;
00395 for (i=0 ; i<atoi(argv[1]) ; i++) {
00396 bench(0, BIG_NUM) ;
00397 }
00398 }
00399 } else if (argc==4) {
00400 from = atoi(argv[1]) ;
00401 to = atoi(argv[2]) ;
00402 step = atoi(argv[3]) ;
00403 for (count=from ; count<=to ; count+=step) {
00404 bench(0, count) ;
00405 }
00406 return 0 ;
00407 }
00408
00409 }
00410
00411