bit_scan_test.c

00001 /* $Id$
00002  * 
00003  * test bit_scan operations from bit_scan.h
00004  *  (both for correctness  and speed)
00005  * 
00006  * Copyright (C) 2007 iptelorg GmbH
00007  *
00008  * Permission to use, copy, modify, and distribute this software for any
00009  * purpose with or without fee is hereby granted, provided that the above
00010  * copyright notice and this permission notice appear in all copies.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00013  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00014  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00015  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00016  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00017  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00018  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00019  */
00020 /* 
00021  * Example gcc command line:
00022  *  gcc -O9 -Wall -DCC_GCC_LIKE_ASM  -D__CPU_x86 bit_scan_test.c ../bit_scan.c
00023  *      -o bit_scan_test
00024  *
00025  * History:
00026  * --------
00027  *  2007-06-23  created by andrei
00028  */
00029 
00030 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 
00034 
00035 #define BIT_SCAN_DEBRUIJN
00036 #define BIT_SCAN_BRANCH
00037 #define BIT_SCAN_SLOW
00038 
00039 #include "../bit_scan.h"
00040 #ifdef NO_PROFILE
00041 #define profile_init(x,y)  do{}while(0)
00042 #define profile_start(x)  do{}while(0)
00043 #define profile_end(x)  do{}while(0)
00044 #define PROFILE_PRINT(x) do{}while(0)
00045 #else
00046 #include "profile.h"
00047 #endif
00048 
00049 #define CHECK(txt, v1, val, f, pd) \
00050         do{ \
00051                 unsigned long long ret; \
00052                 profile_start(pd); \
00053                 ret=(unsigned long long)f(val); \
00054                 profile_end(pd); \
00055                 if ((unsigned long long)v1!=ret){ \
00056                         fprintf(stderr, "ERROR:" #f ": %s, expected %llx (%llx), got"\
00057                                         " %llx\n", \
00058                                         (txt), (unsigned long long)v1, \
00059                                         (unsigned long long)val, ret); \
00060                         exit(-1); \
00061                 } \
00062         }while(0)
00063 
00064 #ifndef PROFILE_PRINT
00065 #define PROFILE_PRINT(pd) \
00066         do{ \
00067                 printf("profile: %s (%ld/%ld) total %llu max %llu average %llu\n", \
00068                                 (pd)->name,  (pd)->entries, (pd)->exits, \
00069                                 (pd)->total_cycles,  (pd)->max_cycles, \
00070                                 (pd)->entries? \
00071                                 (pd)->total_cycles/(unsigned long long)(pd)->entries:0ULL ); \
00072         }while(0)
00073 #endif
00074 
00075 int main(int argc, char** argv)
00076 {
00077         int r;
00078         unsigned int v;
00079         unsigned long long ll;
00080         int i;
00081 #ifndef NO_PROFILE
00082         struct profile_data pdf1, pdf2, pdf4, pdf5, pdf6, pdf8;
00083         struct profile_data pdl1, pdl2, pdl4, pdl5, pdl6, pdl8;
00084 #ifdef HAS_BIT_SCAN_ASM
00085         struct profile_data pdf3, pdf7, pdl3, pdl7;
00086 #endif
00087         struct profile_data pdf_32, pdf_64, pdl_32, pdl_64;
00088         struct profile_data pdf_long, pdl_long;
00089 #endif /* NO_PROFILE */
00090         
00091         profile_init(&pdf1, "first_debruijn32");
00092         profile_init(&pdf2, "first_slow32");
00093 #ifdef HAS_BIT_SCAN_ASM
00094         profile_init(&pdf3, "first_asm32");
00095 #endif
00096         profile_init(&pdf4, "first_br32");
00097         profile_init(&pdf5, "first_debruijn64");
00098         profile_init(&pdf6, "first_slow64");
00099 #ifdef HAS_BIT_SCAN_ASM
00100         profile_init(&pdf7, "first_asm64");
00101 #endif
00102         profile_init(&pdf8, "first_br64");
00103         profile_init(&pdl1, "last_debruijn32");
00104         profile_init(&pdl2, "last_slow32");
00105 #ifdef HAS_BIT_SCAN_ASM
00106         profile_init(&pdl3, "last_asm32");
00107 #endif
00108         profile_init(&pdl4, "last_br32");
00109         profile_init(&pdl5, "last_debruijn64");
00110         profile_init(&pdl6, "last_slow64");
00111 #ifdef HAS_BIT_SCAN_ASM
00112         profile_init(&pdl7, "last_asm64");
00113 #endif
00114         profile_init(&pdl8, "last_br64");
00115         
00116         profile_init(&pdf_32, "scan_forward32");
00117         profile_init(&pdf_64, "scan_forward64");
00118         profile_init(&pdl_32, "scan_reverse32");
00119         profile_init(&pdl_64, "scan_reverse64");
00120         profile_init(&pdf_long, "scan_forward_l");
00121         profile_init(&pdl_long, "scan_reverse_l");
00122 
00123 
00124         for (i=0; i<100; i++){
00125         for (r=0; r<32; r++){
00126                 v=(1U<<r);
00127                 CHECK("first debruijn 32bit", r, v, bit_scan_forward_debruijn32, &pdf1);
00128                 CHECK("first slow 32bit", r, v, bit_scan_forward_slow32, &pdf2);
00129 #ifdef HAS_BIT_SCAN_ASM
00130                 CHECK("first asm 32bit", r, v, bit_scan_forward_asm32, &pdf3);
00131 #endif
00132                 CHECK("first br 32bit", r, v, bit_scan_forward_br32, &pdf4);
00133                 CHECK("scan_forward32", r, v, bit_scan_forward32, &pdf_32);
00134                 if (sizeof(long)<=4){
00135                         CHECK("scan_forward_l", r, v, bit_scan_forward, &pdf_long);
00136                 }
00137                 v+=(v-1);
00138                 CHECK("last debruijn 32bit", r, v, bit_scan_reverse_debruijn32, &pdl1);
00139                 CHECK("last slow 32bit", r, v, bit_scan_reverse_slow32, &pdl2);
00140 #ifdef HAS_BIT_SCAN_ASM
00141                 CHECK("last asm 32bit", r, v, bit_scan_reverse_asm32, &pdl3);
00142 #endif
00143                 CHECK("last br 32bit", r, v, bit_scan_reverse_br32, &pdl4);
00144                 CHECK("scan_reverse32", r, v, bit_scan_reverse32, &pdl_32);
00145                 if (sizeof(long)<=4){
00146                         CHECK("scan_reverse_l", r, v, bit_scan_reverse, &pdl_long);
00147                 }
00148         }
00149         for (r=0; r<64; r++){
00150                 ll=(1ULL<<r);
00151                 CHECK("first debruijn 64bit", r, ll, bit_scan_forward_debruijn64, &pdf5);
00152                 CHECK("first slow 64bit", r, ll, bit_scan_forward_slow64, &pdf6);
00153 #ifdef HAS_BIT_SCAN_ASM
00154                 CHECK("first asm 64bit", r, ll, bit_scan_forward_asm64, &pdf7);
00155 #endif
00156                 CHECK("first br 64bit", r, ll, bit_scan_forward_br64, &pdf8);
00157                 CHECK("scan_forward64", r, ll, bit_scan_forward64, &pdf_64);
00158                 if (sizeof(long)>4){
00159                         CHECK("scan_forward_l", r, ll, bit_scan_forward, &pdf_long);
00160                 }
00161                 ll+=ll-1;
00162                 CHECK("last debruijn 64bit", r, ll, bit_scan_reverse_debruijn64, &pdl5);
00163                 CHECK("last slow 64bit", r, ll, bit_scan_reverse_slow64, &pdl6);
00164 #ifdef HAS_BIT_SCAN_ASM
00165                 CHECK("last asm 64bit", r, ll, bit_scan_reverse_asm64, &pdl7);
00166 #endif
00167                 CHECK("last br 64bit", r, ll, bit_scan_reverse_br64, &pdl8);
00168                 CHECK("scan_reverse64", r, ll, bit_scan_reverse64, &pdl_64);
00169                 if (sizeof(long)>4){
00170                         CHECK("scan_reverse_l", r, ll, bit_scan_reverse, &pdl_long);
00171                 }
00172         }
00173         }
00174 
00175         PROFILE_PRINT(&pdf1);
00176         PROFILE_PRINT(&pdf2);
00177 #ifdef HAS_BIT_SCAN_ASM
00178         PROFILE_PRINT(&pdf3);
00179 #endif
00180         PROFILE_PRINT(&pdf4);
00181         PROFILE_PRINT(&pdl1);
00182         PROFILE_PRINT(&pdl2);
00183 #ifdef HAS_BIT_SCAN_ASM
00184         PROFILE_PRINT(&pdl3);
00185 #endif
00186         PROFILE_PRINT(&pdl4);
00187         PROFILE_PRINT(&pdf5);
00188         PROFILE_PRINT(&pdf6);
00189 #ifdef HAS_BIT_SCAN_ASM
00190         PROFILE_PRINT(&pdf7);
00191 #endif
00192         PROFILE_PRINT(&pdf8);
00193         PROFILE_PRINT(&pdl5);
00194         PROFILE_PRINT(&pdl6);
00195 #ifdef HAS_BIT_SCAN_ASM
00196         PROFILE_PRINT(&pdl7);
00197 #endif
00198         PROFILE_PRINT(&pdl8);
00199         
00200         PROFILE_PRINT(&pdf_32);
00201         PROFILE_PRINT(&pdf_64);
00202         PROFILE_PRINT(&pdf_long);
00203         PROFILE_PRINT(&pdl_32);
00204         PROFILE_PRINT(&pdl_64);
00205         PROFILE_PRINT(&pdl_long);
00206         return 0;
00207 }