SparseBitVector.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  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. typedef BVUnit64 SparseBVUnit;
  7. #define FOREACH_BITSET_IN_SPARSEBV(index, bv) \
  8. { \
  9. BVIndex index; \
  10. for(auto * _curNode = (bv)->head; _curNode != 0 ; _curNode = _curNode->next) \
  11. { \
  12. BVIndex _offset; \
  13. BVIndex _startIndex = _curNode->startIndex; \
  14. SparseBVUnit _unit = _curNode->data; \
  15. for(_offset = _unit.GetNextBit(); _offset != -1; _offset = _unit.GetNextBit()) \
  16. { \
  17. index = _startIndex + _offset; \
  18. _unit.Clear(_offset); \
  19. \
  20. #define BREAK_BITSET_IN_SPARSEBV \
  21. _curNode = 0; \
  22. break;
  23. #define NEXT_BITSET_IN_SPARSEBV \
  24. } \
  25. if(_curNode == 0) \
  26. { \
  27. break; \
  28. } \
  29. } \
  30. }
  31. #define FOREACH_BITSET_IN_SPARSEBV_EDITING(index, bv) \
  32. { \
  33. BVIndex index; \
  34. BVSparseNode * _curNodeEdit = (bv)->head; \
  35. while (_curNodeEdit != nullptr) \
  36. { \
  37. BVSparseNode * _next = _curNodeEdit->next; \
  38. BVIndex _offset; \
  39. BVIndex _startIndex = _curNodeEdit->startIndex; \
  40. SparseBVUnit _unit = _curNodeEdit->data; \
  41. for(_offset = _unit.GetNextBit(); _offset != -1; _offset = _unit.GetNextBit()) \
  42. { \
  43. index = _startIndex + _offset; \
  44. _unit.Clear(_offset); \
  45. \
  46. #define NEXT_BITSET_IN_SPARSEBV_EDITING \
  47. } \
  48. _curNodeEdit = _next; \
  49. } \
  50. }
  51. #define SPARSEBV_CLEAR_CURRENT_BIT() _curNodeEdit->data.Clear(_offset)
  52. template <class TAllocator>
  53. struct BVSparseNode
  54. {
  55. Field(BVSparseNode*, TAllocator) next;
  56. Field(BVIndex) startIndex;
  57. Field(SparseBVUnit) data;
  58. BVSparseNode(BVIndex beginIndex, BVSparseNode * nextNode);
  59. void init(BVIndex beginIndex, BVSparseNode * nextNode);
  60. // Needed for the NatVis Extension for visualizing BitVectors
  61. // in Visual Studio
  62. #ifdef _WIN32
  63. bool ToString(
  64. __out_ecount(strSize) char *const str,
  65. const size_t strSize,
  66. size_t *const writtenLengthRef = nullptr,
  67. const bool isInSequence = false,
  68. const bool isFirstInSequence = false,
  69. const bool isLastInSequence = false) const;
  70. #endif
  71. };
  72. template <class TAllocator>
  73. class BVSparse
  74. {
  75. typedef BVSparseNode<TAllocator> BVSparseNode;
  76. // Data
  77. public:
  78. Field(BVSparseNode*, TAllocator) head;
  79. private:
  80. FieldNoBarrier(TAllocator*) alloc;
  81. Field(Field(BVSparseNode*, TAllocator)*, TAllocator) lastUsedNodePrevNextField;
  82. static const SparseBVUnit s_EmptyUnit;
  83. // Constructor
  84. public:
  85. BVSparse(TAllocator* allocator);
  86. ~BVSparse();
  87. // Implementation
  88. protected:
  89. template <class TOtherAllocator>
  90. static void AssertBV(const BVSparse<TOtherAllocator> * bv);
  91. SparseBVUnit * BitsFromIndex(BVIndex i, bool create = true);
  92. const SparseBVUnit * BitsFromIndex(BVIndex i) const;
  93. BVSparseNode* NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator)** prevNextFieldOut,
  94. bool create = true);
  95. const BVSparseNode* NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator) const** prevNextFieldOut) const;
  96. BVSparseNode * DeleteNode(BVSparseNode *node, bool bResetLastUsed = true);
  97. void QueueInFreeList(BVSparseNode* node);
  98. BVSparseNode * Allocate(const BVIndex searchIndex, BVSparseNode *prevNode);
  99. template<void (SparseBVUnit::*callback)(SparseBVUnit)>
  100. void for_each(const BVSparse<TAllocator> *bv2);
  101. template<void (SparseBVUnit::*callback)(SparseBVUnit)>
  102. void for_each(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
  103. // Methods
  104. public:
  105. BOOLEAN operator[](BVIndex i) const;
  106. BOOLEAN Test(BVIndex i) const;
  107. BVIndex GetNextBit(BVIndex i) const;
  108. BVIndex GetNextBit(BVSparseNode * node) const;
  109. BOOLEAN TestEmpty() const;
  110. BOOLEAN TestAndSet(BVIndex i);
  111. BOOLEAN TestAndClear(BVIndex i);
  112. void Set(BVIndex i);
  113. void Clear(BVIndex i);
  114. void Compliment(BVIndex i);
  115. // this |= bv;
  116. void Or(const BVSparse<TAllocator> *bv);
  117. // this = bv1 | bv2;
  118. void Or(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
  119. // newBv = this | bv;
  120. BVSparse<TAllocator> * OrNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
  121. BVSparse<TAllocator> * OrNew(const BVSparse<TAllocator> *bv) const { return this->OrNew(bv, this->alloc); }
  122. // this &= bv;
  123. void And(const BVSparse<TAllocator> *bv);
  124. // this = bv1 & bv2;
  125. void And(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
  126. // newBv = this & bv;
  127. BVSparse<TAllocator> * AndNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
  128. BVSparse<TAllocator> * AndNew(const BVSparse<TAllocator> *bv) const { return this->AndNew(bv, this->alloc); }
  129. // this ^= bv;
  130. void Xor(const BVSparse<TAllocator> *bv);
  131. // this = bv1 ^ bv2;
  132. void Xor(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
  133. // newBv = this ^ bv;
  134. BVSparse<TAllocator> * XorNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
  135. BVSparse<TAllocator> * XorNew(const BVSparse<TAllocator> *bv) const { return this->XorNew(bv, this->alloc); }
  136. // this -= bv;
  137. void Minus(const BVSparse<TAllocator> *bv);
  138. // this = bv1 - bv2;
  139. void Minus(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
  140. // newBv = this - bv;
  141. BVSparse<TAllocator> * MinusNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
  142. BVSparse<TAllocator> * MinusNew(const BVSparse<TAllocator> *bv) const { return this->MinusNew(bv, this->alloc); }
  143. template <class TSrcAllocator>
  144. void Copy(const BVSparse<TSrcAllocator> *bv);
  145. template <class TSrcAllocator>
  146. void CopyFromNode(const ::BVSparseNode<TSrcAllocator> * node2);
  147. BVSparse<TAllocator> * CopyNew(TAllocator* allocator) const;
  148. BVSparse<TAllocator> * CopyNew() const;
  149. void ComplimentAll();
  150. void ClearAll();
  151. BVIndex Count() const;
  152. bool IsEmpty() const;
  153. bool Equal(BVSparse<TAllocator> const * bv) const;
  154. // this & bv != empty
  155. bool Test(BVSparse const * bv) const;
  156. // Needed for the VS NatVis Extension
  157. #ifdef _WIN32
  158. void ToString(__out_ecount(strSize) char *const str, const size_t strSize) const;
  159. template<class F> void ToString(__out_ecount(strSize) char *const str, const size_t strSize, const F ReadNode) const;
  160. #endif
  161. TAllocator * GetAllocator() const { return alloc; }
  162. #if DBG_DUMP
  163. void Dump() const;
  164. #endif
  165. };
  166. template <class TAllocator>
  167. BVSparseNode<TAllocator>::BVSparseNode(BVIndex beginIndex, BVSparseNode<TAllocator> * nextNode) :
  168. startIndex(beginIndex),
  169. data(0),
  170. next(nextNode)
  171. {
  172. // Performance assert, BVSparseNode is heavily used in the backend, do perf
  173. // measurement before changing this.
  174. #if defined(_M_ARM64) || defined(_M_X64)
  175. CompileAssert(sizeof(BVSparseNode) == 24);
  176. #else
  177. CompileAssert(sizeof(BVSparseNode) == 16);
  178. #endif
  179. }
  180. template <class TAllocator>
  181. void BVSparseNode<TAllocator>::init(BVIndex beginIndex, BVSparseNode<TAllocator> * nextNode)
  182. {
  183. this->startIndex = beginIndex;
  184. this->data = 0;
  185. this->next = nextNode;
  186. }
  187. #ifdef _WIN32
  188. template <class TAllocator>
  189. bool BVSparseNode<TAllocator>::ToString(
  190. __out_ecount(strSize) char *const str,
  191. const size_t strSize,
  192. size_t *const writtenLengthRef,
  193. const bool isInSequence,
  194. const bool isFirstInSequence,
  195. const bool isLastInSequence) const
  196. {
  197. Assert(str);
  198. Assert(!isFirstInSequence || isInSequence);
  199. Assert(!isLastInSequence || isInSequence);
  200. if (strSize == 0)
  201. {
  202. if (writtenLengthRef)
  203. {
  204. *writtenLengthRef = 0;
  205. }
  206. return false;
  207. }
  208. str[0] = '\0';
  209. const size_t reservedLength = _countof(", ...}");
  210. if (strSize <= reservedLength)
  211. {
  212. if (writtenLengthRef)
  213. {
  214. *writtenLengthRef = 0;
  215. }
  216. return false;
  217. }
  218. size_t length = 0;
  219. if (!isInSequence || isFirstInSequence)
  220. {
  221. str[length++] = '{';
  222. }
  223. bool insertComma = isInSequence && !isFirstInSequence;
  224. char tempStr[13];
  225. for (BVIndex i = data.GetNextBit(); i != BVInvalidIndex; i = data.GetNextBit(i + 1))
  226. {
  227. const size_t copyLength = sprintf_s(tempStr, insertComma ? ", %u" : "%u", startIndex + i);
  228. Assert(static_cast<int>(copyLength) > 0);
  229. Assert(strSize > length);
  230. Assert(strSize - length > reservedLength);
  231. if (strSize - length - reservedLength <= copyLength)
  232. {
  233. strcpy_s(&str[length], strSize - length, insertComma ? ", ...}" : "...}");
  234. if (writtenLengthRef)
  235. {
  236. *writtenLengthRef = length + (insertComma ? _countof(", ...}") : _countof("...}"));
  237. }
  238. return false;
  239. }
  240. strcpy_s(&str[length], strSize - length - reservedLength, tempStr);
  241. length += copyLength;
  242. insertComma = true;
  243. }
  244. if (!isInSequence || isLastInSequence)
  245. {
  246. Assert(_countof("}") < strSize - length);
  247. strcpy_s(&str[length], strSize - length, "}");
  248. length += _countof("}");
  249. }
  250. if (writtenLengthRef)
  251. {
  252. *writtenLengthRef = length;
  253. }
  254. return true;
  255. }
  256. #endif
  257. #if DBG_DUMP
  258. template <typename T> void Dump(T const& t);
  259. namespace Memory{ class JitArenaAllocator; }
  260. template<>
  261. inline void Dump(BVSparse<JitArenaAllocator> * const& bv)
  262. {
  263. bv->Dump();
  264. }
  265. namespace Memory { class Recycler; }
  266. template<>
  267. inline void Dump(BVSparse<Recycler> * const& bv)
  268. {
  269. bv->Dump();
  270. }
  271. #endif
  272. template <class TAllocator>
  273. const SparseBVUnit BVSparse<TAllocator>::s_EmptyUnit(0);
  274. template <class TAllocator>
  275. BVSparse<TAllocator>::BVSparse(TAllocator* allocator) :
  276. alloc(allocator),
  277. head(nullptr)
  278. {
  279. this->lastUsedNodePrevNextField = &this->head;
  280. }
  281. template <class TAllocator>
  282. void
  283. BVSparse<TAllocator>::QueueInFreeList(BVSparseNode *curNode)
  284. {
  285. AllocatorDelete(TAllocator, this->alloc, curNode);
  286. }
  287. template <class TAllocator>
  288. BVSparseNode<TAllocator> *
  289. BVSparse<TAllocator>::Allocate(const BVIndex searchIndex, BVSparseNode *nextNode)
  290. {
  291. return AllocatorNew(TAllocator, this->alloc, BVSparseNode, searchIndex, nextNode);
  292. }
  293. template <class TAllocator>
  294. BVSparse<TAllocator>::~BVSparse()
  295. {
  296. BVSparseNode * curNode = this->head;
  297. while (curNode != nullptr)
  298. {
  299. curNode = this->DeleteNode(curNode);
  300. }
  301. }
  302. // Searches for a node which would contain the required bit. If not found, then it inserts
  303. // a new node in the appropriate position.
  304. //
  305. template <class TAllocator>
  306. BVSparseNode<TAllocator> *
  307. BVSparse<TAllocator>::NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator)** prevNextFieldOut, bool create)
  308. {
  309. const BVIndex searchIndex = SparseBVUnit::Floor(i);
  310. Field(BVSparseNode*, TAllocator)* prevNextField = this->lastUsedNodePrevNextField;
  311. BVSparseNode* curNode = *prevNextField;
  312. if (curNode != nullptr)
  313. {
  314. if (curNode->startIndex == searchIndex)
  315. {
  316. *prevNextFieldOut = prevNextField;
  317. return curNode;
  318. }
  319. if (curNode->startIndex > searchIndex)
  320. {
  321. prevNextField = &this->head;
  322. curNode = this->head;
  323. }
  324. }
  325. else
  326. {
  327. prevNextField = &this->head;
  328. curNode = this->head;
  329. }
  330. for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
  331. {
  332. prevNextField = &curNode->next;
  333. }
  334. if(curNode && searchIndex == curNode->startIndex)
  335. {
  336. *prevNextFieldOut = prevNextField;
  337. this->lastUsedNodePrevNextField = prevNextField;
  338. return curNode;
  339. }
  340. if(!create)
  341. {
  342. return nullptr;
  343. }
  344. BVSparseNode * newNode = Allocate(searchIndex, *prevNextField);
  345. *prevNextField = newNode;
  346. *prevNextFieldOut = prevNextField;
  347. this->lastUsedNodePrevNextField = prevNextField;
  348. return newNode;
  349. }
  350. template <class TAllocator>
  351. const BVSparseNode<TAllocator> *
  352. BVSparse<TAllocator>::NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator) const** prevNextFieldOut) const
  353. {
  354. const BVIndex searchIndex = SparseBVUnit::Floor(i);
  355. Field(BVSparseNode*, TAllocator) const* prevNextField = &this->head;
  356. const BVSparseNode * curNode = *prevNextField;
  357. if (curNode != nullptr)
  358. {
  359. if (curNode->startIndex == searchIndex)
  360. {
  361. *prevNextFieldOut = prevNextField;
  362. return curNode;
  363. }
  364. if (curNode->startIndex > searchIndex)
  365. {
  366. prevNextField = &this->head;
  367. curNode = this->head;
  368. }
  369. }
  370. else
  371. {
  372. prevNextField = &this->head;
  373. curNode = this->head;
  374. }
  375. for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
  376. {
  377. prevNextField = &curNode->next;
  378. }
  379. if (curNode && searchIndex == curNode->startIndex)
  380. {
  381. *prevNextFieldOut = prevNextField;
  382. return curNode;
  383. }
  384. return nullptr;
  385. }
  386. template <class TAllocator>
  387. SparseBVUnit *
  388. BVSparse<TAllocator>::BitsFromIndex(BVIndex i, bool create)
  389. {
  390. Field(BVSparseNode*, TAllocator)* prevNextField = nullptr;
  391. BVSparseNode * node = NodeFromIndex(i, &prevNextField, create);
  392. if (node)
  393. {
  394. return &node->data;
  395. }
  396. else
  397. {
  398. return (SparseBVUnit *)&BVSparse::s_EmptyUnit;
  399. }
  400. }
  401. template <class TAllocator>
  402. const SparseBVUnit *
  403. BVSparse<TAllocator>::BitsFromIndex(BVIndex i) const
  404. {
  405. Field(BVSparseNode*, TAllocator) const* prevNextField = nullptr;
  406. const BVSparseNode * node = NodeFromIndex(i, &prevNextField);
  407. if (node)
  408. {
  409. return &node->data;
  410. }
  411. else
  412. {
  413. return (SparseBVUnit *)&BVSparse::s_EmptyUnit;
  414. }
  415. }
  416. template <class TAllocator>
  417. BVSparseNode<TAllocator> *
  418. BVSparse<TAllocator>::DeleteNode(BVSparseNode *node, bool bResetLastUsed)
  419. {
  420. BVSparseNode *next = node->next;
  421. QueueInFreeList(node);
  422. if (bResetLastUsed)
  423. {
  424. this->lastUsedNodePrevNextField = &this->head;
  425. }
  426. else
  427. {
  428. Assert(this->lastUsedNodePrevNextField != &node->next);
  429. }
  430. return next;
  431. }
  432. template <class TAllocator>
  433. BVIndex
  434. BVSparse<TAllocator>::GetNextBit(BVSparseNode *node) const
  435. {
  436. while(0 != node)
  437. {
  438. BVIndex ret = node->data.GetNextBit();
  439. if(-1 != ret)
  440. {
  441. return ret + node->startIndex;
  442. }
  443. }
  444. return -1;
  445. }
  446. template <class TAllocator>
  447. BVIndex
  448. BVSparse<TAllocator>::GetNextBit(BVIndex i) const
  449. {
  450. const BVIndex startIndex = SparseBVUnit::Floor(i);
  451. for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
  452. {
  453. if(startIndex == node->startIndex)
  454. {
  455. BVIndex ret = node->data.GetNextBit(SparseBVUnit::Offset(i));
  456. if(-1 != ret)
  457. {
  458. return ret + node->startIndex;
  459. }
  460. else
  461. {
  462. return GetNextBit(node->next);
  463. }
  464. }
  465. else if(startIndex < node->startIndex)
  466. {
  467. return GetNextBit(node->next);
  468. }
  469. }
  470. return -1;
  471. }
  472. template <class TAllocator>
  473. template <class TOtherAllocator>
  474. void
  475. BVSparse<TAllocator>::AssertBV(const BVSparse<TOtherAllocator> *bv)
  476. {
  477. AssertMsg(nullptr != bv, "Cannot operate on NULL bitvector");
  478. }
  479. template <class TAllocator>
  480. void
  481. BVSparse<TAllocator>::ClearAll()
  482. {
  483. BVSparseNode* nextNode;
  484. for(BVSparseNode * node = this->head; node != 0 ; node = nextNode)
  485. {
  486. nextNode = node->next;
  487. QueueInFreeList(node);
  488. }
  489. this->head = nullptr;
  490. this->lastUsedNodePrevNextField = &this->head;
  491. }
  492. template <class TAllocator>
  493. void
  494. BVSparse<TAllocator>::Set(BVIndex i)
  495. {
  496. this->BitsFromIndex(i)->Set(SparseBVUnit::Offset(i));
  497. }
  498. template <class TAllocator>
  499. void
  500. BVSparse<TAllocator>::Clear(BVIndex i)
  501. {
  502. Field(BVSparseNode*, TAllocator)* prevNextField = nullptr;
  503. BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
  504. if(current)
  505. {
  506. current->data.Clear(SparseBVUnit::Offset(i));
  507. if (current->data.IsEmpty())
  508. {
  509. *prevNextField = this->DeleteNode(current, false);
  510. }
  511. }
  512. }
  513. template <class TAllocator>
  514. void
  515. BVSparse<TAllocator>::Compliment(BVIndex i)
  516. {
  517. this->BitsFromIndex(i)->Complement(SparseBVUnit::Offset(i));
  518. }
  519. template <class TAllocator>
  520. BOOLEAN
  521. BVSparse<TAllocator>::TestEmpty() const
  522. {
  523. return this->head != nullptr;
  524. }
  525. template <class TAllocator>
  526. BOOLEAN
  527. BVSparse<TAllocator>::Test(BVIndex i) const
  528. {
  529. return this->BitsFromIndex(i)->Test(SparseBVUnit::Offset(i));
  530. }
  531. template <class TAllocator>
  532. BOOLEAN
  533. BVSparse<TAllocator>::TestAndSet(BVIndex i)
  534. {
  535. SparseBVUnit * bvUnit = this->BitsFromIndex(i);
  536. BVIndex bvIndex = SparseBVUnit::Offset(i);
  537. BOOLEAN bit = bvUnit->Test(bvIndex);
  538. bvUnit->Set(bvIndex);
  539. return bit;
  540. }
  541. template <class TAllocator>
  542. BOOLEAN
  543. BVSparse<TAllocator>::TestAndClear(BVIndex i)
  544. {
  545. Field(BVSparseNode*, TAllocator)* prevNextField = nullptr;
  546. BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
  547. if (current == nullptr)
  548. {
  549. return false;
  550. }
  551. BVIndex bvIndex = SparseBVUnit::Offset(i);
  552. BOOLEAN bit = current->data.Test(bvIndex);
  553. current->data.Clear(bvIndex);
  554. if (current->data.IsEmpty())
  555. {
  556. *prevNextField = this->DeleteNode(current, false);
  557. }
  558. return bit;
  559. }
  560. template <class TAllocator>
  561. BOOLEAN
  562. BVSparse<TAllocator>::operator[](BVIndex i) const
  563. {
  564. return this->Test(i);
  565. }
  566. template<class TAllocator>
  567. template<void (SparseBVUnit::*callback)(SparseBVUnit)>
  568. void BVSparse<TAllocator>::for_each(const BVSparse *bv2)
  569. {
  570. Assert(callback == &SparseBVUnit::And || callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor || callback == &SparseBVUnit::Minus);
  571. AssertBV(bv2);
  572. BVSparseNode * node1 = this->head;
  573. const BVSparseNode * node2 = bv2->head;
  574. Field(BVSparseNode*, TAllocator)* prevNodeNextField = &this->head;
  575. while(node1 != nullptr && node2 != nullptr)
  576. {
  577. if(node2->startIndex == node1->startIndex)
  578. {
  579. (node1->data.*callback)(node2->data);
  580. prevNodeNextField = &node1->next;
  581. node1 = node1->next;
  582. node2 = node2->next;
  583. }
  584. else if(node2->startIndex > node1->startIndex)
  585. {
  586. if (callback == &SparseBVUnit::And)
  587. {
  588. node1 = this->DeleteNode(node1);
  589. *prevNodeNextField = node1;
  590. }
  591. else
  592. {
  593. prevNodeNextField = &node1->next;
  594. node1 = node1->next;
  595. }
  596. }
  597. else
  598. {
  599. if (callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor)
  600. {
  601. BVSparseNode * newNode = Allocate(node2->startIndex, node1);
  602. (newNode->data.*callback)(node2->data);
  603. *prevNodeNextField = newNode;
  604. prevNodeNextField = &newNode->next;
  605. }
  606. node2 = node2->next;
  607. }
  608. }
  609. if (callback == &SparseBVUnit::And)
  610. {
  611. while (node1 != nullptr)
  612. {
  613. node1 = this->DeleteNode(node1);
  614. }
  615. *prevNodeNextField = nullptr;
  616. }
  617. else if (callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor)
  618. {
  619. while(node2 != 0)
  620. {
  621. Assert(*prevNodeNextField == nullptr);
  622. BVSparseNode * newNode = Allocate(node2->startIndex, nullptr);
  623. *prevNodeNextField = newNode;
  624. (newNode->data.*callback)(node2->data);
  625. node2 = node2->next;
  626. prevNodeNextField = &newNode->next;
  627. }
  628. }
  629. }
  630. template<class TAllocator>
  631. template<void (SparseBVUnit::*callback)(SparseBVUnit)>
  632. void BVSparse<TAllocator>::for_each(const BVSparse *bv1, const BVSparse *bv2)
  633. {
  634. Assert(callback == &SparseBVUnit::And || callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor || callback == &SparseBVUnit::Minus);
  635. Assert(this->IsEmpty());
  636. AssertBV(bv1);
  637. AssertBV(bv2);
  638. BVSparseNode * node1 = bv1->head;
  639. const BVSparseNode * node2 = bv2->head;
  640. BVSparseNode * lastNode = nullptr;
  641. Field(BVSparseNode*, TAllocator)* prevNextField = &this->head;
  642. while(node1 != nullptr && node2 != nullptr)
  643. {
  644. lastNode = node1;
  645. BVIndex startIndex;
  646. SparseBVUnit bvUnit1;
  647. SparseBVUnit bvUnit2;
  648. if (node2->startIndex == node1->startIndex)
  649. {
  650. startIndex = node1->startIndex;
  651. bvUnit1 = node1->data;
  652. bvUnit2 = node2->data;
  653. node1 = node1->next;
  654. node2 = node2->next;
  655. }
  656. else if (node2->startIndex > node1->startIndex)
  657. {
  658. startIndex = node1->startIndex;
  659. bvUnit1 = node1->data;
  660. node1 = node1->next;
  661. }
  662. else
  663. {
  664. startIndex = node2->startIndex;
  665. bvUnit2 = node2->data;
  666. node2 = node2->next;
  667. }
  668. (bvUnit1.*callback)(bvUnit2);
  669. if (!bvUnit1.IsEmpty())
  670. {
  671. BVSparseNode * newNode = Allocate(startIndex, nullptr);
  672. newNode->data = bvUnit1;
  673. *prevNextField = newNode;
  674. prevNextField = &newNode->next;
  675. }
  676. }
  677. if (callback == &SparseBVUnit::Minus || callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor)
  678. {
  679. BVSparseNode const * copyNode = (callback == &SparseBVUnit::Minus || node1 != nullptr)? node1 : node2;
  680. while (copyNode != nullptr)
  681. {
  682. if (!copyNode->data.IsEmpty())
  683. {
  684. BVSparseNode * newNode = Allocate(copyNode->startIndex, nullptr);
  685. newNode->data = copyNode->data;
  686. *prevNextField = newNode;
  687. prevNextField = &newNode->next;
  688. }
  689. copyNode = copyNode->next;
  690. }
  691. }
  692. }
  693. template <class TAllocator>
  694. void
  695. BVSparse<TAllocator>::Or(const BVSparse*bv)
  696. {
  697. this->for_each<&SparseBVUnit::Or>(bv);
  698. }
  699. template <class TAllocator>
  700. void
  701. BVSparse<TAllocator>::Or(const BVSparse * bv1, const BVSparse * bv2)
  702. {
  703. this->ClearAll();
  704. this->for_each<&SparseBVUnit::Or>(bv1, bv2);
  705. }
  706. template <class TAllocator>
  707. BVSparse<TAllocator> *
  708. BVSparse<TAllocator>::OrNew(const BVSparse* bv, TAllocator* allocator) const
  709. {
  710. BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
  711. newBv->for_each<&SparseBVUnit::Or>(this, bv);
  712. return newBv;
  713. }
  714. template <class TAllocator>
  715. void
  716. BVSparse<TAllocator>::And(const BVSparse*bv)
  717. {
  718. this->for_each<&SparseBVUnit::And>(bv);
  719. }
  720. template <class TAllocator>
  721. void
  722. BVSparse<TAllocator>::And(const BVSparse * bv1, const BVSparse * bv2)
  723. {
  724. this->ClearAll();
  725. this->for_each<&SparseBVUnit::And>(bv1, bv2);
  726. }
  727. template <class TAllocator>
  728. BVSparse<TAllocator> *
  729. BVSparse<TAllocator>::AndNew(const BVSparse* bv, TAllocator* allocator) const
  730. {
  731. BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
  732. newBv->for_each<&SparseBVUnit::And>(this, bv);
  733. return newBv;
  734. }
  735. template <class TAllocator>
  736. void
  737. BVSparse<TAllocator>::Xor(const BVSparse*bv)
  738. {
  739. this->for_each<&SparseBVUnit::Xor>(bv);
  740. }
  741. template <class TAllocator>
  742. void
  743. BVSparse<TAllocator>::Xor(const BVSparse * bv1, const BVSparse * bv2)
  744. {
  745. this->ClearAll();
  746. this->for_each<&SparseBVUnit::Xor>(bv1, bv2);
  747. }
  748. template <class TAllocator>
  749. BVSparse<TAllocator> *
  750. BVSparse<TAllocator>::XorNew(const BVSparse* bv, TAllocator* allocator) const
  751. {
  752. BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
  753. newBv->for_each<&SparseBVUnit::Xor>(this, bv);
  754. return newBv;
  755. }
  756. template <class TAllocator>
  757. void
  758. BVSparse<TAllocator>::Minus(const BVSparse*bv)
  759. {
  760. this->for_each<&SparseBVUnit::Minus>(bv);
  761. }
  762. template <class TAllocator>
  763. void
  764. BVSparse<TAllocator>::Minus(const BVSparse * bv1, const BVSparse * bv2)
  765. {
  766. this->ClearAll();
  767. this->for_each<&SparseBVUnit::Minus>(bv1, bv2);
  768. }
  769. template <class TAllocator>
  770. BVSparse<TAllocator> *
  771. BVSparse<TAllocator>::MinusNew(const BVSparse* bv, TAllocator* allocator) const
  772. {
  773. BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
  774. newBv->for_each<&SparseBVUnit::Minus>(this, bv);
  775. return newBv;
  776. }
  777. template <class TAllocator>
  778. template <class TSrcAllocator>
  779. void
  780. BVSparse<TAllocator>::Copy(const BVSparse<TSrcAllocator> * bv2)
  781. {
  782. AssertBV(bv2);
  783. CopyFromNode(bv2->head);
  784. }
  785. template <class TAllocator>
  786. template <class TSrcAllocator>
  787. void
  788. BVSparse<TAllocator>::CopyFromNode(const ::BVSparseNode<TSrcAllocator> * node2)
  789. {
  790. BVSparseNode * node1 = this->head;
  791. Field(BVSparseNode*, TAllocator)* prevNextField = &this->head;
  792. while (node1 != nullptr && node2 != nullptr)
  793. {
  794. if (!node2->data.IsEmpty())
  795. {
  796. node1->startIndex = node2->startIndex;
  797. node1->data.Copy(node2->data);
  798. prevNextField = &node1->next;
  799. node1 = node1->next;
  800. }
  801. node2 = node2->next;
  802. }
  803. if (node1 != nullptr)
  804. {
  805. while (node1 != nullptr)
  806. {
  807. node1 = this->DeleteNode(node1);
  808. }
  809. *prevNextField = nullptr;
  810. }
  811. else
  812. {
  813. while (node2 != nullptr)
  814. {
  815. if (!node2->data.IsEmpty())
  816. {
  817. BVSparseNode * newNode = Allocate(node2->startIndex, nullptr);
  818. newNode->data.Copy(node2->data);
  819. *prevNextField = newNode;
  820. prevNextField = &newNode->next;
  821. }
  822. node2 = node2->next;
  823. }
  824. }
  825. }
  826. template <class TAllocator>
  827. BVSparse<TAllocator> *
  828. BVSparse<TAllocator>::CopyNew(TAllocator* allocator) const
  829. {
  830. BVSparse * bv = AllocatorNew(TAllocator, allocator, BVSparse<TAllocator>, allocator);
  831. bv->Copy(this);
  832. return bv;
  833. }
  834. template <class TAllocator>
  835. BVSparse<TAllocator> *
  836. BVSparse<TAllocator>::CopyNew() const
  837. {
  838. return this->CopyNew(this->alloc);
  839. }
  840. template <class TAllocator>
  841. void
  842. BVSparse<TAllocator>::ComplimentAll()
  843. {
  844. for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
  845. {
  846. node->data.ComplimentAll();
  847. }
  848. }
  849. template <class TAllocator>
  850. BVIndex
  851. BVSparse<TAllocator>::Count() const
  852. {
  853. BVIndex sum = 0;
  854. for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
  855. {
  856. sum += node->data.Count();
  857. }
  858. return sum;
  859. }
  860. template <class TAllocator>
  861. bool
  862. BVSparse<TAllocator>::IsEmpty() const
  863. {
  864. for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
  865. {
  866. if (!node->data.IsEmpty())
  867. {
  868. return false;
  869. }
  870. }
  871. return true;
  872. }
  873. template <class TAllocator>
  874. bool
  875. BVSparse<TAllocator>::Equal(BVSparse const * bv) const
  876. {
  877. BVSparseNode const * bvNode1 = this->head;
  878. BVSparseNode const * bvNode2 = bv->head;
  879. while (true)
  880. {
  881. while (bvNode1 != nullptr && bvNode1->data.IsEmpty())
  882. {
  883. bvNode1 = bvNode1->next;
  884. }
  885. while (bvNode2 != nullptr && bvNode2->data.IsEmpty())
  886. {
  887. bvNode2 = bvNode2->next;
  888. }
  889. if (bvNode1 == nullptr)
  890. {
  891. return (bvNode2 == nullptr);
  892. }
  893. if (bvNode2 == nullptr)
  894. {
  895. return false;
  896. }
  897. if (bvNode1->startIndex != bvNode2->startIndex)
  898. {
  899. return false;
  900. }
  901. if (!bvNode1->data.Equal(bvNode2->data))
  902. {
  903. return false;
  904. }
  905. bvNode1 = bvNode1->next;
  906. bvNode2 = bvNode2->next;
  907. }
  908. }
  909. template <class TAllocator>
  910. bool
  911. BVSparse<TAllocator>::Test(BVSparse const * bv) const
  912. {
  913. BVSparseNode const * bvNode1 = this->head;
  914. BVSparseNode const * bvNode2 = bv->head;
  915. while (bvNode1 != nullptr && bvNode2 != nullptr)
  916. {
  917. if (bvNode1->data.IsEmpty() || bvNode1->startIndex < bvNode2->startIndex)
  918. {
  919. bvNode1 = bvNode1->next;
  920. continue;
  921. }
  922. if (bvNode2->data.IsEmpty() || bvNode1->startIndex > bvNode2->startIndex)
  923. {
  924. bvNode2 = bvNode2->next;
  925. continue;
  926. }
  927. Assert(bvNode1->startIndex == bvNode2->startIndex);
  928. if (bvNode1->data.Test(bvNode2->data))
  929. {
  930. return true;
  931. }
  932. bvNode1 = bvNode1->next;
  933. bvNode2 = bvNode2->next;
  934. }
  935. return false;
  936. }
  937. #ifdef _WIN32
  938. template<class TAllocator>
  939. template<class F>
  940. void BVSparse<TAllocator>::ToString(__out_ecount(strSize) char *const str, const size_t strSize, const F ReadNode) const
  941. {
  942. Assert(str);
  943. if (strSize == 0)
  944. {
  945. return;
  946. }
  947. str[0] = '\0';
  948. bool empty = true;
  949. bool isFirstInSequence = true;
  950. size_t length = 0;
  951. BVSparseNode *nodePtr = head;
  952. while (nodePtr)
  953. {
  954. bool readSuccess;
  955. const BVSparseNode node(ReadNode(nodePtr, &readSuccess));
  956. if (!readSuccess)
  957. {
  958. str[0] = '\0';
  959. return;
  960. }
  961. if (node.data.IsEmpty())
  962. {
  963. nodePtr = node.next;
  964. continue;
  965. }
  966. empty = false;
  967. size_t writtenLength;
  968. if (!node.ToString(&str[length], strSize - length, &writtenLength, true, isFirstInSequence, !node.next))
  969. {
  970. return;
  971. }
  972. length += writtenLength;
  973. isFirstInSequence = false;
  974. nodePtr = node.next;
  975. }
  976. if (empty && _countof("{}") < strSize)
  977. {
  978. strcpy_s(str, strSize, "{}");
  979. }
  980. }
  981. template<class TAllocator>
  982. void BVSparse<TAllocator>::ToString(__out_ecount(strSize) char *const str, const size_t strSize) const
  983. {
  984. ToString(
  985. str,
  986. strSize,
  987. [](BVSparseNode *const nodePtr, bool *const successRef) -> BVSparseNode
  988. {
  989. Assert(nodePtr);
  990. Assert(successRef);
  991. *successRef = true;
  992. return *nodePtr;
  993. });
  994. }
  995. #endif
  996. #if DBG_DUMP
  997. template <class TAllocator>
  998. void
  999. BVSparse<TAllocator>::Dump() const
  1000. {
  1001. bool hasBits = false;
  1002. Output::Print(_u("[ "));
  1003. for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
  1004. {
  1005. hasBits = node->data.Dump(node->startIndex, hasBits);
  1006. }
  1007. Output::Print(_u("]\n"));
  1008. }
  1009. #endif