Quantcast
Channel: What is the fastest/most efficient way to find the position of the highest set bit (msb) in an integer in C? - Stack Overflow
Viewing all articles
Browse latest Browse all 73

Answer by Josh for What is the fastest/most efficient way to find the highest set bit (msb) in an integer in C?

$
0
0

Here are some (simple) benchmarks, of algorithms currently given on this page...

The algorithms have not been tested over all inputs of unsigned int; so check that first, before blindly using something ;)

On my machine clz (__builtin_clz) and asm work best. asm seems even faster then clz... but it might be due to the simple benchmark...

//////// go.c ///////////////////////////////// compile with:  gcc go.c -o go -lm#include <math.h>#include <stdio.h>#include <stdlib.h>#include <time.h>/***************** math ********************/#define POS_OF_HIGHESTBITmath(a) /* 0th position is the Least-Signif-Bit */    \  ((unsigned) log2(a))         /* thus: do not use if a <= 0 */  #define NUM_OF_HIGHESTBITmath(a) ((a)               \                  ? (1U << POS_OF_HIGHESTBITmath(a))    \                  : 0)/***************** clz ********************/unsigned NUM_BITS_U = ((sizeof(unsigned) << 3) - 1);#define POS_OF_HIGHESTBITclz(a) (NUM_BITS_U - __builtin_clz(a)) /* only works for a != 0 */#define NUM_OF_HIGHESTBITclz(a) ((a)                    \                 ? (1U << POS_OF_HIGHESTBITclz(a))  \                 : 0)/***************** i2f ********************/double FF;#define POS_OF_HIGHESTBITi2f(a) (FF = (double)(ui|1), ((*(1+(unsigned*)&FF))>>20)-1023)#define NUM_OF_HIGHESTBITi2f(a) ((a)                    \                 ? (1U << POS_OF_HIGHESTBITi2f(a))  \                 : 0)/***************** asm ********************/unsigned OUT;#define POS_OF_HIGHESTBITasm(a) (({asm("bsrl %1,%0" : "=r"(OUT) : "r"(a));}), OUT)#define NUM_OF_HIGHESTBITasm(a) ((a)                    \                 ? (1U << POS_OF_HIGHESTBITasm(a))  \                 : 0)/***************** bitshift1 ********************/#define NUM_OF_HIGHESTBITbitshift1(a) (({   \  OUT = a;                  \  OUT |= (OUT >> 1);                \  OUT |= (OUT >> 2);                \  OUT |= (OUT >> 4);                \  OUT |= (OUT >> 8);                \  OUT |= (OUT >> 16);               \      }), (OUT & ~(OUT >> 1)))          \/***************** bitshift2 ********************/int POS[32] = {0, 1, 28, 2, 29, 14, 24, 3,             30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,             16, 7, 26, 12, 18, 6, 11, 5, 10, 9};#define POS_OF_HIGHESTBITbitshift2(a) (({   \  OUT = a;                  \  OUT |= OUT >> 1;              \  OUT |= OUT >> 2;              \  OUT |= OUT >> 4;              \  OUT |= OUT >> 8;              \  OUT |= OUT >> 16;             \  OUT = (OUT >> 1) + 1;             \      }), POS[(OUT * 0x077CB531UL) >> 27])#define NUM_OF_HIGHESTBITbitshift2(a) ((a)              \                       ? (1U << POS_OF_HIGHESTBITbitshift2(a)) \                       : 0)#define LOOPS 100000000Uint main(){  time_t start, end;  unsigned ui;  unsigned n;  /********* Checking the first few unsigned values (you'll need to check all if you want to use an algorithm here) **************/  printf("math\n");  for (ui = 0U; ui < 18; ++ui)    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITmath(ui));  printf("\n\n");  printf("clz\n");  for (ui = 0U; ui < 18U; ++ui)    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITclz(ui));  printf("\n\n");  printf("i2f\n");  for (ui = 0U; ui < 18U; ++ui)    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITi2f(ui));  printf("\n\n");  printf("asm\n");  for (ui = 0U; ui < 18U; ++ui) {    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITasm(ui));  }  printf("\n\n");  printf("bitshift1\n");  for (ui = 0U; ui < 18U; ++ui) {    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITbitshift1(ui));  }  printf("\n\n");  printf("bitshift2\n");  for (ui = 0U; ui < 18U; ++ui) {    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITbitshift2(ui));  }  printf("\n\nPlease wait...\n\n");  /************************* Simple clock() benchmark ******************/  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITmath(ui);  end = clock();  printf("math:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITclz(ui);  end = clock();  printf("clz:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITi2f(ui);  end = clock();  printf("i2f:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITasm(ui);  end = clock();  printf("asm:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITbitshift1(ui);  end = clock();  printf("bitshift1:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITbitshift2(ui);  end = clock();  printf("bitshift2\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  printf("\nThe lower, the better. Take note that a negative exponent is good! ;)\n");  return EXIT_SUCCESS;}

Viewing all articles
Browse latest Browse all 73

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>