1 /****************************************************************************
2 *   Copyright (C) 2014 by Jens Nissen jens-chessx@gmx.net                   *
3 ****************************************************************************/
4 
5 #include <qglobal.h>
6 
7 #ifndef BITFIND_H
8 #define BITFIND_H
9 
10 template <typename T>
getFirstBitAndClear64(quint64 & bb)11 T getFirstBitAndClear64(quint64& bb)
12 {
13     quint64 x = bb & -(qint64)bb;
14     bb ^= x;
15 #ifdef __GNUG__
16     return T(x ? (63 - __builtin_clzll(x)) : (T)0xFF);
17 #elif _MSC_VER
18 #ifdef __x86_64__
19     if(x)
20     {
21         unsigned long r;
22         _BitScanReverse64(&r, x);
23         return T(r);
24     }
25     return (T)0xFF;
26 #else
27     if(x)
28     {
29         unsigned long r;
30         unsigned long y = (x >> 32);
31         if(y)
32         {
33             _BitScanReverse(&r, y);
34             return T(32 + r);
35         }
36         _BitScanReverse(&r, x);
37         return T(r);
38     }
39     return (T)0xFF;
40 #endif
41 #else
42     // SBE - After a fair bit of testing, this is the fastest portable version
43     // i could come up with, it's about twice as fast as shift-testing 64 times.
44     unsigned int r = 0;
45     if (!x) return 0xFF;
46     if(!(x & 0xffffffff))
47     {
48         x >>= 32;
49         r |= 32;
50     }
51     if(!(x & 0xffff))
52     {
53         x >>= 16;
54         r |= 16;
55     }
56     if(!(x & 0xff))
57     {
58         x >>= 8;
59         r |= 8;
60     }
61     if(!(x & 0xf))
62     {
63         x >>= 4;
64         r |= 4;
65     }
66     if(!(x & 0x3))
67     {
68         x >>= 2;
69         r |= 2;
70     }
71     if(!(x & 0x1))
72     {
73         r |= 1;
74     }
75     return T(r);
76 #endif
77 }
78 
79 #endif // BITFIND_H
80