UnitBitVector.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #define FOREACH_BITSET_IN_UNITBV(index, bv, BVUnitT) \
  7. { \
  8. BVIndex index; \
  9. BVUnitT _unit = bv; \
  10. for(index = _unit.GetNextBit(); index != -1; index = _unit.GetNextBit()) \
  11. { \
  12. _unit.Clear(index); \
  13. \
  14. #define NEXT_BITSET_IN_UNITBV }}
  15. // Typedef
  16. typedef uint32 UnitWord32;
  17. typedef uint64 UnitWord64;
  18. inline BOOLEAN
  19. GetFirstBitSet(DWORD *Index, UnitWord32 Mask)
  20. {
  21. return _BitScanForward(Index, Mask);
  22. }
  23. inline BOOLEAN
  24. GetFirstBitSet(DWORD *Index, UnitWord64 Mask)
  25. {
  26. #if defined(_M_X64_OR_ARM64)
  27. return _BitScanForward64(Index, Mask);
  28. #else
  29. //_BitScanForward64 intrinsic is not available in x86 & ARM
  30. if (_BitScanForward(Index, (UnitWord32)Mask))
  31. {
  32. return true;
  33. }
  34. if(_BitScanForward(Index, (UnitWord32) (Mask >> 32)))
  35. {
  36. *Index = *Index + 32;
  37. return true;
  38. }
  39. return false;
  40. #endif
  41. }
  42. inline BOOLEAN
  43. GetLastBitSet(DWORD *Index, UnitWord32 Mask)
  44. {
  45. return _BitScanReverse(Index, Mask);
  46. }
  47. inline BOOLEAN
  48. GetLastBitSet(DWORD *Index, UnitWord64 Mask)
  49. {
  50. #if defined(_M_X64_OR_ARM64)
  51. return _BitScanReverse64(Index, Mask);
  52. #else
  53. //_BitScanReverse64 intrinsic is not available in x86 & ARM
  54. if (_BitScanReverse(Index, (UnitWord32)(Mask >> 32)))
  55. {
  56. *Index = *Index + 32;
  57. return true;
  58. }
  59. return _BitScanReverse(Index, (UnitWord32)Mask);
  60. #endif
  61. }
  62. template <typename T>
  63. class BVUnitT
  64. {
  65. // Data
  66. private:
  67. T word;
  68. // Constructor
  69. public:
  70. BVUnitT(T initial = 0)
  71. {
  72. word = initial;
  73. }
  74. typedef T BVUnitTContainer;
  75. // Implementation
  76. private:
  77. static void AssertRange(BVIndex index)
  78. {
  79. AssertMsg(index < BitsPerWord, "index out of bound");
  80. }
  81. static UnitWord32 Reverse(UnitWord32 bitsToReverse) {
  82. bitsToReverse = (bitsToReverse & 0x55555555) << 1 | (bitsToReverse & 0xAAAAAAAA) >> 1;
  83. bitsToReverse = (bitsToReverse & 0x33333333) << 2 | (bitsToReverse & 0xCCCCCCCC) >> 2;
  84. bitsToReverse = (bitsToReverse & 0x0F0F0F0F) << 4 | (bitsToReverse & 0xF0F0F0F0) >> 4;
  85. bitsToReverse = (bitsToReverse & 0x00FF00FF) << 8 | (bitsToReverse & 0xFF00FF00) >> 8;
  86. bitsToReverse = (bitsToReverse & 0x0000FFFF) << 16 | (bitsToReverse & 0xFFFF0000) >> 16;
  87. return bitsToReverse;
  88. }
  89. static UnitWord64 Reverse(UnitWord64 bits)
  90. {
  91. UnitWord32 lower = (UnitWord32) bits;
  92. UnitWord32 upper = (UnitWord32) (bits >> 32);
  93. UnitWord64 result = ((UnitWord64) Reverse(lower)) << 32;
  94. result |= Reverse(upper);
  95. return result;
  96. }
  97. static BVIndex CountBit(UnitWord32 bits)
  98. {
  99. const uint _5_32 = 0x55555555;
  100. const uint _3_32 = 0x33333333;
  101. const uint _F1_32 = 0x0f0f0f0f;
  102. // In-place adder tree: perform 16 1-bit adds, 8 2-bit adds, 4 4-bit adds,
  103. // 2 8=bit adds, and 1 16-bit add.
  104. // From Dr. Dobb's Nov. 2000 letters, from Phil Bagwell, on reducing
  105. // the cost by removing some of the masks that can be "forgotten" dbitse
  106. // to the max # of bits set (32) that will fit in a byte.
  107. //
  108. bits -= (bits >> 1) & _5_32;
  109. bits = ((bits >> 2) & _3_32) + (bits & _3_32);
  110. bits = ((bits >> 4) & _F1_32) + (bits & _F1_32);
  111. bits += bits >> 8;
  112. bits += bits >> 16;
  113. return BVIndex(bits & 0xff);
  114. }
  115. static BVIndex CountBit(UnitWord64 bits)
  116. {
  117. #if DBG
  118. unsigned countBits = CountBit((UnitWord32)bits) + CountBit((UnitWord32)(bits >> 32));
  119. #endif
  120. const uint64 _5_64 = 0x5555555555555555ui64;
  121. const uint64 _3_64 = 0x3333333333333333ui64;
  122. const uint64 _F1_64 = 0x0f0f0f0f0f0f0f0fui64;
  123. // In-place adder tree: perform 32 1-bit adds, 16 2-bit adds, 8 4-bit adds,
  124. // 4 8-bit adds, 2 16-bit adds, and 1 32-bit add.
  125. // From Dr. Dobb's Nov. 2000 letters, from Phil Bagwell, on reducing
  126. // the cost by removing some of the masks that can be "forgotten" due
  127. // to the max # of bits set (64) that will fit in a byte.
  128. //
  129. bits -= (bits >> 1) & _5_64;
  130. bits = ((bits >> 2) & _3_64) + (bits & _3_64);
  131. bits = ((bits >> 4) & _F1_64) + (bits & _F1_64);
  132. bits += bits >> 8;
  133. bits += bits >> 16;
  134. bits += bits >> 32;
  135. AssertMsg(countBits == (bits & 0xff), "Wrong count?");
  136. return (BVIndex)(bits & 0xff);
  137. }
  138. static unsigned int NumLeadingZeroes(UnitWord32 bits)
  139. {
  140. int n = 0;
  141. if (bits == 0) return 32;
  142. // Binary search to figure out the number of leading zeroes
  143. if (bits <= 0x0000FFFF)
  144. {
  145. // At least 16 leading zeroes- so remove them, and
  146. // let's figure out how many leading zeroes in the last 16 bits
  147. n = n + 16;
  148. bits = bits << 16;
  149. }
  150. if (bits <= 0x00FFFFFF)
  151. {
  152. // At least 8 more zeroes- remove them, and repeat process
  153. n = n + 8;
  154. bits = bits << 8;
  155. }
  156. if (bits <= 0x0FFFFFFF)
  157. {
  158. n = n + 4;
  159. bits = bits << 4;
  160. }
  161. if (bits <= 0x3FFFFFFF)
  162. {
  163. n = n + 2;
  164. bits = bits << 2;
  165. }
  166. if (bits <= 0x7FFFFFFF)
  167. {
  168. n = n + 1;
  169. }
  170. return n;
  171. }
  172. static unsigned int NumLeadingZeroes(UnitWord64 bits)
  173. {
  174. UnitWord32 lower = (UnitWord32) bits;
  175. UnitWord32 upper = (UnitWord32) (bits >> 32);
  176. if (upper == 0)
  177. {
  178. return 32 + NumLeadingZeroes(lower);
  179. }
  180. else
  181. {
  182. return NumLeadingZeroes(upper);
  183. }
  184. }
  185. public:
  186. enum
  187. {
  188. BitsPerWord = sizeof(T) * MachBits,
  189. BitMask = BitsPerWord - 1,
  190. AllOnesMask = -1
  191. };
  192. //ShiftValue is essentially log(sizeof(T))
  193. //Initialization is through template specialization
  194. static const LONG ShiftValue;
  195. static BVIndex Position(BVIndex index)
  196. {
  197. return index >> ShiftValue;
  198. }
  199. static BVIndex Offset(BVIndex index)
  200. {
  201. return index & BitMask;
  202. }
  203. static BVIndex Floor(BVIndex index)
  204. {
  205. return index & (~BitMask);
  206. }
  207. static T GetTopBitsClear(BVIndex len)
  208. {
  209. return ((T)1 << Offset(len)) - 1;
  210. }
  211. bool Equal(BVUnitT unit) const
  212. {
  213. return this->word == unit.word;
  214. }
  215. void Set(BVIndex index)
  216. {
  217. AssertRange(index);
  218. this->word |= (T)1 << index;
  219. }
  220. void Clear(BVIndex index)
  221. {
  222. AssertRange(index);
  223. this->word &= ~((T)1 << index);
  224. }
  225. void Complement(BVIndex index)
  226. {
  227. AssertRange(index);
  228. this->word ^= (T)1 << index;
  229. }
  230. BOOLEAN Test(const BVIndex index) const
  231. {
  232. AssertRange(index);
  233. return (this->word & ( (T)1 << index)) != 0;
  234. }
  235. BOOLEAN Test(BVUnitT const unit) const
  236. {
  237. return (this->word & unit.word) != 0;
  238. }
  239. BOOLEAN TestRange(const BVIndex index, uint length) const
  240. {
  241. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  242. return (this->word & mask) == mask;
  243. }
  244. void SetRange(const BVIndex index, uint length)
  245. {
  246. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  247. this->word |= mask;
  248. }
  249. void ClearRange(const BVIndex index, uint length)
  250. {
  251. T mask = ((T)AllOnesMask) >> (BitsPerWord - length) << index;
  252. this->word &= ~mask;
  253. }
  254. BVIndex GetNextBit() const
  255. {
  256. DWORD index;
  257. if(GetFirstBitSet(&index, this->word))
  258. {
  259. return index;
  260. }
  261. else
  262. {
  263. return BVInvalidIndex;
  264. }
  265. }
  266. BVIndex GetNextBit(BVIndex index) const
  267. {
  268. AssertRange(index);
  269. BVUnitT temp = *this;
  270. temp.ClearAllTill(index);
  271. return temp.GetNextBit();
  272. }
  273. BVIndex GetPrevBit() const
  274. {
  275. DWORD index;
  276. if(GetLastBitSet(&index, this->word))
  277. {
  278. return index;
  279. }
  280. else
  281. {
  282. return BVInvalidIndex;
  283. }
  284. }
  285. inline unsigned int GetNumberOfLeadingZeroes()
  286. {
  287. return NumLeadingZeroes(this->word);
  288. }
  289. T GetWord() const
  290. {
  291. return this->word;
  292. }
  293. inline BVIndex FirstStringOfOnes(unsigned int l)
  294. {
  295. unsigned int leadingZeroes;
  296. BVIndex i = 0;
  297. if (this->word == 0)
  298. {
  299. return BVInvalidIndex;
  300. }
  301. T bitVector = Reverse(this->word);
  302. while (bitVector != 0) {
  303. // Find the number of leading zeroes
  304. leadingZeroes = NumLeadingZeroes(bitVector);
  305. // Skip over leading zeroes
  306. bitVector = bitVector << leadingZeroes;
  307. i = i + leadingZeroes;
  308. // Invert the bit vector- leading number of leading zeroes = number of leading 1's in the original bit vector
  309. leadingZeroes = NumLeadingZeroes(~bitVector); // Count first/next group of 1's.
  310. if (leadingZeroes >= l)
  311. return i;
  312. // If there aren't enough ones, we skip over them, iterate again
  313. bitVector = bitVector << leadingZeroes;
  314. i = i + leadingZeroes;
  315. }
  316. // No sub-sequence of 1's of length l found in this bit vector
  317. return BVInvalidIndex;
  318. }
  319. void ClearAllTill(BVIndex index)
  320. {
  321. AssertRange(index);
  322. this->word &= ((T)BVUnitT::AllOnesMask) <<(T)index;
  323. }
  324. BVIndex Count() const
  325. {
  326. return CountBit(this->word);
  327. }
  328. bool IsEmpty() const
  329. {
  330. return 0 == this->word;
  331. }
  332. bool IsFull() const
  333. {
  334. return this->word == AllOnesMask;
  335. }
  336. void SetAll()
  337. {
  338. this->word = (T)AllOnesMask;
  339. }
  340. void ClearAll()
  341. {
  342. this->word = 0;
  343. }
  344. void ComplimentAll()
  345. {
  346. this->word = ~this->word;
  347. }
  348. void Or(BVUnitT x)
  349. {
  350. this->word |= x.word;
  351. }
  352. void OrComplimented(BVUnitT x)
  353. {
  354. this->word |= (~x.word);
  355. }
  356. void And(BVUnitT x)
  357. {
  358. this->word &= x.word;
  359. }
  360. void Xor(BVUnitT x)
  361. {
  362. this->word ^= x.word;
  363. }
  364. uint DiffCount(BVUnitT x) const
  365. {
  366. return CountBit(x.word ^ this->word);
  367. }
  368. void Minus(BVUnitT x)
  369. {
  370. this->word &= (~x.word);
  371. }
  372. void Copy(BVUnitT x)
  373. {
  374. this->word = x.word;
  375. }
  376. void ShiftLeft(BVIndex count)
  377. {
  378. this->word <<= count;
  379. }
  380. void ShiftRight(BVIndex count)
  381. {
  382. this->word >>= count;
  383. }
  384. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  385. void DumpWord()
  386. {
  387. Output::Print(CH_WSTR("%p"), this->word);
  388. }
  389. bool Dump(BVIndex base = 0, bool hasBits = false) const
  390. {
  391. FOREACH_BITSET_IN_UNITBV(index, *this, BVUnitT)
  392. {
  393. if (hasBits)
  394. {
  395. Output::Print(CH_WSTR(", "));
  396. }
  397. Output::Print(CH_WSTR("%u"), index + base);
  398. hasBits = true;
  399. }
  400. NEXT_BITSET_IN_UNITBV;
  401. return hasBits;
  402. }
  403. #endif
  404. };
  405. typedef BVUnitT<UnitWord32> BVUnit32;
  406. typedef BVUnitT<UnitWord64> BVUnit64;
  407. template<> const __declspec(selectany) LONG BVUnitT<UnitWord32>::ShiftValue = 5;
  408. template<> const __declspec(selectany) LONG BVUnitT<UnitWord64>::ShiftValue = 6;
  409. #if defined(_M_X64_OR_ARM64)
  410. typedef BVUnit64 BVUnit;
  411. #else
  412. typedef BVUnit32 BVUnit;
  413. #endif