bit_scan.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2007 iptelorg GmbH
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /*
  19. * bit scan operations
  20. * int bit_scan_forward(unsigned long v) - returns the index of the first
  21. * set bit (undefined value if v==0)
  22. * int bit_scan_forward32(unsigned int v) - returns the index of the first
  23. * set bit (undefined value if v==0)
  24. * int bit_scan_forward64(long long v) - returns the index of the first
  25. * set bit (undefined value if v==0)
  26. * int bit_scan_reverse(unsigned long v) - returns the index of the last
  27. * set bit (undefined value if v==0)
  28. * int bit_scan_reverse32(unsigned int v) - returns the index of the last
  29. * set bit (undefined value if v==0)
  30. * int bit_scan_reverse64(long long v) - returns the index of the last
  31. * set bit (undefined value if v==0)
  32. *
  33. * Config defines: CC_GCC_LIKE_ASM - the compiler support gcc style
  34. * inline asm,
  35. * __CPU_x86, __CPU_x86_64,
  36. * ULONG_MAX (limits.h)
  37. */
  38. /*
  39. * History:
  40. * --------
  41. * 2007-06-23 created by andrei
  42. */
  43. #ifndef _bit_scan_h
  44. #define _bit_scan_h
  45. #include <limits.h>
  46. /* fix __CPU_i386 -> __CPU_x86 */
  47. #if defined __CPU_i386 && ! defined __CPU_x86
  48. #define __CPU_x86
  49. #endif
  50. #ifdef CC_GCC_LIKE_ASM
  51. #if defined __CPU_x86 || defined __CPU_x86_64
  52. #define BIT_SCAN_ASM
  53. #endif
  54. #endif
  55. /* set default bitscan versions, depending on the architecture
  56. * In general the order is asm, debruijn, br, slow for bit_scan_forward
  57. * and asm, br, slow, debruijn for bit_scan_reverse. */
  58. #ifdef BIT_SCAN_ASM
  59. /* have asm => use it */
  60. #define bit_scan_forward32(i) bit_scan_forward_asm32(i)
  61. #define bit_scan_forward64(i) bit_scan_forward_asm64(i)
  62. #define bit_scan_reverse32(i) bit_scan_reverse_asm32(i)
  63. #define bit_scan_reverse64(i) bit_scan_reverse_asm64(i)
  64. #elif defined __CPU_x86 || defined __CPU_x86_64
  65. /* no asm (e.g. no CC_GCC_LIKE_ASM) => debruijn for bit_scan_forward and
  66. * br for bit_scan_reverse */
  67. /* make sure debruijn an branch version are enabled */
  68. #ifndef BIT_SCAN_DEBRUIJN
  69. #define BIT_SCAN_DEBRUIJN
  70. #endif
  71. #ifndef BIT_SCAN_BRANCH
  72. #define BIT_SCAN_BRANCH
  73. #endif
  74. #define bit_scan_forward32(i) bit_scan_forward_debruijn32(i)
  75. #define bit_scan_forward64(i) bit_scan_forward_debruijn64(i)
  76. #define bit_scan_reverse32(i) bit_scan_reverse_br32(i)
  77. #define bit_scan_reverse64(i) bit_scan_reverse_br64(i)
  78. #elif defined __CPU_sparc64
  79. /* no asm yet => use branch for everything in 64 bit mode
  80. * and debruijn + branch in 32 bit mode
  81. * (in 64bit mode the branch method is slightly faster then debruijn,
  82. * however note that in 32 bit mode the roles are reversed for _forward)*/
  83. #ifndef BIT_SCAN_BRANCH
  84. #define BIT_SCAN_BRANCH
  85. #endif
  86. #define bit_scan_reverse32(i) bit_scan_reverse_br32(i)
  87. #define bit_scan_reverse64(i) bit_scan_reverse_br64(i)
  88. #ifdef LP64
  89. #define bit_scan_forward32(i) bit_scan_forward_br32(i)
  90. #define bit_scan_forward64(i) bit_scan_forward_br64(i)
  91. #else /* LP64 */
  92. #ifndef BIT_SCAN_DEBRUIJN
  93. #define BIT_SCAN_DEBRUIJN
  94. #endif
  95. #define bit_scan_forward32(i) bit_scan_forward_debruijn32(i)
  96. #define bit_scan_forward64(i) bit_scan_forward_debruijn64(i)
  97. #endif /* LP64 */
  98. #else /* __CPU_XXX */
  99. /* default - like x86 no asm */
  100. /* make sure debruijn an branch version are enabled */
  101. #ifndef BIT_SCAN_DEBRUIJN
  102. #define BIT_SCAN_DEBRUIJN
  103. #endif
  104. #ifndef BIT_SCAN_BRANCH
  105. #define BIT_SCAN_BRANCH
  106. #endif
  107. #define bit_scan_forward32(i) bit_scan_forward_debruijn32(i)
  108. #define bit_scan_forward64(i) bit_scan_forward_debruijn64(i)
  109. #define bit_scan_reverse32(i) bit_scan_reverse_br32(i)
  110. #define bit_scan_reverse64(i) bit_scan_reverse_br64(i)
  111. #endif /* __CPU_XXX */
  112. /* try to use the right version for bit_scan_forward(unisgned long l)
  113. */
  114. #if (defined (ULONG_MAX) && ULONG_MAX > 4294967295) || defined LP64
  115. /* long is 64 bits */
  116. #define bit_scan_forward(l) bit_scan_forward64((unsigned long long)(l))
  117. #define bit_scan_reverse(l) bit_scan_reverse64((unsigned long long)(l))
  118. #else
  119. /* long is 32 bits */
  120. #define bit_scan_forward(l) bit_scan_forward32((l))
  121. #define bit_scan_reverse(l) bit_scan_reverse32((l))
  122. #endif
  123. #ifdef BIT_SCAN_DEBRUIJN
  124. /* use a de Bruijn sequence to get the index of the set bit for a number
  125. * of the form 2^k (DEBRUIJN_HASH32() and DEBRUIJN_HASH64()).
  126. * bit_scan_forward & bit_scan_reverse would need first to convert
  127. * the argument to 2^k (where k is the first set bit or last set bit index)-
  128. * For bit_scan_forward this can be done very fast using x & (-x).
  129. * For more info about this method see:
  130. * http://citeseer.ist.psu.edu/leiserson98using.html
  131. * ("Using de Bruijn Sequences to Index a 1 in a Computer Word")
  132. */
  133. extern unsigned char _debruijn_hash32[32]; /* see bit_scan.c */
  134. extern unsigned char _debruijn_hash64[64]; /* see bit_scan.c */
  135. #define DEBRUIJN_CT32 0x04653ADFU
  136. #define DEBRUIJN_CT64 0x0218A392CD3D5DBFULL
  137. #define DEBRUIJN_HASH32(x)\
  138. (((x)*DEBRUIJN_CT32)>>(sizeof(x)*8-5))
  139. #define DEBRUIJN_HASH64(x)\
  140. (((x)*DEBRUIJN_CT64)>>(sizeof(x)*8-6))
  141. #define bit_scan_forward_debruijn32(x) \
  142. ( _debruijn_hash32[DEBRUIJN_HASH32((x) & (-(x)))])
  143. #define bit_scan_forward_debruijn64(x) \
  144. ( _debruijn_hash64[DEBRUIJN_HASH64((x) & (-(x)))])
  145. static inline int bit_scan_reverse_debruijn32(unsigned int v)
  146. {
  147. unsigned int last;
  148. do{
  149. last=v;
  150. v=v&(v-1);
  151. }while(v); /* => last is 2^k */
  152. return _debruijn_hash32[DEBRUIJN_HASH32(last)];
  153. }
  154. static inline int bit_scan_reverse_debruijn64(unsigned long long v)
  155. {
  156. unsigned long long last;
  157. do{
  158. last=v;
  159. v=v&(v-1);
  160. }while(v); /* => last is 2^k */
  161. return _debruijn_hash64[DEBRUIJN_HASH64(last)];
  162. }
  163. #endif /* BIT_SCAN_DEBRUIJN */
  164. #ifdef BIT_SCAN_SLOW
  165. /* only for reference purposes (testing the other versions against it) */
  166. static inline int bit_scan_forward_slow32(unsigned int v)
  167. {
  168. int r;
  169. for(r=0; r<(sizeof(v)*8); r++, v>>=1)
  170. if (v&1) return r;
  171. return 0;
  172. }
  173. static inline int bit_scan_reverse_slow32(unsigned int v)
  174. {
  175. int r;
  176. for(r=sizeof(v)*8-1; r>0; r--, v<<=1)
  177. if (v& (1UL<<(sizeof(v)*8-1))) return r;
  178. return 0;
  179. }
  180. static inline int bit_scan_forward_slow64(unsigned long long v)
  181. {
  182. int r;
  183. for(r=0; r<(sizeof(v)*8); r++, v>>=1)
  184. if (v&1ULL) return r;
  185. return 0;
  186. }
  187. static inline int bit_scan_reverse_slow64(unsigned long long v)
  188. {
  189. int r;
  190. for(r=sizeof(v)*8-1; r>0; r--, v<<=1)
  191. if (v& (1ULL<<(sizeof(v)*8-1))) return r;
  192. return 0;
  193. }
  194. #endif /* BIT_SCAN_SLOW */
  195. #ifdef BIT_SCAN_BRANCH
  196. static inline int bit_scan_forward_br32(unsigned int v)
  197. {
  198. int b;
  199. b=0;
  200. if (v&0x01)
  201. return 0;
  202. if (!(v & 0xffff)){
  203. b+=16;
  204. v>>=16;
  205. }
  206. if (!(v&0xff)){
  207. b+=8;
  208. v>>=8;
  209. }
  210. if (!(v&0x0f)){
  211. b+=4;
  212. v>>=4;
  213. }
  214. if (!(v&0x03)){
  215. b+=2;
  216. v>>=2;
  217. }
  218. b+= !(v&0x01);
  219. return b;
  220. }
  221. static inline int bit_scan_reverse_br32(unsigned int v)
  222. {
  223. int b;
  224. b=0;
  225. if (v & 0xffff0000){
  226. b+=16;
  227. v>>=16;
  228. }
  229. if (v&0xff00){
  230. b+=8;
  231. v>>=8;
  232. }
  233. if (v&0xf0){
  234. b+=4;
  235. v>>=4;
  236. }
  237. if (v&0x0c){
  238. b+=2;
  239. v>>=2;
  240. }
  241. b+= !!(v&0x02);
  242. return b;
  243. }
  244. static inline int bit_scan_forward_br64(unsigned long long v)
  245. {
  246. int b;
  247. b=0;
  248. if (v&0x01ULL)
  249. return 0;
  250. if (!(v & 0xffffffffULL)){
  251. b+=32;
  252. v>>=32;
  253. }
  254. if (!(v & 0xffffULL)){
  255. b+=16;
  256. v>>=16;
  257. }
  258. if (!(v&0xffULL)){
  259. b+=8;
  260. v>>=8;
  261. }
  262. if (!(v&0x0fULL)){
  263. b+=4;
  264. v>>=4;
  265. }
  266. if (!(v&0x03ULL)){
  267. b+=2;
  268. v>>=2;
  269. }
  270. b+= !(v&0x01ULL);
  271. return b;
  272. }
  273. static inline int bit_scan_reverse_br64(unsigned long long v)
  274. {
  275. int b;
  276. b=0;
  277. if (v & 0xffffffff00000000ULL){
  278. b+=32;
  279. v>>=32;
  280. }
  281. if (v & 0xffff0000ULL){
  282. b+=16;
  283. v>>=16;
  284. }
  285. if (v&0xff00ULL){
  286. b+=8;
  287. v>>=8;
  288. }
  289. if (v&0xf0ULL){
  290. b+=4;
  291. v>>=4;
  292. }
  293. if (v&0x0cULL){
  294. b+=2;
  295. v>>=2;
  296. }
  297. b+= !!(v&0x02ULL);
  298. return b;
  299. }
  300. #endif /* BIT_SCAN_BRANCH */
  301. #ifdef BIT_SCAN_ASM
  302. #if defined __CPU_x86 || defined __CPU_x86_64
  303. #define HAS_BIT_SCAN_ASM
  304. static inline int bit_scan_forward_asm32(unsigned int v)
  305. {
  306. int r;
  307. asm volatile(" bsfl %1, %0": "=r"(r): "rm"(v) );
  308. return r;
  309. }
  310. static inline int bit_scan_reverse_asm32(unsigned int v)
  311. {
  312. int r;
  313. asm volatile(" bsrl %1, %0": "=r"(r): "rm"(v) );
  314. return r;
  315. }
  316. #ifdef __CPU_x86_64
  317. static inline int bit_scan_forward_asm64(unsigned long long v)
  318. {
  319. long r;
  320. asm volatile(" bsfq %1, %0": "=r"(r): "rm"(v) );
  321. return r;
  322. }
  323. static inline int bit_scan_reverse_asm64(unsigned long long v)
  324. {
  325. long r;
  326. asm volatile(" bsrq %1, %0": "=r"(r): "rm"(v) );
  327. return r;
  328. }
  329. #else
  330. static inline int bit_scan_forward_asm64(unsigned long long v)
  331. {
  332. if ((unsigned int)v)
  333. return bit_scan_forward_asm32((unsigned int)v);
  334. return 32+bit_scan_forward_asm32(*(((unsigned int*)(void*)&v)+1));
  335. }
  336. static inline int bit_scan_reverse_asm64(unsigned long long v)
  337. {
  338. if (v & 0xffffffff00000000ULL)
  339. return 32+bit_scan_reverse_asm32(*(((unsigned int*)(void*)&v)+1));
  340. return bit_scan_reverse_asm32((unsigned int)v);
  341. }
  342. #endif /* __CPU_x86_64 */
  343. #endif /* __CPU_x86 || __CPU_x86_64 */
  344. #endif /* BIT_SCAN_ASM */
  345. #endif