00001 #ifndef MISC_BITOP_H
00002 #define MISC_BITOP_H
00003
00004 #include "osl/config.h"
00005 #include <cassert>
00006 namespace osl
00007 {
00008 namespace misc
00009 {
00013 template <class Integer> struct Bsf;
00014
00015 template <>
00016 struct Bsf<unsigned int>
00017 {
00018 static int bsf(unsigned int mask)
00019 {
00020 assert(mask);
00021 #ifdef __x86_64
00022 int ret;
00023 __asm__("bsfl %1,%0" : "=r"(ret) : "r"(mask));
00024 return ret;
00025 #else
00026 # ifdef i386
00027 int ret;
00028 __asm__("bsfl %1,%0" : "=r"(ret) : "r"(mask));
00029 return ret;
00030 # elif defined __GNUC__
00031 return __builtin_ctzl(mask);
00032 # else
00033 for (int i=0;i<32;i++)
00034 if (mask & (1<<i))
00035 return i;
00036 # endif
00037 #endif
00038 assert(0);
00039 return -1;
00040 }
00041 };
00042 template <>
00043 struct Bsf<unsigned short>
00044 {
00045 static unsigned short bsf(unsigned short mask)
00046 {
00047 assert(mask);
00048 #ifdef __x86_64
00049 unsigned short ret;
00050 __asm__("bsfw %1,%0" : "=r"(ret) : "r"(mask));
00051 return ret;
00052 #else
00053 # ifdef i386
00054 unsigned short ret;
00055 __asm__("bsfw %1,%0" : "=r"(ret) : "r"(mask));
00056 return ret;
00057 # else
00058 return __builtin_ctzl(mask);
00059 # endif
00060 #endif
00061 }
00062 };
00063
00064 template <>
00065 struct Bsf<unsigned long long>
00066 {
00067 static int bsf(unsigned long long mask)
00068 {
00069 assert(mask);
00070 #ifdef __x86_64
00071 long long ret;
00072 __asm__("bsfq %1,%0" : "=r"(ret) : "r"(mask));
00073 return static_cast<int>(ret);
00074 #else
00075 unsigned int mask32 = static_cast<unsigned int>(mask);
00076 if (mask32)
00077 return Bsf<unsigned int>::bsf(mask32);
00078 mask32 = static_cast<unsigned int>(mask >> 32);
00079 return 32+Bsf<unsigned int>::bsf(mask32);
00080 #endif
00081 }
00082 };
00083
00084 template <class Integer> struct Bsr;
00085
00086 template <>
00087 struct Bsr<unsigned int>
00088 {
00089 static int bsr(unsigned int mask)
00090 {
00091 assert(mask);
00092 #ifdef __x86_64
00093 int ret;
00094 __asm__("bsrl %1,%0" : "=r"(ret) : "r"(mask));
00095 return ret;
00096 #else
00097 # ifdef i386
00098 int ret;
00099 __asm__("bsrl %1,%0" : "=r"(ret) : "r"(mask));
00100 return ret;
00101 # elif __GNUC__
00102 return __builtin_clzl(mask);
00103 # else
00104 for (int i=31; i>=0; --i)
00105 if (mask & (1<<i))
00106 return i;
00107 # endif
00108 #endif
00109 assert(0);
00110 return -1;
00111 }
00112 };
00113
00114 template <>
00115 struct Bsr<unsigned long long>
00116 {
00117 static int bsr(unsigned long long mask)
00118 {
00119 assert(mask);
00120 #ifdef __x86_64
00121 long long ret;
00122 __asm__("bsrq %1,%0" : "=r"(ret) : "r"(mask));
00123 return static_cast<int>(ret);
00124 #else
00125 unsigned int mask32 = static_cast<unsigned int>(mask >> 32);
00126 if (mask32)
00127 return 32+Bsr<unsigned int>::bsr(mask32);
00128 mask32 = static_cast<unsigned int>(mask);
00129 return Bsr<unsigned int>::bsr(mask32);
00130 #endif
00131 }
00132 };
00133
00134 struct BitOp
00135 {
00136 template <class Integer>
00137 static int bsf(Integer mask)
00138 {
00139 return Bsf<Integer>::bsf(mask);
00140 }
00141 template <class Integer>
00142 static int bsr(Integer mask)
00143 {
00144 return Bsr<Integer>::bsr(mask);
00145 }
00146 template <class Integer>
00147 static int takeOneBit(Integer& mask){
00148 assert(mask);
00149 const int num=bsf(mask);
00150 mask &= mask-1;
00151 return num;
00152 }
00153
00154 template <class Integer>
00155 static int countBit(Integer mask)
00156 {
00157 int count=0;
00158 while (mask)
00159 {
00160 ++count;
00161 mask &= (mask-1);
00162 }
00163 return count;
00164 }
00165 template <class Integer>
00166 static bool hasMultipleBit(Integer mask){
00167 assert(mask);
00168 return (mask & (mask-1));
00169 }
00173 template <class Integer>
00174 static Integer lowestBit(Integer mask){
00175 assert(mask);
00176 return static_cast<Integer>(mask & (-mask));
00177 }
00178 };
00179
00180 #if 0
00181
00194 inline int countBitDense(unsigned int mask)
00195 {
00196 mask = ((mask>>1)&0x55555555)+(mask&0x55555555);
00197 mask = ((mask>>2)&0x33333333)+(mask&0x33333333);
00198 mask = ((mask>>4)+mask)&0xf0f0f0f;
00199 mask = (mask>>8)+mask;
00200 return ((mask>>16)+mask)&0x3f;
00201 }
00202 #endif
00203 }
00204 }
00205 #endif // _BITOP_H
00206
00207
00208
00209