| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- typedef BVUnit64 SparseBVUnit;
- #define FOREACH_BITSET_IN_SPARSEBV(index, bv) \
- { \
- BVIndex index; \
- for(auto * _curNode = (bv)->head; _curNode != 0 ; _curNode = _curNode->next) \
- { \
- BVIndex _offset; \
- BVIndex _startIndex = _curNode->startIndex; \
- SparseBVUnit _unit = _curNode->data; \
- for(_offset = _unit.GetNextBit(); _offset != -1; _offset = _unit.GetNextBit()) \
- { \
- index = _startIndex + _offset; \
- _unit.Clear(_offset); \
- \
- #define BREAK_BITSET_IN_SPARSEBV \
- _curNode = 0; \
- break;
- #define NEXT_BITSET_IN_SPARSEBV \
- } \
- if(_curNode == 0) \
- { \
- break; \
- } \
- } \
- }
- #define FOREACH_BITSET_IN_SPARSEBV_EDITING(index, bv) \
- { \
- BVIndex index; \
- BVSparseNode * _curNodeEdit = (bv)->head; \
- while (_curNodeEdit != nullptr) \
- { \
- BVSparseNode * _next = _curNodeEdit->next; \
- BVIndex _offset; \
- BVIndex _startIndex = _curNodeEdit->startIndex; \
- SparseBVUnit _unit = _curNodeEdit->data; \
- for(_offset = _unit.GetNextBit(); _offset != -1; _offset = _unit.GetNextBit()) \
- { \
- index = _startIndex + _offset; \
- _unit.Clear(_offset); \
- \
- #define NEXT_BITSET_IN_SPARSEBV_EDITING \
- } \
- _curNodeEdit = _next; \
- } \
- }
- #define SPARSEBV_CLEAR_CURRENT_BIT() _curNodeEdit->data.Clear(_offset)
- template <class TAllocator>
- struct BVSparseNode
- {
- Field(BVSparseNode*, TAllocator) next;
- Field(BVIndex) startIndex;
- Field(SparseBVUnit) data;
- BVSparseNode(BVIndex beginIndex, BVSparseNode * nextNode);
- void init(BVIndex beginIndex, BVSparseNode * nextNode);
- // Needed for the NatVis Extension for visualizing BitVectors
- // in Visual Studio
- #ifdef _WIN32
- bool ToString(
- __out_ecount(strSize) char *const str,
- const size_t strSize,
- size_t *const writtenLengthRef = nullptr,
- const bool isInSequence = false,
- const bool isFirstInSequence = false,
- const bool isLastInSequence = false) const;
- #endif
- };
- template <class TAllocator>
- class BVSparse
- {
- typedef BVSparseNode<TAllocator> BVSparseNode;
- // Data
- public:
- Field(BVSparseNode*, TAllocator) head;
- private:
- FieldNoBarrier(TAllocator*) alloc;
- Field(Field(BVSparseNode*, TAllocator)*, TAllocator) lastUsedNodePrevNextField;
- static const SparseBVUnit s_EmptyUnit;
- // Constructor
- public:
- BVSparse(TAllocator* allocator);
- ~BVSparse();
- // Implementation
- protected:
- template <class TOtherAllocator>
- static void AssertBV(const BVSparse<TOtherAllocator> * bv);
- SparseBVUnit * BitsFromIndex(BVIndex i, bool create = true);
- const SparseBVUnit * BitsFromIndex(BVIndex i) const;
- BVSparseNode* NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator)** prevNextFieldOut,
- bool create = true);
- const BVSparseNode* NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator) const** prevNextFieldOut) const;
- BVSparseNode * DeleteNode(BVSparseNode *node, bool bResetLastUsed = true);
- void QueueInFreeList(BVSparseNode* node);
- BVSparseNode * Allocate(const BVIndex searchIndex, BVSparseNode *prevNode);
- template<void (SparseBVUnit::*callback)(SparseBVUnit)>
- void for_each(const BVSparse<TAllocator> *bv2);
- template<void (SparseBVUnit::*callback)(SparseBVUnit)>
- void for_each(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
- // Methods
- public:
- BOOLEAN operator[](BVIndex i) const;
- BOOLEAN Test(BVIndex i) const;
- BVIndex GetNextBit(BVIndex i) const;
- BVIndex GetNextBit(BVSparseNode * node) const;
- BOOLEAN TestEmpty() const;
- BOOLEAN TestAndSet(BVIndex i);
- BOOLEAN TestAndClear(BVIndex i);
- void Set(BVIndex i);
- void Clear(BVIndex i);
- void Compliment(BVIndex i);
- // this |= bv;
- void Or(const BVSparse<TAllocator> *bv);
- // this = bv1 | bv2;
- void Or(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
- // newBv = this | bv;
- BVSparse<TAllocator> * OrNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
- BVSparse<TAllocator> * OrNew(const BVSparse<TAllocator> *bv) const { return this->OrNew(bv, this->alloc); }
- // this &= bv;
- void And(const BVSparse<TAllocator> *bv);
- // this = bv1 & bv2;
- void And(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
- // newBv = this & bv;
- BVSparse<TAllocator> * AndNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
- BVSparse<TAllocator> * AndNew(const BVSparse<TAllocator> *bv) const { return this->AndNew(bv, this->alloc); }
- // this ^= bv;
- void Xor(const BVSparse<TAllocator> *bv);
- // this = bv1 ^ bv2;
- void Xor(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
- // newBv = this ^ bv;
- BVSparse<TAllocator> * XorNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
- BVSparse<TAllocator> * XorNew(const BVSparse<TAllocator> *bv) const { return this->XorNew(bv, this->alloc); }
- // this -= bv;
- void Minus(const BVSparse<TAllocator> *bv);
- // this = bv1 - bv2;
- void Minus(const BVSparse<TAllocator> *bv1, const BVSparse<TAllocator> *bv2);
- // newBv = this - bv;
- BVSparse<TAllocator> * MinusNew(const BVSparse<TAllocator> *bv, TAllocator* allocator) const;
- BVSparse<TAllocator> * MinusNew(const BVSparse<TAllocator> *bv) const { return this->MinusNew(bv, this->alloc); }
- template <class TSrcAllocator>
- void Copy(const BVSparse<TSrcAllocator> *bv);
- template <class TSrcAllocator>
- void CopyFromNode(const ::BVSparseNode<TSrcAllocator> * node2);
- BVSparse<TAllocator> * CopyNew(TAllocator* allocator) const;
- BVSparse<TAllocator> * CopyNew() const;
- void ComplimentAll();
- void ClearAll();
- BVIndex Count() const;
- bool IsEmpty() const;
- bool Equal(BVSparse<TAllocator> const * bv) const;
- // this & bv != empty
- bool Test(BVSparse const * bv) const;
- // Needed for the VS NatVis Extension
- #ifdef _WIN32
- void ToString(__out_ecount(strSize) char *const str, const size_t strSize) const;
- template<class F> void ToString(__out_ecount(strSize) char *const str, const size_t strSize, const F ReadNode) const;
- #endif
- TAllocator * GetAllocator() const { return alloc; }
- #if DBG_DUMP
- void Dump() const;
- #endif
- };
- template <class TAllocator>
- BVSparseNode<TAllocator>::BVSparseNode(BVIndex beginIndex, BVSparseNode<TAllocator> * nextNode) :
- startIndex(beginIndex),
- data(0),
- next(nextNode)
- {
- // Performance assert, BVSparseNode is heavily used in the backend, do perf
- // measurement before changing this.
- #if defined(_M_ARM64) || defined(_M_X64)
- CompileAssert(sizeof(BVSparseNode) == 24);
- #else
- CompileAssert(sizeof(BVSparseNode) == 16);
- #endif
- }
- template <class TAllocator>
- void BVSparseNode<TAllocator>::init(BVIndex beginIndex, BVSparseNode<TAllocator> * nextNode)
- {
- this->startIndex = beginIndex;
- this->data = 0;
- this->next = nextNode;
- }
- #ifdef _WIN32
- template <class TAllocator>
- bool BVSparseNode<TAllocator>::ToString(
- __out_ecount(strSize) char *const str,
- const size_t strSize,
- size_t *const writtenLengthRef,
- const bool isInSequence,
- const bool isFirstInSequence,
- const bool isLastInSequence) const
- {
- Assert(str);
- Assert(!isFirstInSequence || isInSequence);
- Assert(!isLastInSequence || isInSequence);
- if (strSize == 0)
- {
- if (writtenLengthRef)
- {
- *writtenLengthRef = 0;
- }
- return false;
- }
- str[0] = '\0';
- const size_t reservedLength = _countof(", ...}");
- if (strSize <= reservedLength)
- {
- if (writtenLengthRef)
- {
- *writtenLengthRef = 0;
- }
- return false;
- }
- size_t length = 0;
- if (!isInSequence || isFirstInSequence)
- {
- str[length++] = '{';
- }
- bool insertComma = isInSequence && !isFirstInSequence;
- char tempStr[13];
- for (BVIndex i = data.GetNextBit(); i != BVInvalidIndex; i = data.GetNextBit(i + 1))
- {
- const size_t copyLength = sprintf_s(tempStr, insertComma ? ", %u" : "%u", startIndex + i);
- Assert(static_cast<int>(copyLength) > 0);
- Assert(strSize > length);
- Assert(strSize - length > reservedLength);
- if (strSize - length - reservedLength <= copyLength)
- {
- strcpy_s(&str[length], strSize - length, insertComma ? ", ...}" : "...}");
- if (writtenLengthRef)
- {
- *writtenLengthRef = length + (insertComma ? _countof(", ...}") : _countof("...}"));
- }
- return false;
- }
- strcpy_s(&str[length], strSize - length - reservedLength, tempStr);
- length += copyLength;
- insertComma = true;
- }
- if (!isInSequence || isLastInSequence)
- {
- Assert(_countof("}") < strSize - length);
- strcpy_s(&str[length], strSize - length, "}");
- length += _countof("}");
- }
- if (writtenLengthRef)
- {
- *writtenLengthRef = length;
- }
- return true;
- }
- #endif
- #if DBG_DUMP
- template <typename T> void Dump(T const& t);
- namespace Memory{ class JitArenaAllocator; }
- template<>
- inline void Dump(BVSparse<JitArenaAllocator> * const& bv)
- {
- bv->Dump();
- }
- namespace Memory { class Recycler; }
- template<>
- inline void Dump(BVSparse<Recycler> * const& bv)
- {
- bv->Dump();
- }
- #endif
- template <class TAllocator>
- const SparseBVUnit BVSparse<TAllocator>::s_EmptyUnit(0);
- template <class TAllocator>
- BVSparse<TAllocator>::BVSparse(TAllocator* allocator) :
- alloc(allocator),
- head(nullptr)
- {
- this->lastUsedNodePrevNextField = &this->head;
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::QueueInFreeList(BVSparseNode *curNode)
- {
- AllocatorDelete(TAllocator, this->alloc, curNode);
- }
- template <class TAllocator>
- BVSparseNode<TAllocator> *
- BVSparse<TAllocator>::Allocate(const BVIndex searchIndex, BVSparseNode *nextNode)
- {
- return AllocatorNew(TAllocator, this->alloc, BVSparseNode, searchIndex, nextNode);
- }
- template <class TAllocator>
- BVSparse<TAllocator>::~BVSparse()
- {
- BVSparseNode * curNode = this->head;
- while (curNode != nullptr)
- {
- curNode = this->DeleteNode(curNode);
- }
- }
- // Searches for a node which would contain the required bit. If not found, then it inserts
- // a new node in the appropriate position.
- //
- template <class TAllocator>
- BVSparseNode<TAllocator> *
- BVSparse<TAllocator>::NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator)** prevNextFieldOut, bool create)
- {
- const BVIndex searchIndex = SparseBVUnit::Floor(i);
- Field(BVSparseNode*, TAllocator)* prevNextField = this->lastUsedNodePrevNextField;
- BVSparseNode* curNode = *prevNextField;
- if (curNode != nullptr)
- {
- if (curNode->startIndex == searchIndex)
- {
- *prevNextFieldOut = prevNextField;
- return curNode;
- }
- if (curNode->startIndex > searchIndex)
- {
- prevNextField = &this->head;
- curNode = this->head;
- }
- }
- else
- {
- prevNextField = &this->head;
- curNode = this->head;
- }
- for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
- {
- prevNextField = &curNode->next;
- }
- if(curNode && searchIndex == curNode->startIndex)
- {
- *prevNextFieldOut = prevNextField;
- this->lastUsedNodePrevNextField = prevNextField;
- return curNode;
- }
- if(!create)
- {
- return nullptr;
- }
- BVSparseNode * newNode = Allocate(searchIndex, *prevNextField);
- *prevNextField = newNode;
- *prevNextFieldOut = prevNextField;
- this->lastUsedNodePrevNextField = prevNextField;
- return newNode;
- }
- template <class TAllocator>
- const BVSparseNode<TAllocator> *
- BVSparse<TAllocator>::NodeFromIndex(BVIndex i, Field(BVSparseNode*, TAllocator) const** prevNextFieldOut) const
- {
- const BVIndex searchIndex = SparseBVUnit::Floor(i);
- Field(BVSparseNode*, TAllocator) const* prevNextField = &this->head;
- const BVSparseNode * curNode = *prevNextField;
- if (curNode != nullptr)
- {
- if (curNode->startIndex == searchIndex)
- {
- *prevNextFieldOut = prevNextField;
- return curNode;
- }
- if (curNode->startIndex > searchIndex)
- {
- prevNextField = &this->head;
- curNode = this->head;
- }
- }
- else
- {
- prevNextField = &this->head;
- curNode = this->head;
- }
- for (; curNode && searchIndex > curNode->startIndex; curNode = curNode->next)
- {
- prevNextField = &curNode->next;
- }
- if (curNode && searchIndex == curNode->startIndex)
- {
- *prevNextFieldOut = prevNextField;
- return curNode;
- }
- return nullptr;
- }
- template <class TAllocator>
- SparseBVUnit *
- BVSparse<TAllocator>::BitsFromIndex(BVIndex i, bool create)
- {
- Field(BVSparseNode*, TAllocator)* prevNextField = nullptr;
- BVSparseNode * node = NodeFromIndex(i, &prevNextField, create);
- if (node)
- {
- return &node->data;
- }
- else
- {
- return (SparseBVUnit *)&BVSparse::s_EmptyUnit;
- }
- }
- template <class TAllocator>
- const SparseBVUnit *
- BVSparse<TAllocator>::BitsFromIndex(BVIndex i) const
- {
- Field(BVSparseNode*, TAllocator) const* prevNextField = nullptr;
- const BVSparseNode * node = NodeFromIndex(i, &prevNextField);
- if (node)
- {
- return &node->data;
- }
- else
- {
- return (SparseBVUnit *)&BVSparse::s_EmptyUnit;
- }
- }
- template <class TAllocator>
- BVSparseNode<TAllocator> *
- BVSparse<TAllocator>::DeleteNode(BVSparseNode *node, bool bResetLastUsed)
- {
- BVSparseNode *next = node->next;
- QueueInFreeList(node);
- if (bResetLastUsed)
- {
- this->lastUsedNodePrevNextField = &this->head;
- }
- else
- {
- Assert(this->lastUsedNodePrevNextField != &node->next);
- }
- return next;
- }
- template <class TAllocator>
- BVIndex
- BVSparse<TAllocator>::GetNextBit(BVSparseNode *node) const
- {
- while(0 != node)
- {
- BVIndex ret = node->data.GetNextBit();
- if(-1 != ret)
- {
- return ret + node->startIndex;
- }
- }
- return -1;
- }
- template <class TAllocator>
- BVIndex
- BVSparse<TAllocator>::GetNextBit(BVIndex i) const
- {
- const BVIndex startIndex = SparseBVUnit::Floor(i);
- for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
- {
- if(startIndex == node->startIndex)
- {
- BVIndex ret = node->data.GetNextBit(SparseBVUnit::Offset(i));
- if(-1 != ret)
- {
- return ret + node->startIndex;
- }
- else
- {
- return GetNextBit(node->next);
- }
- }
- else if(startIndex < node->startIndex)
- {
- return GetNextBit(node->next);
- }
- }
- return -1;
- }
- template <class TAllocator>
- template <class TOtherAllocator>
- void
- BVSparse<TAllocator>::AssertBV(const BVSparse<TOtherAllocator> *bv)
- {
- AssertMsg(nullptr != bv, "Cannot operate on NULL bitvector");
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::ClearAll()
- {
- BVSparseNode* nextNode;
- for(BVSparseNode * node = this->head; node != 0 ; node = nextNode)
- {
- nextNode = node->next;
- QueueInFreeList(node);
- }
- this->head = nullptr;
- this->lastUsedNodePrevNextField = &this->head;
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Set(BVIndex i)
- {
- this->BitsFromIndex(i)->Set(SparseBVUnit::Offset(i));
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Clear(BVIndex i)
- {
- Field(BVSparseNode*, TAllocator)* prevNextField = nullptr;
- BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
- if(current)
- {
- current->data.Clear(SparseBVUnit::Offset(i));
- if (current->data.IsEmpty())
- {
- *prevNextField = this->DeleteNode(current, false);
- }
- }
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Compliment(BVIndex i)
- {
- this->BitsFromIndex(i)->Complement(SparseBVUnit::Offset(i));
- }
- template <class TAllocator>
- BOOLEAN
- BVSparse<TAllocator>::TestEmpty() const
- {
- return this->head != nullptr;
- }
- template <class TAllocator>
- BOOLEAN
- BVSparse<TAllocator>::Test(BVIndex i) const
- {
- return this->BitsFromIndex(i)->Test(SparseBVUnit::Offset(i));
- }
- template <class TAllocator>
- BOOLEAN
- BVSparse<TAllocator>::TestAndSet(BVIndex i)
- {
- SparseBVUnit * bvUnit = this->BitsFromIndex(i);
- BVIndex bvIndex = SparseBVUnit::Offset(i);
- BOOLEAN bit = bvUnit->Test(bvIndex);
- bvUnit->Set(bvIndex);
- return bit;
- }
- template <class TAllocator>
- BOOLEAN
- BVSparse<TAllocator>::TestAndClear(BVIndex i)
- {
- Field(BVSparseNode*, TAllocator)* prevNextField = nullptr;
- BVSparseNode * current = this->NodeFromIndex(i, &prevNextField, false /* create */);
- if (current == nullptr)
- {
- return false;
- }
- BVIndex bvIndex = SparseBVUnit::Offset(i);
- BOOLEAN bit = current->data.Test(bvIndex);
- current->data.Clear(bvIndex);
- if (current->data.IsEmpty())
- {
- *prevNextField = this->DeleteNode(current, false);
- }
- return bit;
- }
- template <class TAllocator>
- BOOLEAN
- BVSparse<TAllocator>::operator[](BVIndex i) const
- {
- return this->Test(i);
- }
- template<class TAllocator>
- template<void (SparseBVUnit::*callback)(SparseBVUnit)>
- void BVSparse<TAllocator>::for_each(const BVSparse *bv2)
- {
- Assert(callback == &SparseBVUnit::And || callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor || callback == &SparseBVUnit::Minus);
- AssertBV(bv2);
- BVSparseNode * node1 = this->head;
- const BVSparseNode * node2 = bv2->head;
- Field(BVSparseNode*, TAllocator)* prevNodeNextField = &this->head;
- while(node1 != nullptr && node2 != nullptr)
- {
- if(node2->startIndex == node1->startIndex)
- {
- (node1->data.*callback)(node2->data);
- prevNodeNextField = &node1->next;
- node1 = node1->next;
- node2 = node2->next;
- }
- else if(node2->startIndex > node1->startIndex)
- {
- if (callback == &SparseBVUnit::And)
- {
- node1 = this->DeleteNode(node1);
- *prevNodeNextField = node1;
- }
- else
- {
- prevNodeNextField = &node1->next;
- node1 = node1->next;
- }
- }
- else
- {
- if (callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor)
- {
- BVSparseNode * newNode = Allocate(node2->startIndex, node1);
- (newNode->data.*callback)(node2->data);
- *prevNodeNextField = newNode;
- prevNodeNextField = &newNode->next;
- }
- node2 = node2->next;
- }
- }
- if (callback == &SparseBVUnit::And)
- {
- while (node1 != nullptr)
- {
- node1 = this->DeleteNode(node1);
- }
- *prevNodeNextField = nullptr;
- }
- else if (callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor)
- {
- while(node2 != 0)
- {
- Assert(*prevNodeNextField == nullptr);
- BVSparseNode * newNode = Allocate(node2->startIndex, nullptr);
- *prevNodeNextField = newNode;
- (newNode->data.*callback)(node2->data);
- node2 = node2->next;
- prevNodeNextField = &newNode->next;
- }
- }
- }
- template<class TAllocator>
- template<void (SparseBVUnit::*callback)(SparseBVUnit)>
- void BVSparse<TAllocator>::for_each(const BVSparse *bv1, const BVSparse *bv2)
- {
- Assert(callback == &SparseBVUnit::And || callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor || callback == &SparseBVUnit::Minus);
- Assert(this->IsEmpty());
- AssertBV(bv1);
- AssertBV(bv2);
- BVSparseNode * node1 = bv1->head;
- const BVSparseNode * node2 = bv2->head;
- BVSparseNode * lastNode = nullptr;
- Field(BVSparseNode*, TAllocator)* prevNextField = &this->head;
- while(node1 != nullptr && node2 != nullptr)
- {
- lastNode = node1;
- BVIndex startIndex;
- SparseBVUnit bvUnit1;
- SparseBVUnit bvUnit2;
- if (node2->startIndex == node1->startIndex)
- {
- startIndex = node1->startIndex;
- bvUnit1 = node1->data;
- bvUnit2 = node2->data;
- node1 = node1->next;
- node2 = node2->next;
- }
- else if (node2->startIndex > node1->startIndex)
- {
- startIndex = node1->startIndex;
- bvUnit1 = node1->data;
- node1 = node1->next;
- }
- else
- {
- startIndex = node2->startIndex;
- bvUnit2 = node2->data;
- node2 = node2->next;
- }
- (bvUnit1.*callback)(bvUnit2);
- if (!bvUnit1.IsEmpty())
- {
- BVSparseNode * newNode = Allocate(startIndex, nullptr);
- newNode->data = bvUnit1;
- *prevNextField = newNode;
- prevNextField = &newNode->next;
- }
- }
- if (callback == &SparseBVUnit::Minus || callback == &SparseBVUnit::Or || callback == &SparseBVUnit::Xor)
- {
- BVSparseNode const * copyNode = (callback == &SparseBVUnit::Minus || node1 != nullptr)? node1 : node2;
- while (copyNode != nullptr)
- {
- if (!copyNode->data.IsEmpty())
- {
- BVSparseNode * newNode = Allocate(copyNode->startIndex, nullptr);
- newNode->data = copyNode->data;
- *prevNextField = newNode;
- prevNextField = &newNode->next;
- }
- copyNode = copyNode->next;
- }
- }
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Or(const BVSparse*bv)
- {
- this->for_each<&SparseBVUnit::Or>(bv);
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Or(const BVSparse * bv1, const BVSparse * bv2)
- {
- this->ClearAll();
- this->for_each<&SparseBVUnit::Or>(bv1, bv2);
- }
- template <class TAllocator>
- BVSparse<TAllocator> *
- BVSparse<TAllocator>::OrNew(const BVSparse* bv, TAllocator* allocator) const
- {
- BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
- newBv->for_each<&SparseBVUnit::Or>(this, bv);
- return newBv;
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::And(const BVSparse*bv)
- {
- this->for_each<&SparseBVUnit::And>(bv);
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::And(const BVSparse * bv1, const BVSparse * bv2)
- {
- this->ClearAll();
- this->for_each<&SparseBVUnit::And>(bv1, bv2);
- }
- template <class TAllocator>
- BVSparse<TAllocator> *
- BVSparse<TAllocator>::AndNew(const BVSparse* bv, TAllocator* allocator) const
- {
- BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
- newBv->for_each<&SparseBVUnit::And>(this, bv);
- return newBv;
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Xor(const BVSparse*bv)
- {
- this->for_each<&SparseBVUnit::Xor>(bv);
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Xor(const BVSparse * bv1, const BVSparse * bv2)
- {
- this->ClearAll();
- this->for_each<&SparseBVUnit::Xor>(bv1, bv2);
- }
- template <class TAllocator>
- BVSparse<TAllocator> *
- BVSparse<TAllocator>::XorNew(const BVSparse* bv, TAllocator* allocator) const
- {
- BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
- newBv->for_each<&SparseBVUnit::Xor>(this, bv);
- return newBv;
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Minus(const BVSparse*bv)
- {
- this->for_each<&SparseBVUnit::Minus>(bv);
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Minus(const BVSparse * bv1, const BVSparse * bv2)
- {
- this->ClearAll();
- this->for_each<&SparseBVUnit::Minus>(bv1, bv2);
- }
- template <class TAllocator>
- BVSparse<TAllocator> *
- BVSparse<TAllocator>::MinusNew(const BVSparse* bv, TAllocator* allocator) const
- {
- BVSparse * newBv = AllocatorNew(TAllocator, allocator, BVSparse, allocator);
- newBv->for_each<&SparseBVUnit::Minus>(this, bv);
- return newBv;
- }
- template <class TAllocator>
- template <class TSrcAllocator>
- void
- BVSparse<TAllocator>::Copy(const BVSparse<TSrcAllocator> * bv2)
- {
- AssertBV(bv2);
- CopyFromNode(bv2->head);
- }
- template <class TAllocator>
- template <class TSrcAllocator>
- void
- BVSparse<TAllocator>::CopyFromNode(const ::BVSparseNode<TSrcAllocator> * node2)
- {
- BVSparseNode * node1 = this->head;
- Field(BVSparseNode*, TAllocator)* prevNextField = &this->head;
- while (node1 != nullptr && node2 != nullptr)
- {
- if (!node2->data.IsEmpty())
- {
- node1->startIndex = node2->startIndex;
- node1->data.Copy(node2->data);
- prevNextField = &node1->next;
- node1 = node1->next;
- }
- node2 = node2->next;
- }
- if (node1 != nullptr)
- {
- while (node1 != nullptr)
- {
- node1 = this->DeleteNode(node1);
- }
- *prevNextField = nullptr;
- }
- else
- {
- while (node2 != nullptr)
- {
- if (!node2->data.IsEmpty())
- {
- BVSparseNode * newNode = Allocate(node2->startIndex, nullptr);
- newNode->data.Copy(node2->data);
- *prevNextField = newNode;
- prevNextField = &newNode->next;
- }
- node2 = node2->next;
- }
- }
- }
- template <class TAllocator>
- BVSparse<TAllocator> *
- BVSparse<TAllocator>::CopyNew(TAllocator* allocator) const
- {
- BVSparse * bv = AllocatorNew(TAllocator, allocator, BVSparse<TAllocator>, allocator);
- bv->Copy(this);
- return bv;
- }
- template <class TAllocator>
- BVSparse<TAllocator> *
- BVSparse<TAllocator>::CopyNew() const
- {
- return this->CopyNew(this->alloc);
- }
- template <class TAllocator>
- void
- BVSparse<TAllocator>::ComplimentAll()
- {
- for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
- {
- node->data.ComplimentAll();
- }
- }
- template <class TAllocator>
- BVIndex
- BVSparse<TAllocator>::Count() const
- {
- BVIndex sum = 0;
- for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
- {
- sum += node->data.Count();
- }
- return sum;
- }
- template <class TAllocator>
- bool
- BVSparse<TAllocator>::IsEmpty() const
- {
- for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
- {
- if (!node->data.IsEmpty())
- {
- return false;
- }
- }
- return true;
- }
- template <class TAllocator>
- bool
- BVSparse<TAllocator>::Equal(BVSparse const * bv) const
- {
- BVSparseNode const * bvNode1 = this->head;
- BVSparseNode const * bvNode2 = bv->head;
- while (true)
- {
- while (bvNode1 != nullptr && bvNode1->data.IsEmpty())
- {
- bvNode1 = bvNode1->next;
- }
- while (bvNode2 != nullptr && bvNode2->data.IsEmpty())
- {
- bvNode2 = bvNode2->next;
- }
- if (bvNode1 == nullptr)
- {
- return (bvNode2 == nullptr);
- }
- if (bvNode2 == nullptr)
- {
- return false;
- }
- if (bvNode1->startIndex != bvNode2->startIndex)
- {
- return false;
- }
- if (!bvNode1->data.Equal(bvNode2->data))
- {
- return false;
- }
- bvNode1 = bvNode1->next;
- bvNode2 = bvNode2->next;
- }
- }
- template <class TAllocator>
- bool
- BVSparse<TAllocator>::Test(BVSparse const * bv) const
- {
- BVSparseNode const * bvNode1 = this->head;
- BVSparseNode const * bvNode2 = bv->head;
- while (bvNode1 != nullptr && bvNode2 != nullptr)
- {
- if (bvNode1->data.IsEmpty() || bvNode1->startIndex < bvNode2->startIndex)
- {
- bvNode1 = bvNode1->next;
- continue;
- }
- if (bvNode2->data.IsEmpty() || bvNode1->startIndex > bvNode2->startIndex)
- {
- bvNode2 = bvNode2->next;
- continue;
- }
- Assert(bvNode1->startIndex == bvNode2->startIndex);
- if (bvNode1->data.Test(bvNode2->data))
- {
- return true;
- }
- bvNode1 = bvNode1->next;
- bvNode2 = bvNode2->next;
- }
- return false;
- }
- #ifdef _WIN32
- template<class TAllocator>
- template<class F>
- void BVSparse<TAllocator>::ToString(__out_ecount(strSize) char *const str, const size_t strSize, const F ReadNode) const
- {
- Assert(str);
- if (strSize == 0)
- {
- return;
- }
- str[0] = '\0';
- bool empty = true;
- bool isFirstInSequence = true;
- size_t length = 0;
- BVSparseNode *nodePtr = head;
- while (nodePtr)
- {
- bool readSuccess;
- const BVSparseNode node(ReadNode(nodePtr, &readSuccess));
- if (!readSuccess)
- {
- str[0] = '\0';
- return;
- }
- if (node.data.IsEmpty())
- {
- nodePtr = node.next;
- continue;
- }
- empty = false;
- size_t writtenLength;
- if (!node.ToString(&str[length], strSize - length, &writtenLength, true, isFirstInSequence, !node.next))
- {
- return;
- }
- length += writtenLength;
- isFirstInSequence = false;
- nodePtr = node.next;
- }
- if (empty && _countof("{}") < strSize)
- {
- strcpy_s(str, strSize, "{}");
- }
- }
- template<class TAllocator>
- void BVSparse<TAllocator>::ToString(__out_ecount(strSize) char *const str, const size_t strSize) const
- {
- ToString(
- str,
- strSize,
- [](BVSparseNode *const nodePtr, bool *const successRef) -> BVSparseNode
- {
- Assert(nodePtr);
- Assert(successRef);
- *successRef = true;
- return *nodePtr;
- });
- }
- #endif
- #if DBG_DUMP
- template <class TAllocator>
- void
- BVSparse<TAllocator>::Dump() const
- {
- bool hasBits = false;
- Output::Print(_u("[ "));
- for(BVSparseNode * node = this->head; node != 0 ; node = node->next)
- {
- hasBits = node->data.Dump(node->startIndex, hasBits);
- }
- Output::Print(_u("]\n"));
- }
- #endif
|