1 // Created on: 2005-11-05
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <TColStd_PackedMapOfInteger.hxx>
17 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
18 #include <TCollection_MapNode.hxx>
19 #include <Standard_DefineHandle.hxx>
22 #define MASK_LOW 0x001f
24 #define MASK_HIGH (~MASK_LOW)
27 * Class implementing a block of 32 consecutive integer values as a node of
28 * a Map collection. The data are stored in 64 bits as:
29 * - bits 0 - 4 : (number of integers stored in the block) - 1;
30 * - bits 5 - 31: base address of the block of integers (low bits assumed 0)
31 * - bits 32 - 63: 32-bit field where each bit indicates the presence of the
32 * corresponding integer in the block. Number of non-zero bits
33 * must be equal to the number expressed in bits 0-4.
35 class TColStd_intMapNode : public TCollection_MapNode
38 inline TColStd_intMapNode (TCollection_MapNode * ptr = 0L)
39 : TCollection_MapNode (ptr),
43 inline TColStd_intMapNode (const Standard_Integer theValue,
44 TCollection_MapNode *& ptr)
45 : TCollection_MapNode (ptr),
46 myMask ((unsigned int) (theValue & MASK_HIGH)),
47 myData (1 << (theValue & MASK_LOW)) {}
49 inline TColStd_intMapNode (unsigned int theMask,
51 TCollection_MapNode * ptr)
52 : TCollection_MapNode (ptr),
56 inline unsigned int Mask () const
59 inline unsigned int Data () const
62 inline unsigned int& ChangeMask ()
65 inline unsigned int& ChangeData ()
68 inline Standard_Integer Key () const
69 { return Standard_Integer (myMask & MASK_HIGH); }
71 inline size_t NbValues () const
72 { return size_t(myMask & MASK_LOW) + 1; }
74 inline Standard_Boolean HasValues () const
75 { return (myData != 0); }
77 Standard_Integer HasValue (const Standard_Integer theValue) const
78 { return (myData & (1 << (theValue & MASK_LOW))); }
80 Standard_Boolean AddValue (const Standard_Integer theValue);
82 Standard_Boolean DelValue (const Standard_Integer theValue);
85 * Find the smallest non-zero bit under the given mask. Outputs the new mask
86 * that does not contain the detected bit.
88 Standard_Integer FindNext (unsigned int& theMask) const;
91 * Support of Map interface.
93 inline Standard_Integer HashCode (const Standard_Integer theUpper) const
95 return ::HashCode (Standard_Integer(myMask >> 5), theUpper);
99 * Support of Map interface.
101 inline Standard_Boolean IsEqual (const Standard_Integer theOther) const
103 return ((myMask >> 5) == (unsigned)theOther);
107 * Local friend function, used in TColStd_MapIteratorOfPackedMapOfInteger.
109 friend Standard_Integer TColStd_intMapNode_findNext(const TColStd_intMapNode*,
113 * Local friend function.
115 friend Standard_Integer TColStd_intMapNode_findPrev(const TColStd_intMapNode*,
124 //=======================================================================
125 //function : TColStd_intMapNode::AddValue
127 //=======================================================================
129 Standard_Boolean TColStd_intMapNode::AddValue (const Standard_Integer theValue)
131 Standard_Boolean aResult (Standard_False);
132 const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
133 if ((myData & aValInt) == 0) {
136 aResult = Standard_True;
141 //=======================================================================
142 //function : TColStd_intMapNode::DelValue
144 //=======================================================================
146 Standard_Boolean TColStd_intMapNode::DelValue (const Standard_Integer theValue)
148 Standard_Boolean aResult (Standard_False);
149 const Standard_Integer aValInt = (1 << (theValue & MASK_LOW));
150 if ((myData & aValInt) != 0) {
153 aResult = Standard_True;
158 //=======================================================================
159 //function : TColStd_Population
160 //purpose : Compute the population (i.e., the number of non-zero bits) of
161 // the 32-bit word theData. The population is stored decremented
162 // as it is defined in TColStd_intMapNode.
163 //source : H.S.Warren, Hacker''s Delight, Addison-Wesley Inc. 2002, Ch.5.1
164 //=======================================================================
166 inline size_t TColStd_Population (unsigned int& theMask,
167 const unsigned int theData)
169 unsigned int aRes = theData - ((theData>>1) & 0x55555555);
170 aRes = (aRes & 0x33333333) + ((aRes>>2) & 0x33333333);
171 aRes = (aRes + (aRes>>4)) & 0x0f0f0f0f;
172 aRes = aRes + (aRes>>8);
173 aRes = aRes + (aRes>>16);
174 theMask = (theMask & MASK_HIGH) | ((aRes-1) & MASK_LOW);
175 return (size_t) (aRes & 0x3f);
178 //=======================================================================
179 //function : TColStd_intMapNode_findNext
180 //purpose : Find the smallest non-zero bit under the given mask. Outputs
181 // the new mask that does not contain the detected bit.
182 //=======================================================================
184 Standard_Integer TColStd_intMapNode_findNext (const TColStd_intMapNode* theNode,
185 unsigned int& theMask)
187 unsigned int val = theNode->myData & theMask;
190 theMask = ~0U; // void, nothing to do
192 unsigned int aMask = ~0U;
193 if ((val & 0x0000ffff) == 0) {
198 if ((val & 0x000000ff) == 0) {
203 if ((val & 0x0000000f) == 0) {
208 if ((val & 0x00000003) == 0) {
213 if ((val & 0x00000001) == 0) {
217 theMask = (aMask << 1);
219 return nZeros + theNode->Key();
222 //=======================================================================
223 //function : TColStd_intMapNode_findPrev
224 //purpose : Find the highest non-zero bit under the given mask. Outputs
225 // the new mask that does not contain the detected bit.
226 //=======================================================================
228 Standard_Integer TColStd_intMapNode_findPrev (const TColStd_intMapNode* theNode,
229 unsigned int& theMask)
231 unsigned int val = theNode->myData & theMask;
234 theMask = ~0U; // void, nothing to do
236 unsigned int aMask = ~0U;
237 if ((val & 0xffff0000) == 0) {
242 if ((val & 0xff000000) == 0) {
247 if ((val & 0xf0000000) == 0) {
252 if ((val & 0xc0000000) == 0) {
257 if ((val & 0x80000000) == 0) {
261 theMask = (aMask >> 1);
263 return (31 - nZeros) + theNode->Key();
266 //=======================================================================
269 //=======================================================================
271 TColStd_PackedMapOfInteger& TColStd_PackedMapOfInteger::Assign
272 (const TColStd_PackedMapOfInteger& theOther)
274 if (this != &theOther) {
276 if (!theOther.IsEmpty()) {
277 ReSize (theOther.InternalExtent());
278 const Standard_Integer nBucketsSrc = theOther.NbBuckets();
279 const Standard_Integer nBuckets = NbBuckets();
280 const TColStd_intMapNode** aDataSrc =
281 (const TColStd_intMapNode**) theOther.myData1;
282 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
283 for (Standard_Integer i = 0; i <= nBucketsSrc; i++) {
284 const TColStd_intMapNode * p = aDataSrc[i];
286 const Standard_Integer aHashCode = p->HashCode(nBuckets);
288 new TColStd_intMapNode (p->Mask(), p->Data(), aData[aHashCode]);
290 p = reinterpret_cast <const TColStd_intMapNode*> (p->Next());
293 // TColStd_MapIteratorOfPackedMapOfInteger anIt (theOther);
294 // for (; anIt.More(); anIt.Next())
298 myExtent = theOther.myExtent;
302 //=======================================================================
305 //=======================================================================
307 void TColStd_PackedMapOfInteger::ReSize (const Standard_Integer nbBuckets)
309 Standard_Integer newBuck;
310 Standard_Address newData1=NULL, dummy=NULL;
311 if (BeginResize (nbBuckets, newBuck, newData1, dummy))
314 TColStd_intMapNode** newdata =
315 reinterpret_cast <TColStd_intMapNode**> (newData1);
316 TColStd_intMapNode** olddata =
317 reinterpret_cast <TColStd_intMapNode**> (myData1);
318 TColStd_intMapNode * p;
319 Standard_Integer i,k;
320 for (i = 0; i <= NbBuckets(); i++) {
324 k = p->HashCode(newBuck);
325 TCollection_MapNode * q = p->Next();
326 p->Next() = newdata[k];
328 p = static_cast <TColStd_intMapNode*> (q);
333 EndResize (nbBuckets, newBuck, newData1, dummy);
337 //=======================================================================
340 //=======================================================================
342 void TColStd_PackedMapOfInteger::Clear ()
346 TColStd_intMapNode** data =
347 reinterpret_cast <TColStd_intMapNode**> (myData1);
348 TColStd_intMapNode * p;
349 for (i = 0; i <= NbBuckets(); i++) {
353 TCollection_MapNode * q = p->Next();
355 p = static_cast <TColStd_intMapNode*> (q);
360 TCollection_BasicMap::Destroy();
364 //=======================================================================
367 //=======================================================================
369 Standard_Boolean TColStd_PackedMapOfInteger::Add (const Standard_Integer aKey)
372 ReSize(InternalExtent());
373 Standard_Boolean aResult (Standard_False);
374 TColStd_intMapNode ** data =
375 reinterpret_cast <TColStd_intMapNode**> (myData1);
376 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
377 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
378 TCollection_MapNodePtr aBucketHead = data[aHashCode];
379 TColStd_intMapNode * p = static_cast<TColStd_intMapNode*> (aBucketHead);
381 if (p->IsEqual(aKeyInt)) {
382 aResult = p->AddValue (aKey);
384 goto finish; // goto saves us 4 CPU clocks or 4% performance
386 p = reinterpret_cast <TColStd_intMapNode*> (p->Next());
388 // if (!p) { // not needed, as long as we exit the loop by goto
389 data[aHashCode] = new TColStd_intMapNode(aKey, aBucketHead);
391 aResult = Standard_True;
399 //=======================================================================
400 //function : Contains
402 //=======================================================================
404 Standard_Boolean TColStd_PackedMapOfInteger::Contains
405 (const Standard_Integer aKey) const
407 Standard_Boolean aResult (Standard_False);
409 TColStd_intMapNode** data = (TColStd_intMapNode**) myData1;
410 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
411 TColStd_intMapNode * p = data[HashCode (aKeyInt, NbBuckets())];
413 if (p->IsEqual(aKeyInt)) {
414 aResult = (p->HasValue (aKey) != 0);
417 p = reinterpret_cast <TColStd_intMapNode*> (p->Next());
423 //=======================================================================
426 //=======================================================================
428 Standard_Boolean TColStd_PackedMapOfInteger::Remove(const Standard_Integer aKey)
430 Standard_Boolean aResult (Standard_False);
432 TColStd_intMapNode** data =
433 reinterpret_cast <TColStd_intMapNode**> (myData1);
434 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
435 TColStd_intMapNode*& aBucketHead = data[HashCode(aKeyInt, NbBuckets())];
436 TColStd_intMapNode* p = aBucketHead;
437 TColStd_intMapNode* q = 0L;
439 if (p->IsEqual(aKeyInt)) {
440 aResult = p->DelValue (aKey);
443 if (p->HasValues() == Standard_False) {
445 if (q) q->Next() = p->Next();
446 else aBucketHead = reinterpret_cast<TColStd_intMapNode*>(p->Next());
453 p = reinterpret_cast <TColStd_intMapNode*> (p->Next());
459 //=======================================================================
460 //function : GetMinimalMapped
461 //purpose : Query the minimal contained key value.
462 //=======================================================================
464 Standard_Integer TColStd_PackedMapOfInteger::GetMinimalMapped () const
466 Standard_Integer aResult (IntegerLast());
468 const TCollection_MapNode** aData = (const TCollection_MapNode**) myData1;
469 const TColStd_intMapNode * pFoundNode = 0L;
470 for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
471 for (const TCollection_MapNode * p = aData[i]; p != 0L; p = p->Next()) {
472 const Standard_Integer aKey =
473 reinterpret_cast <const TColStd_intMapNode *>(p)->Key();
474 if (aResult > aKey) {
476 pFoundNode = reinterpret_cast<const TColStd_intMapNode *>(p);
481 unsigned int aFullMask (0xffffffff);
482 aResult = TColStd_intMapNode_findNext (pFoundNode, aFullMask);
488 //=======================================================================
489 //function : GetMaximalMapped
490 //purpose : Query the maximal contained key value.
491 //=======================================================================
493 Standard_Integer TColStd_PackedMapOfInteger::GetMaximalMapped () const
495 Standard_Integer aResult (IntegerFirst());
497 const TCollection_MapNode** aData = (const TCollection_MapNode**) myData1;
498 const TColStd_intMapNode * pFoundNode = 0L;
499 for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
500 for (const TCollection_MapNode * p = aData[i]; p != 0L; p = p->Next()) {
501 const Standard_Integer aKey =
502 reinterpret_cast <const TColStd_intMapNode *>(p)->Key();
503 if (aResult < aKey) {
505 pFoundNode = reinterpret_cast<const TColStd_intMapNode *>(p);
510 unsigned int aFullMask (0xffffffff);
511 aResult = TColStd_intMapNode_findPrev (pFoundNode, aFullMask);
517 //=======================================================================
519 //purpose : Boolean operation OR between 2 maps
520 //=======================================================================
522 void TColStd_PackedMapOfInteger::Union (const TColStd_PackedMapOfInteger& theMap1,
523 const TColStd_PackedMapOfInteger& theMap2)
525 if (theMap1.IsEmpty()) // 0 | B == B
527 else if (theMap2.IsEmpty()) // A | 0 == A
529 else if (myData1 == theMap1.myData1)
531 else if (myData1 == theMap2.myData1)
535 const TColStd_intMapNode** aData1 =
536 (const TColStd_intMapNode**) theMap1.myData1;
537 const TColStd_intMapNode** aData2 =
538 (const TColStd_intMapNode**) theMap2.myData1;
539 const Standard_Integer nBuckets1 = theMap1.NbBuckets();
540 const Standard_Integer nBuckets2 = theMap2.NbBuckets();
542 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
543 // Iteration of the 1st map.
544 for (i = 0; i <= nBuckets1; i++) {
545 const TColStd_intMapNode * p1 = aData1[i];
547 // Find aKey - the base address of currently iterated block
548 const Standard_Integer aKey = p1->Key();
549 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
550 unsigned int aNewMask = p1->Mask();
551 unsigned int aNewData = p1->Data();
552 size_t nValues (p1->NbValues());
553 // Find the corresponding block in the 2nd map
554 const TColStd_intMapNode * p2 =
555 aData2 [HashCode (aKeyInt, nBuckets2)];
557 if (p2->IsEqual(aKeyInt)) {
558 aNewData |= p2->Data();
559 nValues = TColStd_Population (aNewMask, aNewData);
562 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
564 // Store the block - result of operation
566 ReSize(InternalExtent());
567 aData = (TColStd_intMapNode**) myData1;
569 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
570 aData[aHashCode] = new TColStd_intMapNode (aNewMask, aNewData,
574 p1 = reinterpret_cast <const TColStd_intMapNode*> (p1->Next());
577 // Iteration of the 2nd map.
578 for (i = 0; i <= nBuckets2; i++) {
579 const TColStd_intMapNode * p2 = aData2[i];
581 // Find aKey - the base address of currently iterated block
582 const Standard_Integer aKey = p2->Key();
583 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
584 // Find the corresponding block in the 1st map
585 const TColStd_intMapNode * p1 =
586 aData1 [HashCode (aKeyInt, nBuckets1)];
588 if (p1->IsEqual(aKeyInt))
590 p1 = reinterpret_cast <const TColStd_intMapNode*> (p1->Next());
592 // Add the block from the 2nd map only in the case when the similar
593 // block has not been found in the 1st map
596 ReSize(InternalExtent());
597 aData = (TColStd_intMapNode**) myData1;
599 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
600 aData[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
603 myExtent += p2->NbValues();
605 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
611 //=======================================================================
613 //purpose : Boolean operation OR with the given map
614 //=======================================================================
616 Standard_Boolean TColStd_PackedMapOfInteger::Unite(const TColStd_PackedMapOfInteger& theMap)
618 if (theMap.IsEmpty() || myData1 == theMap.myData1) // A | 0 == A | A == A
619 return Standard_False;
620 else if ( IsEmpty() ) { // 0 | B == B
622 return Standard_True;
625 size_t aNewExtent (myExtent);
626 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
627 const TColStd_intMapNode** aData2 =
628 (const TColStd_intMapNode**) theMap.myData1;
629 const Standard_Integer nBuckets2 = theMap.NbBuckets();
631 // Iteration of the 2nd map.
632 for (Standard_Integer i = 0; i <= nBuckets2; i++) {
633 const TColStd_intMapNode * p2 = aData2[i];
635 // Find aKey - the base address of currently iterated block of integers
636 const Standard_Integer aKey = p2->Key();
637 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
638 // Find the corresponding block in the 1st (this) map
639 Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
640 TColStd_intMapNode * p1 = aData[aHashCode];
642 if (p1->IsEqual(aKeyInt)) {
643 const size_t anOldPop = p1->NbValues();
644 unsigned int newData = p1->Data() | p2->Data();
645 if ( newData != p1->Data() ) {
646 p1->ChangeData() = newData;
647 aNewExtent = aNewExtent - anOldPop +
648 TColStd_Population (p1->ChangeMask(), newData);
652 p1 = reinterpret_cast <TColStd_intMapNode*> (p1->Next());
654 // If the block is not found in the 1st map, add it to the 1st map
657 ReSize(InternalExtent());
658 aData = (TColStd_intMapNode**) myData1;
659 aHashCode = HashCode (aKeyInt, NbBuckets());
661 aData[aHashCode] = new TColStd_intMapNode (p2->Mask(), p2->Data(),
664 aNewExtent += p2->NbValues();
666 p2 = reinterpret_cast <TColStd_intMapNode*> (p2->Next());
669 Standard_Boolean isChanged = ( myExtent != aNewExtent );
670 myExtent = aNewExtent;
675 //=======================================================================
676 //function : Intersection
677 //purpose : Boolean operation AND between 2 maps
678 //=======================================================================
680 void TColStd_PackedMapOfInteger::Intersection
681 (const TColStd_PackedMapOfInteger& theMap1,
682 const TColStd_PackedMapOfInteger& theMap2)
684 if (theMap1.IsEmpty() || theMap2.IsEmpty()) // A & 0 == 0 & B == 0
686 else if (myData1 == theMap1.myData1)
688 else if (myData1 == theMap2.myData1)
691 const TColStd_intMapNode** aData1, ** aData2;
692 Standard_Integer nBuckets1, nBuckets2;
693 if (theMap1.Extent() < theMap2.Extent()) {
694 aData1 = (const TColStd_intMapNode**) theMap1.myData1;
695 aData2 = (const TColStd_intMapNode**) theMap2.myData1;
696 nBuckets1 = theMap1.NbBuckets();
697 nBuckets2 = theMap2.NbBuckets();
700 aData1 = (const TColStd_intMapNode**) theMap2.myData1;
701 aData2 = (const TColStd_intMapNode**) theMap1.myData1;
702 nBuckets1 = theMap2.NbBuckets();
703 nBuckets2 = theMap1.NbBuckets();
706 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
707 // Iteration of the 1st map.
708 for (Standard_Integer i = 0; i <= nBuckets1; i++) {
709 const TColStd_intMapNode * p1 = aData1[i];
711 // Find aKey - the base address of currently iterated block
712 const Standard_Integer aKey = p1->Key();
713 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
714 // Find the corresponding block in the 2nd map
715 const TColStd_intMapNode * p2 =
716 aData2 [HashCode (aKeyInt, nBuckets2)];
718 if (p2->IsEqual(aKeyInt)) {
719 const unsigned int aNewData = p1->Data() & p2->Data();
720 // Store the block - result of operation
723 ReSize(InternalExtent());
724 aData = (TColStd_intMapNode**) myData1;
726 const Standard_Integer aHashCode = HashCode (aKeyInt,
728 unsigned int aNewMask = p1->Mask();
729 myExtent += TColStd_Population (aNewMask, aNewData);
730 aData[aHashCode]= new TColStd_intMapNode(aNewMask, aNewData,
736 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
738 p1 = reinterpret_cast <const TColStd_intMapNode*> (p1->Next());
744 //=======================================================================
745 //function : Intersect
746 //purpose : Boolean operation AND with the given map
747 //=======================================================================
749 Standard_Boolean TColStd_PackedMapOfInteger::Intersect
750 (const TColStd_PackedMapOfInteger& theMap)
752 if ( IsEmpty() ) // 0 & B == 0
753 return Standard_False;
754 else if (theMap.IsEmpty()) { // A & 0 == 0
756 return Standard_True;
758 else if (myData1 == theMap.myData1) // A & A == A
759 return Standard_False;
761 size_t aNewExtent (0);
762 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
763 const TColStd_intMapNode** aData2 =
764 (const TColStd_intMapNode**) theMap.myData1;
765 const Standard_Integer nBuckets2 = theMap.NbBuckets();
767 // Iteration of this map.
768 for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
769 TColStd_intMapNode * q = 0L;
770 TColStd_intMapNode * p1 = aData[i];
772 // Find aKey - the base address of currently iterated block of integers
773 const Standard_Integer aKey = p1->Key();
774 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
775 // Find the corresponding block in the 2nd map
776 const TColStd_intMapNode * p2 =
777 aData2 [HashCode (aKeyInt, nBuckets2)];
779 if (p2->IsEqual(aKeyInt)) {
780 const unsigned int aNewData = p1->Data() & p2->Data();
781 // Store the block - result of operation
783 p2 = 0L; // no match - the block has to be removed
786 if ( aNewData != p1->Data() )
787 p1->ChangeData() = aNewData;
788 aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
792 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
794 TColStd_intMapNode* pNext =
795 reinterpret_cast <TColStd_intMapNode*> (p1->Next());
796 // If p2!=NULL, then the map node is kept and we move to the next one
797 // Otherwise we should remove the current node
802 if (q) q->Next() = pNext;
803 else aData[i] = pNext;
809 Standard_Boolean isChanged = ( myExtent != aNewExtent );
810 myExtent = aNewExtent;
815 //=======================================================================
816 //function : Subtraction
817 //purpose : Boolean operation SUBTRACT between two maps
818 //=======================================================================
820 void TColStd_PackedMapOfInteger::Subtraction
821 (const TColStd_PackedMapOfInteger& theMap1,
822 const TColStd_PackedMapOfInteger& theMap2)
824 if (theMap1.IsEmpty() || theMap2.myData1 == theMap1.myData1) // 0 \ A == A \ A == 0
826 else if (theMap2.IsEmpty()) // A \ 0 == A
828 else if (myData1 == theMap1.myData1)
830 else if (myData1 == theMap2.myData1) {
831 TColStd_PackedMapOfInteger aMap;
832 aMap.Subtraction ( theMap1, theMap2 );
836 const TColStd_intMapNode** aData1 =
837 (const TColStd_intMapNode**) theMap1.myData1;
838 const TColStd_intMapNode** aData2 =
839 (const TColStd_intMapNode**) theMap2.myData1;
840 const Standard_Integer nBuckets1 = theMap1.NbBuckets();
841 const Standard_Integer nBuckets2 = theMap2.NbBuckets();
843 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
844 // Iteration of the 1st map.
845 for (Standard_Integer i = 0; i <= nBuckets1; i++) {
846 const TColStd_intMapNode * p1 = aData1[i];
848 // Find aKey - the base address of currently iterated block of integers
849 const Standard_Integer aKey = p1->Key();
850 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
851 unsigned int aNewMask = p1->Mask();
852 unsigned int aNewData = p1->Data();
853 size_t nValues (p1->NbValues());
854 // Find the corresponding block in the 2nd map
855 const TColStd_intMapNode * p2 =
856 aData2 [HashCode (aKeyInt, nBuckets2)];
858 if (p2->IsEqual(aKeyInt)) {
859 aNewData &= ~p2->Data();
860 nValues = TColStd_Population (aNewMask, aNewData);
863 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
865 // Store the block - result of operation
868 ReSize(InternalExtent());
869 aData = (TColStd_intMapNode**) myData1;
871 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
872 aData[aHashCode]= new TColStd_intMapNode (aNewMask, aNewData,
877 p1 = reinterpret_cast <const TColStd_intMapNode*> (p1->Next());
883 //=======================================================================
884 //function : Subtract
885 //purpose : Boolean operation SUBTRACT with the given map
886 //=======================================================================
888 Standard_Boolean TColStd_PackedMapOfInteger::Subtract
889 (const TColStd_PackedMapOfInteger& theMap)
891 if ( IsEmpty() || theMap.IsEmpty() ) // 0 \ B == 0; A \ 0 == A
892 return Standard_False;
893 else if (myData1 == theMap.myData1) { // A \ A == 0
895 return Standard_True;
898 size_t aNewExtent (0);
899 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
900 const TColStd_intMapNode** aData2 =
901 (const TColStd_intMapNode**) theMap.myData1;
902 const Standard_Integer nBuckets2 = theMap.NbBuckets();
903 // Iteration of this map.
904 for (Standard_Integer i = 0; i <= NbBuckets(); i++) {
905 TColStd_intMapNode * q = 0L;
906 TColStd_intMapNode * p1 = aData[i];
908 // Find aKey - the base address of currently iterated block of integers
909 const Standard_Integer aKey = p1->Key();
910 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
911 TColStd_intMapNode* pNext =
912 reinterpret_cast <TColStd_intMapNode*> (p1->Next());
913 // Find the corresponding block in the 2nd map
914 const TColStd_intMapNode * p2 =
915 aData2 [HashCode (aKeyInt, nBuckets2)];
917 if (p2->IsEqual(aKeyInt)) {
918 const unsigned int aNewData = p1->Data() & ~p2->Data();
919 // Store the block - result of operation
921 // no match - the block has to be removed
923 if (q) q->Next() = pNext;
924 else aData[i] = pNext;
927 else if ( aNewData != p1->Data() ) {
928 p1->ChangeData() = aNewData;
929 aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
933 aNewExtent += p1->NbValues();
938 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
941 aNewExtent += p1->NbValues();
947 Standard_Boolean isChanged = ( myExtent != aNewExtent );
948 myExtent = aNewExtent;
953 //=======================================================================
954 //function : Difference
955 //purpose : Boolean operation XOR
956 //=======================================================================
958 void TColStd_PackedMapOfInteger::Difference (const TColStd_PackedMapOfInteger& theMap1,
959 const TColStd_PackedMapOfInteger& theMap2)
961 if (theMap1.IsEmpty()) // 0 ^ B == B
963 else if (theMap2.IsEmpty()) // A ^ 0 == A
965 else if (myData1 == theMap1.myData1)
967 else if (myData1 == theMap2.myData1)
971 const TColStd_intMapNode** aData1 =
972 (const TColStd_intMapNode**) theMap1.myData1;
973 const TColStd_intMapNode** aData2 =
974 (const TColStd_intMapNode**) theMap2.myData1;
975 const Standard_Integer nBuckets1 = theMap1.NbBuckets();
976 const Standard_Integer nBuckets2 = theMap2.NbBuckets();
978 TColStd_intMapNode** aData = (TColStd_intMapNode**) myData1;
980 // Iteration of the 1st map.
981 for (i = 0; i <= nBuckets1; i++) {
982 const TColStd_intMapNode * p1 = aData1[i];
984 // Find aKey - the base address of currently iterated block of integers
985 const Standard_Integer aKey = p1->Key();
986 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
987 unsigned int aNewMask = p1->Mask();
988 unsigned int aNewData = p1->Data();
989 size_t nValues (p1->NbValues());
990 // Find the corresponding block in the 2nd map
991 const TColStd_intMapNode * p2 =
992 aData2 [HashCode (aKeyInt, nBuckets2)];
994 if (p2->IsEqual(aKeyInt)) {
995 aNewData ^= p2->Data();
996 nValues = TColStd_Population (aNewMask, aNewData);
999 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
1001 // Store the block - result of operation
1004 ReSize(InternalExtent());
1005 aData = (TColStd_intMapNode**) myData1;
1007 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
1008 aData[aHashCode]= new TColStd_intMapNode (aNewMask, aNewData,
1011 myExtent += nValues;
1013 p1 = reinterpret_cast <const TColStd_intMapNode*> (p1->Next());
1017 // Iteration of the 2nd map.
1018 for (i = 0; i <= nBuckets2; i++) {
1019 const TColStd_intMapNode * p2 = aData2[i];
1021 // Find aKey - the base address of currently iterated block
1022 const Standard_Integer aKey = p2->Key();
1023 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
1024 // Find the corresponding block in the 1st map
1025 const TColStd_intMapNode * p1 =
1026 aData1 [HashCode (aKeyInt, nBuckets1)];
1028 if (p1->IsEqual(aKeyInt))
1030 p1 = reinterpret_cast <const TColStd_intMapNode*> (p1->Next());
1032 // Add the block from the 2nd map only in the case when the similar
1033 // block has not been found in the 1st map
1036 ReSize(InternalExtent());
1037 aData = (TColStd_intMapNode**) myData1;
1039 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
1040 aData[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
1043 myExtent += p2->NbValues();
1045 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
1051 //=======================================================================
1053 //purpose : Boolean operation XOR
1054 //=======================================================================
1056 Standard_Boolean TColStd_PackedMapOfInteger::Differ(const TColStd_PackedMapOfInteger& theMap)
1058 if (theMap.IsEmpty()) // A ^ 0 = A
1059 return Standard_False;
1060 else if (IsEmpty()) { // 0 ^ B = B
1062 return Standard_True;
1064 else if( myData1 == theMap.myData1) { // A ^ A == 0
1066 return Standard_True;
1069 size_t aNewExtent (0);
1070 TColStd_intMapNode** aData1 = (TColStd_intMapNode**) myData1;
1071 const TColStd_intMapNode** aData2 =
1072 (const TColStd_intMapNode**) theMap.myData1;
1073 const Standard_Integer nBuckets2 = theMap.NbBuckets();
1074 Standard_Boolean isChanged = Standard_False;
1075 Standard_Integer i = 0;
1076 // Iteration by other map
1077 for ( ; i <= nBuckets2; i++) {
1078 TColStd_intMapNode * q = 0L;
1079 const TColStd_intMapNode * p2 = aData2[i];
1081 // Find aKey - the base address of currently iterated block
1082 const Standard_Integer aKey = p2->Key();
1083 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
1085 // Find the corresponding block in the 1st map
1086 TColStd_intMapNode * p1 =
1087 aData1[HashCode (aKeyInt, NbBuckets())];
1088 TColStd_intMapNode* pNext =
1089 reinterpret_cast <TColStd_intMapNode*> (p1->Next());
1092 if (p1->IsEqual(aKeyInt)) {
1093 const unsigned int aNewData = p1->Data() ^ p2->Data();
1094 // Store the block - result of operation
1095 if (aNewData == 0) {
1096 // no match - the block has to be removed
1098 if (q) q->Next() = pNext;
1099 else aData1[i] = pNext;
1102 else if ( aNewData != p1->Data() ) {
1103 p1->ChangeData() = aNewData;
1104 isChanged = Standard_True;
1105 aNewExtent += TColStd_Population (p1->ChangeMask(), aNewData);
1112 // Add the block from the 2nd map only in the case when the similar
1113 // block has not been found in the 1st map
1114 TColStd_intMapNode** aData = NULL;
1117 ReSize(InternalExtent());
1118 aData = (TColStd_intMapNode**) myData1;
1120 const Standard_Integer aHashCode = HashCode (aKeyInt, NbBuckets());
1121 aData[aHashCode]= new TColStd_intMapNode (p2->Mask(), p2->Data(),
1124 aNewExtent += p2->NbValues();
1125 isChanged = Standard_True;
1127 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
1130 myExtent = aNewExtent;
1135 //=======================================================================
1136 //function : IsEqual
1137 //purpose : Boolean operation returns true if this map is equal to the other map
1138 //=======================================================================
1140 Standard_Boolean TColStd_PackedMapOfInteger::IsEqual(const TColStd_PackedMapOfInteger& theMap) const
1142 if (IsEmpty() && theMap.IsEmpty())
1143 return Standard_True;
1144 else if ( Extent() != theMap.Extent() )
1145 return Standard_False;
1147 const TColStd_intMapNode** aData1 = (const TColStd_intMapNode**) myData1;
1148 const TColStd_intMapNode** aData2 = (const TColStd_intMapNode**) theMap.myData1;
1149 const Standard_Integer nBuckets2 = theMap.NbBuckets();
1150 if(aData1 == aData2)
1151 return Standard_True;
1153 Standard_Integer i = 0;
1154 // Iteration of this map.
1155 for (; i <= NbBuckets(); i++) {
1156 const TColStd_intMapNode * p1 = aData1[i];
1158 // Find aKey - the base address of currently iterated block of integers
1159 const Standard_Integer aKey = p1->Key();
1160 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
1161 TColStd_intMapNode* pNext =
1162 reinterpret_cast <TColStd_intMapNode*> (p1->Next());
1163 // Find the corresponding block in the 2nd map
1164 const TColStd_intMapNode * p2 =
1165 aData2 [HashCode (aKeyInt, nBuckets2)];
1167 if ( p2->IsEqual(aKeyInt) ) {
1168 if ( p1->Data() != p2->Data() )
1169 return Standard_False;
1172 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
1174 // if the same block not found, maps are different
1176 return Standard_False;
1181 return Standard_True;
1185 //=======================================================================
1186 //function : IsSubset
1187 //purpose : Boolean operation returns true if this map if subset of other map
1188 //=======================================================================
1190 Standard_Boolean TColStd_PackedMapOfInteger::IsSubset (const TColStd_PackedMapOfInteger& theMap) const
1192 if ( IsEmpty() ) // 0 <= A
1193 return Standard_True;
1194 else if ( theMap.IsEmpty() ) // ! ( A <= 0 )
1195 return Standard_False;
1196 else if ( Extent() > theMap.Extent() )
1197 return Standard_False;
1199 const TColStd_intMapNode** aData1 = (const TColStd_intMapNode**) myData1;
1200 const TColStd_intMapNode** aData2 = (const TColStd_intMapNode**) theMap.myData1;
1201 if(aData1 == aData2)
1202 return Standard_True;
1203 const Standard_Integer nBuckets2 = theMap.NbBuckets();
1205 Standard_Integer i = 0;
1206 // Iteration of this map.
1207 for (; i <= NbBuckets(); i++) {
1208 const TColStd_intMapNode * p1 = aData1[i];
1210 // Find aKey - the base address of currently iterated block of integers
1211 const Standard_Integer aKey = p1->Key();
1212 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
1213 TColStd_intMapNode* pNext =
1214 reinterpret_cast <TColStd_intMapNode*> (p1->Next());
1215 // Find the corresponding block in the 2nd map
1216 const TColStd_intMapNode * p2 =
1217 aData2 [HashCode (aKeyInt, nBuckets2)];
1219 if ( p2->IsEqual(aKeyInt) ) {
1220 if ( p1->Data() & ~p2->Data() ) // at least one bit set in p1 is not set in p2
1221 return Standard_False;
1224 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
1229 return Standard_True;
1233 //=======================================================================
1234 //function : HasIntersection
1235 //purpose : Boolean operation returns true if this map intersects with other map
1236 //=======================================================================
1238 Standard_Boolean TColStd_PackedMapOfInteger::HasIntersection (const TColStd_PackedMapOfInteger& theMap) const
1240 if (IsEmpty() || theMap.IsEmpty()) // A * 0 == 0 * B == 0
1241 return Standard_False;
1243 const TColStd_intMapNode** aData1 = (const TColStd_intMapNode**) myData1;
1244 const TColStd_intMapNode** aData2 = (const TColStd_intMapNode**) theMap.myData1;
1245 const Standard_Integer nBuckets2 = theMap.NbBuckets();
1246 if(aData1 == aData2)
1247 return Standard_True;
1249 Standard_Integer i = 0;
1250 // Iteration of this map.
1251 for (; i <= NbBuckets(); i++) {
1252 const TColStd_intMapNode * p1 = aData1[i];
1254 // Find aKey - the base address of currently iterated block of integers
1255 const Standard_Integer aKey = p1->Key();
1256 const Standard_Integer aKeyInt = (unsigned)aKey >> 5;
1257 TColStd_intMapNode* pNext =
1258 reinterpret_cast <TColStd_intMapNode*> (p1->Next());
1259 // Find the corresponding block in the 2nd map
1260 const TColStd_intMapNode * p2 =
1261 aData2 [HashCode (aKeyInt, nBuckets2)];
1263 if (p2->IsEqual(aKeyInt)) {
1264 if ( p1->Data() & p2->Data() )
1265 return Standard_True;
1268 p2 = reinterpret_cast <const TColStd_intMapNode*> (p2->Next());
1273 return Standard_False;