diff --git a/src/ApplicationFramework/TKBinL/BinMDataStd/BinMDataStd_IntPackedMapDriver.cxx b/src/ApplicationFramework/TKBinL/BinMDataStd/BinMDataStd_IntPackedMapDriver.cxx index 2bf85a7c65..826be6a193 100644 --- a/src/ApplicationFramework/TKBinL/BinMDataStd/BinMDataStd_IntPackedMapDriver.cxx +++ b/src/ApplicationFramework/TKBinL/BinMDataStd/BinMDataStd_IntPackedMapDriver.cxx @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -120,7 +119,7 @@ void BinMDataStd_IntPackedMapDriver::Paste( Target << aSize; if (aSize) { - TColStd_MapIteratorOfPackedMapOfInteger anIt(anAtt->GetMap()); + TColStd_PackedMapOfInteger::Iterator anIt(anAtt->GetMap()); for (; anIt.More(); anIt.Next()) Target << anIt.Key(); } diff --git a/src/ApplicationFramework/TKLCAF/TDataStd/TDataStd_DeltaOnModificationOfIntPackedMap.cxx b/src/ApplicationFramework/TKLCAF/TDataStd/TDataStd_DeltaOnModificationOfIntPackedMap.cxx index 582a47454e..971cb0800e 100644 --- a/src/ApplicationFramework/TKLCAF/TDataStd/TDataStd_DeltaOnModificationOfIntPackedMap.cxx +++ b/src/ApplicationFramework/TKLCAF/TDataStd/TDataStd_DeltaOnModificationOfIntPackedMap.cxx @@ -131,7 +131,7 @@ void TDataStd_DeltaOnModificationOfIntPackedMap::Apply() #ifdef OCCT_DEBUG_disable std::cout << " << Map Dump after Delta Apply >>" << std::endl; occ::handle aIntMap = aCurAtt->GetHMap(); - TColStd_MapIteratorOfPackedMapOfInteger it(aIntMap->Map()); + TColStd_PackedMapOfInteger::Iterator it(aIntMap->Map()); for (int i = 1; it.More() && i <= MAXUP; it.Next(), i++) std::cout << it.Key() << " "; std::cout << std::endl; diff --git a/src/ApplicationFramework/TKXmlL/XmlMDataStd/XmlMDataStd_IntPackedMapDriver.cxx b/src/ApplicationFramework/TKXmlL/XmlMDataStd/XmlMDataStd_IntPackedMapDriver.cxx index 79e23c8831..0abc259ce0 100644 --- a/src/ApplicationFramework/TKXmlL/XmlMDataStd/XmlMDataStd_IntPackedMapDriver.cxx +++ b/src/ApplicationFramework/TKXmlL/XmlMDataStd/XmlMDataStd_IntPackedMapDriver.cxx @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -160,7 +159,7 @@ void XmlMDataStd_IntPackedMapDriver::Paste(const occ::handle& the int iChar = 0; NCollection_LocalArray str(12 * aSize + 1); - TColStd_MapIteratorOfPackedMapOfInteger anIt(aS->GetMap()); + TColStd_PackedMapOfInteger::Iterator anIt(aS->GetMap()); for (; anIt.More(); anIt.Next()) { const int intValue = anIt.Key(); diff --git a/src/DataExchange/TKXCAF/XCAFDoc/XCAFDoc_AssemblyGraph.cxx b/src/DataExchange/TKXCAF/XCAFDoc/XCAFDoc_AssemblyGraph.cxx index 25d89e1f83..1102664250 100644 --- a/src/DataExchange/TKXCAF/XCAFDoc/XCAFDoc_AssemblyGraph.cxx +++ b/src/DataExchange/TKXCAF/XCAFDoc/XCAFDoc_AssemblyGraph.cxx @@ -13,7 +13,7 @@ // commercial license or contractual agreement. #include -#include +#include #include #include #include diff --git a/src/Draw/TKDCAF/DDataStd/DDataStd_BasicCommands.cxx b/src/Draw/TKDCAF/DDataStd/DDataStd_BasicCommands.cxx index 31fdaae1ea..3471bfd419 100644 --- a/src/Draw/TKDCAF/DDataStd/DDataStd_BasicCommands.cxx +++ b/src/Draw/TKDCAF/DDataStd/DDataStd_BasicCommands.cxx @@ -63,7 +63,6 @@ #include #include #include -#include #include #include #include @@ -3088,8 +3087,8 @@ static int DDataStd_GetIntPackedMap(Draw_Interpretor& di, int nb, const char** a return 1; } // - const TColStd_PackedMapOfInteger& aMap = anAtt->GetMap(); - TColStd_MapIteratorOfPackedMapOfInteger itr(aMap); + const TColStd_PackedMapOfInteger& aMap = anAtt->GetMap(); + TColStd_PackedMapOfInteger::Iterator itr(aMap); for (int j = 1; itr.More(); itr.Next(), j++) { int aKey(itr.Key()); diff --git a/src/Draw/TKXDEDRAW/XDEDRAW/XDEDRAW.cxx b/src/Draw/TKXDEDRAW/XDEDRAW/XDEDRAW.cxx index ded9175610..d7a9755d8b 100644 --- a/src/Draw/TKXDEDRAW/XDEDRAW/XDEDRAW.cxx +++ b/src/Draw/TKXDEDRAW/XDEDRAW/XDEDRAW.cxx @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -1606,7 +1606,7 @@ static int XDumpAssemblyGraph(Draw_Interpretor& di, int argc, const char** argv) const TColStd_PackedMapOfInteger* aLinksPtr = anAdjacencyMap.Seek(theNode); if (aLinksPtr != nullptr) { - for (TColStd_MapIteratorOfPackedMapOfInteger anIt1(*aLinksPtr); anIt1.More(); anIt1.Next()) + for (TColStd_PackedMapOfInteger::Iterator anIt1(*aLinksPtr); anIt1.More(); anIt1.Next()) { aSS << " " << anIt1.Key(); } diff --git a/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.cxx b/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.cxx index 35b4a71aa0..a2bddb2c60 100644 --- a/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.cxx +++ b/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.cxx @@ -195,7 +195,7 @@ int Poly_MakeLoops::Perform() if (aPassNum == 0) { // move hanging links to start indices to make the second pass - TColStd_MapIteratorOfPackedMapOfInteger it(myHangIndices); + TColStd_PackedMapOfInteger::Iterator it(myHangIndices); for (; it.More(); it.Next()) myStartIndices.Add(it.Key()); } @@ -479,8 +479,8 @@ void Poly_MakeLoops::showBoundaryBreaks() const } // check each node if the number of input and output links are equal - bool isFirst = true; - TColStd_MapIteratorOfPackedMapOfInteger it(aNodesMap); + bool isFirst = true; + TColStd_PackedMapOfInteger::Iterator it(aNodesMap); for (; it.More(); it.Next()) { int aNode = it.Key(); @@ -534,7 +534,7 @@ void Poly_MakeLoops::showBoundaryBreaks() const void Poly_MakeLoops::GetHangingLinks(ListOfLink& theLinks) const { - TColStd_MapIteratorOfPackedMapOfInteger it(myHangIndices); + TColStd_PackedMapOfInteger::Iterator it(myHangIndices); for (; it.More(); it.Next()) { int aIndexS = it.Key(); diff --git a/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.hxx b/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.hxx index 4b30f35f62..3ce0feb1e6 100644 --- a/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.hxx +++ b/src/FoundationClasses/TKMath/Poly/Poly_MakeLoops.hxx @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -165,9 +165,9 @@ public: } private: - TColStd_PackedMapOfInteger myMap; - TColStd_MapIteratorOfPackedMapOfInteger myIter; - bool myIterReady; + TColStd_PackedMapOfInteger myMap; + TColStd_PackedMapOfInteger::Iterator myIter; + bool myIterReady; }; public: diff --git a/src/FoundationClasses/TKernel/GTests/FILES.cmake b/src/FoundationClasses/TKernel/GTests/FILES.cmake index 7dc2a02f43..68b9577415 100644 --- a/src/FoundationClasses/TKernel/GTests/FILES.cmake +++ b/src/FoundationClasses/TKernel/GTests/FILES.cmake @@ -18,6 +18,7 @@ set(OCCT_TKernel_GTests_FILES NCollection_LocalArray_Test.cxx NCollection_Map_Test.cxx NCollection_OccAllocator_Test.cxx + NCollection_PackedMap_Test.cxx NCollection_Sequence_Test.cxx NCollection_SparseArray_Test.cxx NCollection_Vec4_Test.cxx diff --git a/src/FoundationClasses/TKernel/GTests/NCollection_PackedMap_Test.cxx b/src/FoundationClasses/TKernel/GTests/NCollection_PackedMap_Test.cxx new file mode 100644 index 0000000000..745b5744cd --- /dev/null +++ b/src/FoundationClasses/TKernel/GTests/NCollection_PackedMap_Test.cxx @@ -0,0 +1,1044 @@ +// Copyright (c) 2025 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include + +#include +#include + +//================================================================================================== +// Type-parameterized tests for NCollection_PackedMap +//================================================================================================== + +template +class NCollection_PackedMapTypedTest : public testing::Test +{ +protected: + using MapType = NCollection_PackedMap; +}; + +using TestedTypes = ::testing::Types; + +TYPED_TEST_SUITE(NCollection_PackedMapTypedTest, TestedTypes); + +//================================================================================================== +// Basic Construction Tests +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, DefaultConstructor) +{ + typename TestFixture::MapType aMap; + EXPECT_TRUE(aMap.IsEmpty()); + EXPECT_EQ(aMap.Extent(), 0); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, ConstructorWithBuckets) +{ + typename TestFixture::MapType aMap(100); + EXPECT_TRUE(aMap.IsEmpty()); + EXPECT_EQ(aMap.Extent(), 0); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, CopyConstructor) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(10)); + aMap1.Add(TypeParam(100)); + + typename TestFixture::MapType aMap2(aMap1); + + EXPECT_EQ(aMap2.Extent(), 3); + EXPECT_TRUE(aMap2.Contains(TypeParam(1))); + EXPECT_TRUE(aMap2.Contains(TypeParam(10))); + EXPECT_TRUE(aMap2.Contains(TypeParam(100))); + + // Ensure deep copy + aMap1.Add(TypeParam(1000)); + EXPECT_EQ(aMap1.Extent(), 4); + EXPECT_EQ(aMap2.Extent(), 3); + EXPECT_FALSE(aMap2.Contains(TypeParam(1000))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, MoveConstructor) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(10)); + aMap1.Add(TypeParam(100)); + + typename TestFixture::MapType aMap2(std::move(aMap1)); + + EXPECT_EQ(aMap2.Extent(), 3); + EXPECT_TRUE(aMap2.Contains(TypeParam(1))); + EXPECT_TRUE(aMap2.Contains(TypeParam(10))); + EXPECT_TRUE(aMap2.Contains(TypeParam(100))); + EXPECT_TRUE(aMap1.IsEmpty()); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, CopyAssignment) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(5)); + aMap1.Add(TypeParam(15)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(100)); + aMap2.Add(TypeParam(200)); + + aMap2 = aMap1; + + EXPECT_EQ(aMap2.Extent(), 2); + EXPECT_TRUE(aMap2.Contains(TypeParam(5))); + EXPECT_TRUE(aMap2.Contains(TypeParam(15))); + EXPECT_FALSE(aMap2.Contains(TypeParam(100))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, MoveAssignment) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(5)); + aMap1.Add(TypeParam(15)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(100)); + + aMap2 = std::move(aMap1); + + EXPECT_EQ(aMap2.Extent(), 2); + EXPECT_TRUE(aMap2.Contains(TypeParam(5))); + EXPECT_TRUE(aMap2.Contains(TypeParam(15))); + EXPECT_TRUE(aMap1.IsEmpty()); +} + +//================================================================================================== +// Basic Operations Tests +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, AddAndContains) +{ + typename TestFixture::MapType aMap; + + EXPECT_TRUE(aMap.Add(TypeParam(10))); + EXPECT_TRUE(aMap.Add(TypeParam(20))); + EXPECT_TRUE(aMap.Add(TypeParam(30))); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(TypeParam(10))); + EXPECT_TRUE(aMap.Contains(TypeParam(20))); + EXPECT_TRUE(aMap.Contains(TypeParam(30))); + EXPECT_FALSE(aMap.Contains(TypeParam(40))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, AddDuplicate) +{ + typename TestFixture::MapType aMap; + + EXPECT_TRUE(aMap.Add(TypeParam(10))); + EXPECT_EQ(aMap.Extent(), 1); + + EXPECT_FALSE(aMap.Add(TypeParam(10))); + EXPECT_EQ(aMap.Extent(), 1); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, Remove) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(10)); + aMap.Add(TypeParam(20)); + aMap.Add(TypeParam(30)); + + EXPECT_EQ(aMap.Extent(), 3); + + EXPECT_TRUE(aMap.Remove(TypeParam(20))); + EXPECT_EQ(aMap.Extent(), 2); + EXPECT_FALSE(aMap.Contains(TypeParam(20))); + + EXPECT_FALSE(aMap.Remove(TypeParam(20))); + EXPECT_FALSE(aMap.Remove(TypeParam(40))); + EXPECT_EQ(aMap.Extent(), 2); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, Clear) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + aMap.Add(TypeParam(3)); + + EXPECT_EQ(aMap.Extent(), 3); + + aMap.Clear(); + + EXPECT_TRUE(aMap.IsEmpty()); + EXPECT_EQ(aMap.Extent(), 0); + + aMap.Add(TypeParam(100)); + EXPECT_EQ(aMap.Extent(), 1); + EXPECT_TRUE(aMap.Contains(TypeParam(100))); +} + +//================================================================================================== +// Edge Cases and Special Values +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, ZeroValue) +{ + typename TestFixture::MapType aMap; + + EXPECT_TRUE(aMap.Add(TypeParam(0))); + EXPECT_TRUE(aMap.Contains(TypeParam(0))); + EXPECT_EQ(aMap.Extent(), 1); + + EXPECT_TRUE(aMap.Remove(TypeParam(0))); + EXPECT_FALSE(aMap.Contains(TypeParam(0))); + EXPECT_TRUE(aMap.IsEmpty()); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, ConsecutiveValues) +{ + typename TestFixture::MapType aMap; + constexpr int aNbValues = 64; + + for (int i = 0; i < aNbValues; ++i) + { + aMap.Add(static_cast(i)); + } + + EXPECT_EQ(aMap.Extent(), aNbValues); + + for (int i = 0; i < aNbValues; ++i) + { + EXPECT_TRUE(aMap.Contains(static_cast(i))); + } +} + +TYPED_TEST(NCollection_PackedMapTypedTest, SparseValues) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(0)); + aMap.Add(TypeParam(100)); + aMap.Add(TypeParam(1000)); + aMap.Add(TypeParam(10000)); + aMap.Add(TypeParam(100000)); + + EXPECT_EQ(aMap.Extent(), 5); + + EXPECT_TRUE(aMap.Contains(TypeParam(0))); + EXPECT_TRUE(aMap.Contains(TypeParam(100))); + EXPECT_TRUE(aMap.Contains(TypeParam(1000))); + EXPECT_TRUE(aMap.Contains(TypeParam(10000))); + EXPECT_TRUE(aMap.Contains(TypeParam(100000))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, BlockBoundary) +{ + // Test values around block boundaries (31, 32, 33 for 32-bit, 63, 64, 65 for 64-bit) + typename TestFixture::MapType aMap; + constexpr int aBitsPerBlock = NCollection_PackedMap::BitsPerBlock; + + aMap.Add(static_cast(aBitsPerBlock - 1)); + aMap.Add(static_cast(aBitsPerBlock)); + aMap.Add(static_cast(aBitsPerBlock + 1)); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(static_cast(aBitsPerBlock - 1))); + EXPECT_TRUE(aMap.Contains(static_cast(aBitsPerBlock))); + EXPECT_TRUE(aMap.Contains(static_cast(aBitsPerBlock + 1))); +} + +//================================================================================================== +// Min/Max Queries +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, GetMinimalMapped) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(50)); + aMap.Add(TypeParam(10)); + aMap.Add(TypeParam(100)); + aMap.Add(TypeParam(5)); + aMap.Add(TypeParam(75)); + + EXPECT_EQ(aMap.GetMinimalMapped(), TypeParam(5)); + + aMap.Remove(TypeParam(5)); + EXPECT_EQ(aMap.GetMinimalMapped(), TypeParam(10)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, GetMaximalMapped) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(50)); + aMap.Add(TypeParam(10)); + aMap.Add(TypeParam(100)); + aMap.Add(TypeParam(5)); + aMap.Add(TypeParam(75)); + + EXPECT_EQ(aMap.GetMaximalMapped(), TypeParam(100)); + + aMap.Remove(TypeParam(100)); + EXPECT_EQ(aMap.GetMaximalMapped(), TypeParam(75)); +} + +//================================================================================================== +// Boolean Operations - Union +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, Union) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + aMap2.Add(TypeParam(5)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Union(aResult, aMap1, aMap2); + + EXPECT_EQ(aResult.Extent(), 5); + EXPECT_TRUE(aResult.Contains(TypeParam(1))); + EXPECT_TRUE(aResult.Contains(TypeParam(2))); + EXPECT_TRUE(aResult.Contains(TypeParam(3))); + EXPECT_TRUE(aResult.Contains(TypeParam(4))); + EXPECT_TRUE(aResult.Contains(TypeParam(5))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, Unite) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + aMap2.Add(TypeParam(5)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::Unite(aMap1, aMap2)); + + EXPECT_EQ(aMap1.Extent(), 5); + EXPECT_TRUE(aMap1.Contains(TypeParam(1))); + EXPECT_TRUE(aMap1.Contains(TypeParam(2))); + EXPECT_TRUE(aMap1.Contains(TypeParam(3))); + EXPECT_TRUE(aMap1.Contains(TypeParam(4))); + EXPECT_TRUE(aMap1.Contains(TypeParam(5))); + + EXPECT_FALSE(NCollection_PackedMapAlgo::Unite(aMap1, aMap2)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, UniteInPlace) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + + NCollection_PackedMapAlgo::Unite(aMap1, aMap2); + + EXPECT_EQ(aMap1.Extent(), 3); + EXPECT_TRUE(aMap1.Contains(TypeParam(1))); + EXPECT_TRUE(aMap1.Contains(TypeParam(2))); + EXPECT_TRUE(aMap1.Contains(TypeParam(3))); +} + +//================================================================================================== +// Boolean Operations - Intersection +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, Intersection) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + aMap1.Add(TypeParam(4)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(5)); + aMap2.Add(TypeParam(6)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Intersection(aResult, aMap1, aMap2); + + EXPECT_EQ(aResult.Extent(), 2); + EXPECT_TRUE(aResult.Contains(TypeParam(2))); + EXPECT_TRUE(aResult.Contains(TypeParam(3))); + EXPECT_FALSE(aResult.Contains(TypeParam(1))); + EXPECT_FALSE(aResult.Contains(TypeParam(4))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, Intersect) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + aMap1.Add(TypeParam(4)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(5)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::Intersect(aMap1, aMap2)); + + EXPECT_EQ(aMap1.Extent(), 2); + EXPECT_TRUE(aMap1.Contains(TypeParam(2))); + EXPECT_TRUE(aMap1.Contains(TypeParam(3))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IntersectInPlace) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + + NCollection_PackedMapAlgo::Intersect(aMap1, aMap2); + + EXPECT_EQ(aMap1.Extent(), 2); + EXPECT_TRUE(aMap1.Contains(TypeParam(2))); + EXPECT_TRUE(aMap1.Contains(TypeParam(3))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IntersectionDisjoint) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Intersection(aResult, aMap1, aMap2); + + EXPECT_TRUE(aResult.IsEmpty()); +} + +//================================================================================================== +// Boolean Operations - Subtraction +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, Subtraction) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + aMap1.Add(TypeParam(4)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(5)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Subtraction(aResult, aMap1, aMap2); + + EXPECT_EQ(aResult.Extent(), 2); + EXPECT_TRUE(aResult.Contains(TypeParam(1))); + EXPECT_TRUE(aResult.Contains(TypeParam(4))); + EXPECT_FALSE(aResult.Contains(TypeParam(2))); + EXPECT_FALSE(aResult.Contains(TypeParam(3))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, Subtract) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + aMap1.Add(TypeParam(4)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(5)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::Subtract(aMap1, aMap2)); + + EXPECT_EQ(aMap1.Extent(), 2); + EXPECT_TRUE(aMap1.Contains(TypeParam(1))); + EXPECT_TRUE(aMap1.Contains(TypeParam(4))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, SubtractInPlace) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + + NCollection_PackedMapAlgo::Subtract(aMap1, aMap2); + + EXPECT_EQ(aMap1.Extent(), 2); + EXPECT_TRUE(aMap1.Contains(TypeParam(1))); + EXPECT_TRUE(aMap1.Contains(TypeParam(3))); + EXPECT_FALSE(aMap1.Contains(TypeParam(2))); +} + +//================================================================================================== +// Boolean Operations - Difference (XOR) +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, Difference) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Difference(aResult, aMap1, aMap2); + + EXPECT_EQ(aResult.Extent(), 2); + EXPECT_TRUE(aResult.Contains(TypeParam(1))); + EXPECT_TRUE(aResult.Contains(TypeParam(4))); + EXPECT_FALSE(aResult.Contains(TypeParam(2))); + EXPECT_FALSE(aResult.Contains(TypeParam(3))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, Differ) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::Differ(aMap1, aMap2)); + + EXPECT_EQ(aMap1.Extent(), 2); + EXPECT_TRUE(aMap1.Contains(TypeParam(1))); + EXPECT_TRUE(aMap1.Contains(TypeParam(4))); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, DifferInPlace) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + + NCollection_PackedMapAlgo::Differ(aMap1, aMap2); + + EXPECT_EQ(aMap1.Extent(), 2); + EXPECT_TRUE(aMap1.Contains(TypeParam(1))); + EXPECT_TRUE(aMap1.Contains(TypeParam(3))); + EXPECT_FALSE(aMap1.Contains(TypeParam(2))); +} + +//================================================================================================== +// Comparison Operations +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, IsEqual) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(1)); + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsEqual(aMap1, aMap2)); + + aMap2.Add(TypeParam(4)); + EXPECT_FALSE(NCollection_PackedMapAlgo::IsEqual(aMap1, aMap2)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IsEqualEmpty) +{ + typename TestFixture::MapType aMap1; + typename TestFixture::MapType aMap2; + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsEqual(aMap1, aMap2)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IsSubset) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(1)); + aMap2.Add(TypeParam(2)); + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsSubset(aMap1, aMap2)); + EXPECT_FALSE(NCollection_PackedMapAlgo::IsSubset(aMap2, aMap1)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IsSubsetSame) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(1)); + aMap2.Add(TypeParam(2)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsSubset(aMap1, aMap2)); + EXPECT_TRUE(NCollection_PackedMapAlgo::IsSubset(aMap2, aMap1)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IsSubsetEmpty) +{ + typename TestFixture::MapType aEmptyMap; + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsSubset(aEmptyMap, aMap)); + EXPECT_TRUE(NCollection_PackedMapAlgo::IsSubset(aEmptyMap, aEmptyMap)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, HasIntersection) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + aMap1.Add(TypeParam(3)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(3)); + aMap2.Add(TypeParam(4)); + aMap2.Add(TypeParam(5)); + + EXPECT_TRUE(NCollection_PackedMapAlgo::HasIntersection(aMap1, aMap2)); + + typename TestFixture::MapType aMap3; + aMap3.Add(TypeParam(10)); + aMap3.Add(TypeParam(20)); + + EXPECT_FALSE(NCollection_PackedMapAlgo::HasIntersection(aMap1, aMap3)); +} + +//================================================================================================== +// Iterator Tests +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, IteratorBasic) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(10)); + aMap.Add(TypeParam(20)); + aMap.Add(TypeParam(30)); + + std::vector aValues; + for (typename TestFixture::MapType::Iterator anIt(aMap); anIt.More(); anIt.Next()) + { + aValues.push_back(anIt.Key()); + } + + EXPECT_EQ(aValues.size(), 3); + EXPECT_NE(std::find(aValues.begin(), aValues.end(), TypeParam(10)), aValues.end()); + EXPECT_NE(std::find(aValues.begin(), aValues.end(), TypeParam(20)), aValues.end()); + EXPECT_NE(std::find(aValues.begin(), aValues.end(), TypeParam(30)), aValues.end()); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IteratorEmpty) +{ + typename TestFixture::MapType aMap; + + int aCount = 0; + for (typename TestFixture::MapType::Iterator anIt(aMap); anIt.More(); anIt.Next()) + { + ++aCount; + } + + EXPECT_EQ(aCount, 0); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IteratorReinitialize) +{ + typename TestFixture::MapType aMap1; + aMap1.Add(TypeParam(1)); + aMap1.Add(TypeParam(2)); + + typename TestFixture::MapType aMap2; + aMap2.Add(TypeParam(100)); + aMap2.Add(TypeParam(200)); + aMap2.Add(TypeParam(300)); + + typename TestFixture::MapType::Iterator anIt(aMap1); + + int aCount1 = 0; + for (; anIt.More(); anIt.Next()) + { + ++aCount1; + } + EXPECT_EQ(aCount1, 2); + + anIt.Initialize(aMap2); + + int aCount2 = 0; + for (; anIt.More(); anIt.Next()) + { + ++aCount2; + } + EXPECT_EQ(aCount2, 3); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IteratorReset) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + + typename TestFixture::MapType::Iterator anIt(aMap); + + int aCount1 = 0; + for (; anIt.More(); anIt.Next()) + { + ++aCount1; + } + EXPECT_EQ(aCount1, 2); + + anIt.Reset(); + + int aCount2 = 0; + for (; anIt.More(); anIt.Next()) + { + ++aCount2; + } + EXPECT_EQ(aCount2, 2); +} + +//================================================================================================== +// Resize and Performance Tests +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, ReSize) +{ + typename TestFixture::MapType aMap(1); + + for (int i = 0; i < 1000; ++i) + { + aMap.Add(static_cast(i)); + } + + EXPECT_EQ(aMap.Extent(), 1000); + + for (int i = 0; i < 1000; ++i) + { + EXPECT_TRUE(aMap.Contains(static_cast(i))); + } +} + +TYPED_TEST(NCollection_PackedMapTypedTest, LargeValues) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(1000000)); + aMap.Add(TypeParam(2000000)); + aMap.Add(TypeParam(3000000)); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(TypeParam(1000000))); + EXPECT_TRUE(aMap.Contains(TypeParam(2000000))); + EXPECT_TRUE(aMap.Contains(TypeParam(3000000))); +} + +//================================================================================================== +// Self-Operations Tests +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, UnionWithSelf) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + aMap.Add(TypeParam(3)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Union(aResult, aMap, aMap); + + EXPECT_EQ(aResult.Extent(), 3); + EXPECT_TRUE(NCollection_PackedMapAlgo::IsEqual(aResult, aMap)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IntersectionWithSelf) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + aMap.Add(TypeParam(3)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Intersection(aResult, aMap, aMap); + + EXPECT_EQ(aResult.Extent(), 3); + EXPECT_TRUE(NCollection_PackedMapAlgo::IsEqual(aResult, aMap)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, SubtractionFromSelf) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + aMap.Add(TypeParam(3)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Subtraction(aResult, aMap, aMap); + + EXPECT_TRUE(aResult.IsEmpty()); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, DifferenceWithSelf) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + aMap.Add(TypeParam(3)); + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Difference(aResult, aMap, aMap); + + EXPECT_TRUE(aResult.IsEmpty()); +} + +//================================================================================================== +// Empty Map Operations +//================================================================================================== + +TYPED_TEST(NCollection_PackedMapTypedTest, UnionWithEmpty) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + + typename TestFixture::MapType aEmpty; + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Union(aResult, aMap, aEmpty); + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsEqual(aResult, aMap)); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, IntersectionWithEmpty) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + + typename TestFixture::MapType aEmpty; + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Intersection(aResult, aMap, aEmpty); + + EXPECT_TRUE(aResult.IsEmpty()); +} + +TYPED_TEST(NCollection_PackedMapTypedTest, SubtractionEmpty) +{ + typename TestFixture::MapType aMap; + aMap.Add(TypeParam(1)); + aMap.Add(TypeParam(2)); + + typename TestFixture::MapType aEmpty; + + typename TestFixture::MapType aResult; + NCollection_PackedMapAlgo::Subtraction(aResult, aMap, aEmpty); + + EXPECT_TRUE(NCollection_PackedMapAlgo::IsEqual(aResult, aMap)); + + typename TestFixture::MapType aResult2; + NCollection_PackedMapAlgo::Subtraction(aResult2, aEmpty, aMap); + + EXPECT_TRUE(aResult2.IsEmpty()); +} + +//================================================================================================== +// Signed Integer Specific Tests (only run for signed types) +//================================================================================================== + +template +class NCollection_PackedMapSignedTest : public testing::Test +{ +protected: + using MapType = NCollection_PackedMap; +}; + +using SignedTypes = ::testing::Types; + +TYPED_TEST_SUITE(NCollection_PackedMapSignedTest, SignedTypes); + +TYPED_TEST(NCollection_PackedMapSignedTest, NegativeValues) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(-1)); + aMap.Add(TypeParam(-100)); + aMap.Add(TypeParam(-1000)); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(TypeParam(-1))); + EXPECT_TRUE(aMap.Contains(TypeParam(-100))); + EXPECT_TRUE(aMap.Contains(TypeParam(-1000))); + EXPECT_FALSE(aMap.Contains(TypeParam(1))); + + EXPECT_TRUE(aMap.Remove(TypeParam(-100))); + EXPECT_EQ(aMap.Extent(), 2); + EXPECT_FALSE(aMap.Contains(TypeParam(-100))); +} + +TYPED_TEST(NCollection_PackedMapSignedTest, MixedPositiveNegative) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(-50)); + aMap.Add(TypeParam(0)); + aMap.Add(TypeParam(50)); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(TypeParam(-50))); + EXPECT_TRUE(aMap.Contains(TypeParam(0))); + EXPECT_TRUE(aMap.Contains(TypeParam(50))); +} + +TYPED_TEST(NCollection_PackedMapSignedTest, MinMaxWithNegatives) +{ + typename TestFixture::MapType aMap; + + aMap.Add(TypeParam(-100)); + aMap.Add(TypeParam(-50)); + aMap.Add(TypeParam(0)); + aMap.Add(TypeParam(50)); + aMap.Add(TypeParam(100)); + + EXPECT_EQ(aMap.GetMinimalMapped(), TypeParam(-100)); + EXPECT_EQ(aMap.GetMaximalMapped(), TypeParam(100)); +} + +//================================================================================================== +// 64-bit Type Specific Tests +//================================================================================================== + +TEST(NCollection_PackedMap64BitTest, LargeValues64Bit) +{ + NCollection_PackedMap aMap; + + // Values that require 64-bit storage + constexpr int64_t aLargeVal1 = 1LL << 40; + constexpr int64_t aLargeVal2 = 1LL << 50; + constexpr int64_t aLargeVal3 = 1LL << 60; + + aMap.Add(aLargeVal1); + aMap.Add(aLargeVal2); + aMap.Add(aLargeVal3); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(aLargeVal1)); + EXPECT_TRUE(aMap.Contains(aLargeVal2)); + EXPECT_TRUE(aMap.Contains(aLargeVal3)); + + EXPECT_EQ(aMap.GetMinimalMapped(), aLargeVal1); + EXPECT_EQ(aMap.GetMaximalMapped(), aLargeVal3); +} + +TEST(NCollection_PackedMap64BitTest, Negative64BitValues) +{ + NCollection_PackedMap aMap; + + constexpr int64_t aNegVal1 = -(1LL << 40); + constexpr int64_t aNegVal2 = -(1LL << 50); + + aMap.Add(aNegVal1); + aMap.Add(aNegVal2); + aMap.Add(int64_t(0)); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(aNegVal1)); + EXPECT_TRUE(aMap.Contains(aNegVal2)); + EXPECT_TRUE(aMap.Contains(int64_t(0))); +} + +TEST(NCollection_PackedMap64BitTest, SizeTypeValues) +{ + NCollection_PackedMap aMap; + + aMap.Add(size_t(0)); + aMap.Add(size_t(1) << 32); + aMap.Add(std::numeric_limits::max() / 2); + + EXPECT_EQ(aMap.Extent(), 3); + EXPECT_TRUE(aMap.Contains(size_t(0))); + EXPECT_TRUE(aMap.Contains(size_t(1) << 32)); + EXPECT_TRUE(aMap.Contains(std::numeric_limits::max() / 2)); +} + +//================================================================================================== +// Type Configuration Verification Tests +//================================================================================================== + +TEST(NCollection_PackedMapConfigTest, ConfigFor32BitTypes) +{ + EXPECT_FALSE(NCollection_PackedMap::Is64Bit); + EXPECT_FALSE(NCollection_PackedMap::Is64Bit); + EXPECT_EQ(NCollection_PackedMap::BitsPerBlock, 32); + EXPECT_EQ(NCollection_PackedMap::BitsPerBlock, 32); +} + +TEST(NCollection_PackedMapConfigTest, ConfigFor64BitTypes) +{ + EXPECT_TRUE(NCollection_PackedMap::Is64Bit); + EXPECT_TRUE(NCollection_PackedMap::Is64Bit); + EXPECT_TRUE(NCollection_PackedMap::Is64Bit); + EXPECT_EQ(NCollection_PackedMap::BitsPerBlock, 64); + EXPECT_EQ(NCollection_PackedMap::BitsPerBlock, 64); +} diff --git a/src/FoundationClasses/TKernel/Message/Message_Algorithm.cxx b/src/FoundationClasses/TKernel/Message/Message_Algorithm.cxx index 38ad6e579a..11fae04592 100644 --- a/src/FoundationClasses/TKernel/Message/Message_Algorithm.cxx +++ b/src/FoundationClasses/TKernel/Message/Message_Algorithm.cxx @@ -26,9 +26,10 @@ #include #include #include +#include #include #include -#include +#include IMPLEMENT_STANDARD_RTTIEXT(Message_Algorithm, Standard_Transient) @@ -299,7 +300,9 @@ void Message_Algorithm::AddStatus(const Message_ExecStatus& theAllow aData = new TColStd_HPackedMapOfInteger; // add integer parameter for the status - occ::down_cast(aData)->ChangeMap().Unite(aNumsOther->Map()); + NCollection_PackedMapAlgo::Unite( + occ::down_cast(aData)->ChangeMap(), + aNumsOther->Map()); } // b) strings occ::handle>> aStrsOther = @@ -351,9 +354,9 @@ TCollection_ExtendedString Message_Algorithm::PrepareReport( const occ::handle& theMapError, const int theMaxCount) { - TCollection_ExtendedString aNewReport; - TColStd_MapIteratorOfPackedMapOfInteger anIt(theMapError->Map()); - int nb = 1; + TCollection_ExtendedString aNewReport; + TColStd_PackedMapOfInteger::Iterator anIt(theMapError->Map()); + int nb = 1; for (; anIt.More() && nb <= theMaxCount; anIt.Next(), nb++) { if (nb > 1) diff --git a/src/FoundationClasses/TKernel/NCollection/FILES.cmake b/src/FoundationClasses/TKernel/NCollection/FILES.cmake index cc40518bb8..665f470353 100644 --- a/src/FoundationClasses/TKernel/NCollection/FILES.cmake +++ b/src/FoundationClasses/TKernel/NCollection/FILES.cmake @@ -53,6 +53,8 @@ set(OCCT_NCollection_FILES NCollection_Mat3.hxx NCollection_Mat4.hxx NCollection_OccAllocator.hxx + NCollection_PackedMap.hxx + NCollection_PackedMapAlgo.hxx NCollection_Primes.cxx NCollection_Primes.hxx NCollection_Sequence.hxx diff --git a/src/FoundationClasses/TKernel/NCollection/NCollection_PackedMap.hxx b/src/FoundationClasses/TKernel/NCollection/NCollection_PackedMap.hxx new file mode 100644 index 0000000000..b67933ff9c --- /dev/null +++ b/src/FoundationClasses/TKernel/NCollection/NCollection_PackedMap.hxx @@ -0,0 +1,908 @@ +// Copyright (c) 2005-2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef NCollection_PackedMap_HeaderFile +#define NCollection_PackedMap_HeaderFile + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//! @brief Optimized Map for integer values of various integral types. +//! +//! This template class provides a memory-efficient storage for sets of integers. +//! Each block of BitsPerBlock (32 or 64) consecutive integers is stored compactly +//! using bit manipulation. The block size is automatically selected based on +//! the integer type: 32 bits for int/unsigned, 64 bits for int64_t/size_t. +//! +//! @tparam IntType The integral type to store (int, unsigned int, int64_t, size_t, etc.) +template +class NCollection_PackedMap +{ + static_assert(std::is_integral::value, + "NCollection_PackedMap requires an integral type"); + +public: + DEFINE_STANDARD_ALLOC + + //! True if the integer type is larger than 32 bits + static constexpr bool Is64Bit = sizeof(IntType) > 4; + + //! The block type for storing packed bits + using BlockType = typename std::conditional::type; + + //! The index type for addressing blocks + using IndexType = typename std::conditional::type; + + //! Number of bits per block + static constexpr int BitsPerBlock = Is64Bit ? 64 : 32; + +private: + //! Number of low bits used for position within a block + static constexpr int MaskLowBits = Is64Bit ? 6 : 5; + + //! Mask for low bits (position within block) + static constexpr IndexType MASK_LOW = (IndexType(1) << MaskLowBits) - 1; + + //! Mask for high bits (block base address) + static constexpr IndexType MASK_HIGH = ~MASK_LOW; + + //! @brief Class implementing a block of consecutive integer values as a node. + //! + //! For 32-bit types: stores 32 consecutive values + //! For 64-bit types: stores 64 consecutive values + //! + //! The data are stored as: + //! - myMask: contains the count-1 in low bits and block base address in high bits + //! - myData: bit field where each bit indicates presence of corresponding integer + class PackedMapNode + { + public: + PackedMapNode(PackedMapNode* thePtr = nullptr) + : myNext(thePtr), + myMask(0), + myData(0) + { + } + + PackedMapNode(IntType theValue, PackedMapNode*& thePtr) + : myNext(thePtr), + myMask(static_cast(theValue) & MASK_HIGH), + myData(BlockType(1) << (static_cast(theValue) & MASK_LOW)) + { + } + + PackedMapNode(IndexType theMask, BlockType theData, PackedMapNode* thePtr) + : myNext(thePtr), + myMask(theMask), + myData(theData) + { + } + + IndexType Mask() const { return myMask; } + + BlockType Data() const { return myData; } + + IndexType& ChangeMask() { return myMask; } + + BlockType& ChangeData() { return myData; } + + //! Compute the sequential index of this packed node in the map. + IntType Key() const { return static_cast(myMask & MASK_HIGH); } + + //! Return the number of set integer keys. + size_t NbValues() const { return size_t(myMask & MASK_LOW) + 1; } + + //! Return TRUE if this packed node is not empty. + bool HasValues() const { return (myData != 0); } + + //! Return TRUE if the given integer key is set within this packed node. + bool HasValue(IntType theValue) const + { + return (myData & (BlockType(1) << (static_cast(theValue) & MASK_LOW))) != 0; + } + + //! Add integer key to this packed node. + //! @return TRUE if key has been added + bool AddValue(IntType theValue) + { + const BlockType aValBit = BlockType(1) << (static_cast(theValue) & MASK_LOW); + if ((myData & aValBit) == 0) + { + myData ^= aValBit; + ++myMask; + return true; + } + return false; + } + + //! Delete integer key from this packed node. + //! @return TRUE if key has been deleted + bool DelValue(IntType theValue) + { + const BlockType aValBit = BlockType(1) << (static_cast(theValue) & MASK_LOW); + if ((myData & aValBit) != 0) + { + myData ^= aValBit; + myMask--; + return true; + } + return false; + } + + //! Return the next node having the same hash code. + PackedMapNode* Next() const { return myNext; } + + //! Set the next node having the same hash code. + void SetNext(PackedMapNode* theNext) { myNext = theNext; } + + public: + //! Support of Map interface. + size_t HashCode(size_t theUpper) const + { + return static_cast(myMask >> MaskLowBits) % theUpper + 1; + } + + //! Support of Map interface. + bool IsEqual(IndexType theOther) const + { + return (myMask >> MaskLowBits) == (static_cast(theOther)); + } + + private: + PackedMapNode* myNext; + IndexType myMask; + BlockType myData; + }; + +public: + //! Iterator of class NCollection_PackedMap. + class Iterator + { + public: + //! Empty Constructor. + Iterator() + : myBuckets(nullptr), + myNode(nullptr), + myNbBuckets(-1), + myBucket(-1), + myIntMask(~BlockType(0)), + myKey(0) + { + } + + //! Constructor. + Iterator(const NCollection_PackedMap& theMap) + : myBuckets(theMap.myData1), + myNode(nullptr), + myNbBuckets(theMap.myData1 != nullptr ? theMap.myNbBuckets : -1), + myBucket(-1), + myIntMask(~BlockType(0)) + { + next(); + myKey = myNode != nullptr ? NCollection_PackedMap::findNext(myNode, myIntMask) : 0; + } + + //! Re-initialize with the same or another Map instance. + void Initialize(const NCollection_PackedMap& theMap) + { + myBuckets = theMap.myData1; + myBucket = -1; + myNode = nullptr; + myNbBuckets = theMap.myData1 != nullptr ? theMap.myNbBuckets : -1; + next(); + + myIntMask = ~BlockType(0); + myKey = myNode != nullptr ? findNext(myNode, myIntMask) : 0; + } + + //! Restart the iteration + void Reset() + { + myBucket = -1; + myNode = nullptr; + next(); + + myIntMask = ~BlockType(0); + myKey = myNode != nullptr ? findNext(myNode, myIntMask) : 0; + } + + //! Query the iterated key. + IntType Key() const + { + Standard_NoSuchObject_Raise_if((myIntMask == ~BlockType(0)), + "NCollection_PackedMap::Iterator::Key"); + return myKey; + } + + //! Return TRUE if iterator points to the node. + bool More() const { return myNode != nullptr; } + + //! Increment the iterator + void Next() + { + for (; myNode != nullptr; next()) + { + myKey = NCollection_PackedMap::findNext(myNode, myIntMask); + if (myIntMask != ~BlockType(0)) + { + break; + } + } + } + + private: + //! Go to the next bucket in the map. + void next() + { + if (myBuckets == nullptr) + { + return; + } + + if (myNode != nullptr) + { + myNode = myNode->Next(); + } + + while (myNode == nullptr) + { + ++myBucket; + if (myBucket > myNbBuckets) + { + return; + } + myNode = myBuckets[myBucket]; + } + } + + private: + PackedMapNode** myBuckets; + PackedMapNode* myNode; + int myNbBuckets; + int myBucket; + + BlockType myIntMask; //!< all bits set above the iterated position + IntType myKey; //!< Currently iterated key + }; + +public: + //! Constructor + NCollection_PackedMap(const int theNbBuckets = 1) + : myData1(nullptr), + myNbBuckets(theNbBuckets), + myNbPackedMapNodes(0), + myExtent(0) + { + } + + //! Copy constructor + NCollection_PackedMap(const NCollection_PackedMap& theOther) + : myData1(nullptr), + myNbBuckets(1), + myNbPackedMapNodes(0), + myExtent(0) + { + Assign(theOther); + } + + NCollection_PackedMap& operator=(const NCollection_PackedMap& theOther) + { + return Assign(theOther); + } + + //! Move constructor + NCollection_PackedMap(NCollection_PackedMap&& theOther) noexcept + : myData1(theOther.myData1), + myNbBuckets(theOther.myNbBuckets), + myNbPackedMapNodes(theOther.myNbPackedMapNodes), + myExtent(theOther.myExtent) + { + theOther.myData1 = nullptr; + theOther.myNbBuckets = 1; + theOther.myNbPackedMapNodes = 0; + theOther.myExtent = 0; + } + + //! Move assignment operator + NCollection_PackedMap& operator=(NCollection_PackedMap&& theOther) noexcept + { + if (this != &theOther) + { + Clear(); + myData1 = theOther.myData1; + myNbBuckets = theOther.myNbBuckets; + myNbPackedMapNodes = theOther.myNbPackedMapNodes; + myExtent = theOther.myExtent; + theOther.myData1 = nullptr; + theOther.myNbBuckets = 1; + theOther.myNbPackedMapNodes = 0; + theOther.myExtent = 0; + } + return *this; + } + + //! Assignment operator + NCollection_PackedMap& Assign(const NCollection_PackedMap& theOther) + { + if (this != &theOther) + { + Clear(); + if (!theOther.IsEmpty()) + { + ReSize(theOther.myNbPackedMapNodes); + const int nBucketsSrc = theOther.myNbBuckets; + const int nBuckets = myNbBuckets; + for (int i = 0; i <= nBucketsSrc; i++) + { + for (const PackedMapNode* p = theOther.myData1[i]; p != nullptr;) + { + const size_t aHashCode = p->HashCode(nBuckets); + myData1[aHashCode] = new PackedMapNode(p->Mask(), p->Data(), myData1[aHashCode]); + ++myNbPackedMapNodes; + p = p->Next(); + } + } + } + myExtent = theOther.myExtent; + } + return *this; + } + + //! Resize the map + void ReSize(const int theNbBuckets) + { + int aNewBuck = NCollection_Primes::NextPrimeForMap(theNbBuckets); + if (aNewBuck <= myNbBuckets) + { + if (!IsEmpty()) + { + return; + } + aNewBuck = myNbBuckets; + } + + PackedMapNode** aNewData = reinterpret_cast( + Standard::AllocateOptimal((aNewBuck + 1) * sizeof(PackedMapNode*))); + memset(aNewData, 0, (aNewBuck + 1) * sizeof(PackedMapNode*)); + if (myData1 != nullptr) + { + PackedMapNode** anOldData = myData1; + for (int i = 0; i <= myNbBuckets; ++i) + { + for (PackedMapNode* p = anOldData[i]; p != nullptr;) + { + size_t k = p->HashCode(aNewBuck); + PackedMapNode* q = p->Next(); + p->SetNext(aNewData[k]); + aNewData[k] = p; + p = q; + } + } + } + + Standard::Free(myData1); + myNbBuckets = aNewBuck; + myData1 = aNewData; + } + + //! Clear the map + void Clear() + { + if (!IsEmpty()) + { + for (int aBucketIter = 0; aBucketIter <= myNbBuckets; ++aBucketIter) + { + if (myData1[aBucketIter]) + { + for (PackedMapNode* aSubNodeIter = myData1[aBucketIter]; aSubNodeIter != nullptr;) + { + PackedMapNode* q = aSubNodeIter->Next(); + delete aSubNodeIter; + aSubNodeIter = q; + } + } + } + } + + myNbPackedMapNodes = 0; + Standard::Free(myData1); + myData1 = nullptr; + myExtent = 0; + } + + ~NCollection_PackedMap() { Clear(); } + + //! Add a key to the map + //! @param[in] theKey the key to add + //! @return true if the key was added, false if it already existed + bool Add(const IntType theKey) + { + if (Resizable()) + { + ReSize(myNbPackedMapNodes); + } + + const IndexType aKeyInt = packedKeyIndex(theKey); + const size_t aHashCode = hashCode(aKeyInt, myNbBuckets); + PackedMapNode* aBucketHead = myData1[aHashCode]; + for (PackedMapNode* p = aBucketHead; p != nullptr; p = p->Next()) + { + if (p->IsEqual(aKeyInt)) + { + if (p->AddValue(theKey)) + { + ++myExtent; + return true; + } + return false; + } + } + + myData1[aHashCode] = new PackedMapNode(theKey, aBucketHead); + ++myNbPackedMapNodes; + ++myExtent; + return true; + } + + //! Check if the map contains a key + //! @param[in] theKey the key to check + //! @return true if the key is in the map + bool Contains(const IntType theKey) const + { + if (IsEmpty()) + { + return false; + } + + const IndexType aKeyInt = packedKeyIndex(theKey); + for (PackedMapNode* p = myData1[hashCode(aKeyInt, myNbBuckets)]; p != nullptr;) + { + if (p->IsEqual(aKeyInt)) + { + return p->HasValue(theKey); + } + p = p->Next(); + } + return false; + } + + //! Remove a key from the map + //! @param[in] theKey the key to remove + //! @return true if the key was removed, false if it was not present + bool Remove(const IntType theKey) + { + if (IsEmpty()) + { + return false; + } + + const IndexType aKeyInt = packedKeyIndex(theKey); + PackedMapNode*& aBucketHead = myData1[hashCode(aKeyInt, myNbBuckets)]; + PackedMapNode* p = aBucketHead; + PackedMapNode* q = nullptr; + while (p) + { + if (p->IsEqual(aKeyInt)) + { + bool aResult = p->DelValue(theKey); + if (aResult) + { + --myExtent; + if (!p->HasValues()) + { + --myNbPackedMapNodes; + if (q != nullptr) + { + q->SetNext(p->Next()); + } + else + { + aBucketHead = p->Next(); + } + delete p; + } + } + return aResult; + } + q = p; + p = p->Next(); + } + return false; + } + + //! Returns the number of map buckets. + int NbBuckets() const { return myNbBuckets; } + + //! Returns map extent. + int Extent() const { return static_cast(myExtent); } + + //! Returns TRUE if map is empty. + bool IsEmpty() const { return myNbPackedMapNodes == 0; } + + //! Query the minimal contained key value. + IntType GetMinimalMapped() const + { + if (IsEmpty()) + { + return std::numeric_limits::max(); + } + + IntType aResult = std::numeric_limits::max(); + const PackedMapNode* pFoundNode = nullptr; + for (int i = 0; i <= myNbBuckets; i++) + { + for (const PackedMapNode* p = myData1[i]; p != nullptr; p = p->Next()) + { + const IntType aKey = p->Key(); + if (aResult > aKey) + { + aResult = aKey; + pFoundNode = p; + } + } + } + if (pFoundNode) + { + BlockType aFullMask = ~BlockType(0); + aResult = findNext(pFoundNode, aFullMask); + } + return aResult; + } + + //! Query the maximal contained key value. + IntType GetMaximalMapped() const + { + if (IsEmpty()) + { + return std::numeric_limits::lowest(); + } + + IntType aResult = std::numeric_limits::lowest(); + const PackedMapNode* pFoundNode = nullptr; + for (int i = 0; i <= myNbBuckets; i++) + { + for (const PackedMapNode* p = myData1[i]; p != nullptr; p = p->Next()) + { + const IntType aKey = p->Key(); + if (aResult < aKey) + { + aResult = aKey; + pFoundNode = p; + } + } + } + if (pFoundNode) + { + BlockType aFullMask = ~BlockType(0); + aResult = findPrev(pFoundNode, aFullMask); + } + return aResult; + } + +public: + //! @name Deprecated boolean operations (use NCollection_PackedMapAlgo instead) + + //! @deprecated Use NCollection_PackedMapAlgo::Union() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + void Union(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight); + + //! @deprecated Use NCollection_PackedMapAlgo::Unite() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool Unite(const NCollection_PackedMap& theOther); + + //! @deprecated Use NCollection_PackedMapAlgo::Intersection() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + void Intersection(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight); + + //! @deprecated Use NCollection_PackedMapAlgo::Intersect() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool Intersect(const NCollection_PackedMap& theOther); + + //! @deprecated Use NCollection_PackedMapAlgo::Subtraction() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + void Subtraction(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight); + + //! @deprecated Use NCollection_PackedMapAlgo::Subtract() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool Subtract(const NCollection_PackedMap& theOther); + + //! @deprecated Use NCollection_PackedMapAlgo::Difference() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + void Difference(const NCollection_PackedMap& theLeft, const NCollection_PackedMap& theRight); + + //! @deprecated Use NCollection_PackedMapAlgo::Differ() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool Differ(const NCollection_PackedMap& theOther); + + //! @deprecated Use NCollection_PackedMapAlgo::IsEqual() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool IsEqual(const NCollection_PackedMap& theOther) const; + + //! @deprecated Use NCollection_PackedMapAlgo::IsSubset() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool IsSubset(const NCollection_PackedMap& theOther) const; + + //! @deprecated Use NCollection_PackedMapAlgo::HasIntersection() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool HasIntersection(const NCollection_PackedMap& theOther) const; + + //! @deprecated Use NCollection_PackedMapAlgo::Contains() instead + Standard_DEPRECATED("This method will be removed after OCCT 7.9 release. Use methods from " + "NCollection_PackedMapAlgo.hxx instead.") + bool Contains(const NCollection_PackedMap& theOther) const; + +protected: + //! Returns TRUE if resizing the map should be considered. + bool Resizable() const { return IsEmpty() || (myNbPackedMapNodes > myNbBuckets); } + + //! Return an integer index for specified key. + static IndexType packedKeyIndex(IntType theKey) + { + return static_cast(theKey) >> MaskLowBits; + } + + //! Compute hash code for a key index. + static size_t hashCode(IndexType theKeyIndex, int theNbBuckets) + { + return static_cast(theKeyIndex) % theNbBuckets + 1; + } + + //! Compute the population (i.e., the number of non-zero bits) of the block. + //! The population is stored decremented as it is defined in PackedMapNode. + static size_t population(IndexType& theMask, BlockType theData) + { + if constexpr (Is64Bit) + { + // 64-bit population count + uint64_t aRes = theData - ((theData >> 1) & 0x5555555555555555ULL); + aRes = (aRes & 0x3333333333333333ULL) + ((aRes >> 2) & 0x3333333333333333ULL); + aRes = (aRes + (aRes >> 4)) & 0x0f0f0f0f0f0f0f0fULL; + aRes = aRes + (aRes >> 8); + aRes = aRes + (aRes >> 16); + aRes = aRes + (aRes >> 32); + theMask = (theMask & MASK_HIGH) | ((static_cast(aRes) - 1) & MASK_LOW); + return size_t(aRes & 0x7f); + } + else + { + // 32-bit population count + uint32_t aRes = + static_cast(theData) - ((static_cast(theData) >> 1) & 0x55555555); + aRes = (aRes & 0x33333333) + ((aRes >> 2) & 0x33333333); + aRes = (aRes + (aRes >> 4)) & 0x0f0f0f0f; + aRes = aRes + (aRes >> 8); + aRes = aRes + (aRes >> 16); + theMask = (theMask & MASK_HIGH) | ((aRes - 1) & MASK_LOW); + return size_t(aRes & 0x3f); + } + } + + //! Find the smallest non-zero bit under the given mask. + //! Outputs the new mask that does not contain the detected bit. + static IntType findNext(const PackedMapNode* theNode, BlockType& theMask) + { + BlockType val = theNode->Data() & theMask; + int nZeros = 0; + if (val == 0) + { + theMask = ~BlockType(0); // void, nothing to do + } + else + { + BlockType aMask = ~BlockType(0); + if constexpr (Is64Bit) + { + if ((val & 0x00000000ffffffffULL) == 0) + { + aMask = 0xffffffff00000000ULL; + nZeros = 32; + val >>= 32; + } + } + if ((val & 0x0000ffff) == 0) + { + aMask <<= 16; + nZeros += 16; + val >>= 16; + } + if ((val & 0x000000ff) == 0) + { + aMask <<= 8; + nZeros += 8; + val >>= 8; + } + if ((val & 0x0000000f) == 0) + { + aMask <<= 4; + nZeros += 4; + val >>= 4; + } + if ((val & 0x00000003) == 0) + { + aMask <<= 2; + nZeros += 2; + val >>= 2; + } + if ((val & 0x00000001) == 0) + { + aMask <<= 1; + nZeros++; + } + theMask = (aMask << 1); + } + return static_cast(nZeros) + theNode->Key(); + } + + //! Find the highest non-zero bit under the given mask. + //! Outputs the new mask that does not contain the detected bit. + static IntType findPrev(const PackedMapNode* theNode, BlockType& theMask) + { + BlockType val = theNode->Data() & theMask; + int nZeros = 0; + if (val == 0) + { + theMask = ~BlockType(0); // void, nothing to do + } + else + { + BlockType aMask = ~BlockType(0); + if constexpr (Is64Bit) + { + if ((val & 0xffffffff00000000ULL) == 0) + { + aMask = 0x00000000ffffffffULL; + nZeros = 32; + val <<= 32; + } + } + if ((val & BlockType(0xffff0000) << (Is64Bit ? 32 : 0)) == 0) + { + aMask >>= 16; + nZeros += 16; + val <<= 16; + } + if ((val & BlockType(0xff000000) << (Is64Bit ? 32 : 0)) == 0) + { + aMask >>= 8; + nZeros += 8; + val <<= 8; + } + if ((val & BlockType(0xf0000000) << (Is64Bit ? 32 : 0)) == 0) + { + aMask >>= 4; + nZeros += 4; + val <<= 4; + } + if ((val & BlockType(0xc0000000) << (Is64Bit ? 32 : 0)) == 0) + { + aMask >>= 2; + nZeros += 2; + val <<= 2; + } + if ((val & BlockType(0x80000000) << (Is64Bit ? 32 : 0)) == 0) + { + aMask >>= 1; + nZeros++; + } + theMask = (aMask >> 1); + } + return static_cast((BitsPerBlock - 1) - nZeros) + theNode->Key(); + } + +private: + PackedMapNode** myData1; //!< data array + int myNbBuckets; //!< number of buckets (size of data array) + int myNbPackedMapNodes; //!< amount of packed map nodes + size_t myExtent; //!< extent of this map (number of unpacked integer keys) +}; + +// Include algorithm header after class definition to avoid circular dependency +#include + +// Implementation of deprecated methods +template +void NCollection_PackedMap::Union(const NCollection_PackedMap& theLeft, + const NCollection_PackedMap& theRight) +{ + NCollection_PackedMapAlgo::Union(*this, theLeft, theRight); +} + +template +bool NCollection_PackedMap::Unite(const NCollection_PackedMap& theOther) +{ + return NCollection_PackedMapAlgo::Unite(*this, theOther); +} + +template +void NCollection_PackedMap::Intersection(const NCollection_PackedMap& theLeft, + const NCollection_PackedMap& theRight) +{ + NCollection_PackedMapAlgo::Intersection(*this, theLeft, theRight); +} + +template +bool NCollection_PackedMap::Intersect(const NCollection_PackedMap& theOther) +{ + return NCollection_PackedMapAlgo::Intersect(*this, theOther); +} + +template +void NCollection_PackedMap::Subtraction(const NCollection_PackedMap& theLeft, + const NCollection_PackedMap& theRight) +{ + NCollection_PackedMapAlgo::Subtraction(*this, theLeft, theRight); +} + +template +bool NCollection_PackedMap::Subtract(const NCollection_PackedMap& theOther) +{ + return NCollection_PackedMapAlgo::Subtract(*this, theOther); +} + +template +void NCollection_PackedMap::Difference(const NCollection_PackedMap& theLeft, + const NCollection_PackedMap& theRight) +{ + NCollection_PackedMapAlgo::Difference(*this, theLeft, theRight); +} + +template +bool NCollection_PackedMap::Differ(const NCollection_PackedMap& theOther) +{ + return NCollection_PackedMapAlgo::Differ(*this, theOther); +} + +template +bool NCollection_PackedMap::IsEqual(const NCollection_PackedMap& theOther) const +{ + return NCollection_PackedMapAlgo::IsEqual(*this, theOther); +} + +template +bool NCollection_PackedMap::IsSubset(const NCollection_PackedMap& theOther) const +{ + return NCollection_PackedMapAlgo::IsSubset(*this, theOther); +} + +template +bool NCollection_PackedMap::HasIntersection(const NCollection_PackedMap& theOther) const +{ + return NCollection_PackedMapAlgo::HasIntersection(*this, theOther); +} + +template +bool NCollection_PackedMap::Contains(const NCollection_PackedMap& theOther) const +{ + return NCollection_PackedMapAlgo::Contains(*this, theOther); +} + +#endif // NCollection_PackedMap_HeaderFile diff --git a/src/FoundationClasses/TKernel/NCollection/NCollection_PackedMapAlgo.hxx b/src/FoundationClasses/TKernel/NCollection/NCollection_PackedMapAlgo.hxx new file mode 100644 index 0000000000..f8eecbd47d --- /dev/null +++ b/src/FoundationClasses/TKernel/NCollection/NCollection_PackedMapAlgo.hxx @@ -0,0 +1,376 @@ +// Copyright (c) 2005-2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef NCollection_PackedMapAlgo_HeaderFile +#define NCollection_PackedMapAlgo_HeaderFile + +#include + +//! @brief Algorithms and utilities for NCollection_PackedMap operations. +//! +//! This namespace provides template functions for boolean operations +//! on packed maps: union, intersection, subtraction, and symmetric difference. +//! These algorithms are optimized for the packed bit representation. +namespace NCollection_PackedMapAlgo +{ +//! Apply to theMap the boolean operation union (aka addition, fuse, merge, boolean OR) +//! with another (given) Map. The result contains the values that were previously +//! contained in theMap or contained in the given (operand) map. +//! @return True if content of theMap is changed +template +bool Unite(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (theOtherMap.IsEmpty() || &theMap == &theOtherMap) + return false; + else if (theMap.IsEmpty()) + { + theMap.Assign(theOtherMap); + return true; + } + + const int anOldExtent = theMap.Extent(); + for (typename NCollection_PackedMap::Iterator anIter(theOtherMap); anIter.More(); + anIter.Next()) + { + theMap.Add(anIter.Key()); + } + return anOldExtent != theMap.Extent(); +} + +//! Sets theMap to be the result of union (aka addition, fuse, merge, boolean OR) +//! operation between two given Maps. The new Map contains the values that are +//! contained either in the first map or in the second map or in both. +//! All previous content of theMap is cleared. theMap (result of the boolean +//! operation) can also be passed as one of operands. +template +void Union(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theLeftMap, + const NCollection_PackedMap& theRightMap) +{ + if (theLeftMap.IsEmpty()) + theMap.Assign(theRightMap); + else if (theRightMap.IsEmpty()) + theMap.Assign(theLeftMap); + else if (&theMap == &theLeftMap) + Unite(theMap, theRightMap); + else if (&theMap == &theRightMap) + Unite(theMap, theLeftMap); + else + { + theMap.Clear(); + for (typename NCollection_PackedMap::Iterator anIter(theLeftMap); anIter.More(); + anIter.Next()) + { + theMap.Add(anIter.Key()); + } + for (typename NCollection_PackedMap::Iterator anIter(theRightMap); anIter.More(); + anIter.Next()) + { + theMap.Add(anIter.Key()); + } + } +} + +//! Apply to theMap the intersection operation (aka multiplication, common, boolean AND) +//! with another (given) Map. The result contains only the values that are contained in +//! both theMap and the given map. +//! @return True if content of theMap is changed +template +bool Intersect(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (theMap.IsEmpty()) + return false; + else if (theOtherMap.IsEmpty()) + { + theMap.Clear(); + return true; + } + else if (&theMap == &theOtherMap) + return false; + + const int anOldExtent = theMap.Extent(); + NCollection_PackedMap aCopy; + for (typename NCollection_PackedMap::Iterator anIter(theMap); anIter.More(); + anIter.Next()) + { + if (theOtherMap.Contains(anIter.Key())) + { + aCopy.Add(anIter.Key()); + } + } + theMap = std::move(aCopy); + return anOldExtent != theMap.Extent(); +} + +//! Sets theMap to be the result of intersection (aka multiplication, common, boolean AND) +//! operation between two given Maps. The new Map contains only the values that are +//! contained in both map operands. All previous content of theMap is cleared. +//! theMap (result of the boolean operation) can also be used as one of operands. +template +void Intersection(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theLeftMap, + const NCollection_PackedMap& theRightMap) +{ + if (theLeftMap.IsEmpty() || theRightMap.IsEmpty()) + theMap.Clear(); + else if (&theMap == &theLeftMap) + Intersect(theMap, theRightMap); + else if (&theMap == &theRightMap) + Intersect(theMap, theLeftMap); + else + { + theMap.Clear(); + const NCollection_PackedMap* aSmaller = &theLeftMap; + const NCollection_PackedMap* aLarger = &theRightMap; + if (theLeftMap.Extent() > theRightMap.Extent()) + { + aSmaller = &theRightMap; + aLarger = &theLeftMap; + } + for (typename NCollection_PackedMap::Iterator anIter(*aSmaller); anIter.More(); + anIter.Next()) + { + if (aLarger->Contains(anIter.Key())) + { + theMap.Add(anIter.Key()); + } + } + } +} + +//! Apply to theMap the subtraction (aka set-theoretic difference, relative complement, +//! exclude, cut, boolean NOT) operation with another (given) Map. The result contains +//! only the values that were previously contained in theMap and not contained in theOtherMap. +//! @return True if content of theMap is changed +template +bool Subtract(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (&theMap == &theOtherMap) + { + if (theMap.IsEmpty()) + { + return false; + } + theMap.Clear(); + return true; + } + + if (theMap.IsEmpty() || theOtherMap.IsEmpty()) + return false; + + const int anOldExtent = theMap.Extent(); + for (typename NCollection_PackedMap::Iterator anIter(theOtherMap); anIter.More(); + anIter.Next()) + { + theMap.Remove(anIter.Key()); + } + return anOldExtent != theMap.Extent(); +} + +//! Sets theMap to be the result of subtraction (aka set-theoretic difference, relative +//! complement, exclude, cut, boolean NOT) operation between two given Maps. The new Map +//! contains only the values that are contained in the first map operand and not contained +//! in the second one. All previous content of theMap is cleared. +template +void Subtraction(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theLeftMap, + const NCollection_PackedMap& theRightMap) +{ + if (&theMap == &theLeftMap) + { + Subtract(theMap, theRightMap); + return; + } + else if (&theMap == &theRightMap) + { + NCollection_PackedMap aCopy; + Subtraction(aCopy, theLeftMap, theRightMap); + theMap = std::move(aCopy); + return; + } + + theMap.Assign(theLeftMap); + Subtract(theMap, theRightMap); +} + +//! Apply to theMap the symmetric difference (aka exclusive disjunction, boolean XOR) +//! operation with another (given) Map. The result contains the values that are contained +//! only in theMap or the operand map, but not in both. +//! @return True if content of theMap is changed +template +bool Differ(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (&theMap == &theOtherMap) + { + if (theMap.IsEmpty()) + { + return false; + } + theMap.Clear(); + return true; + } + + if (theOtherMap.IsEmpty()) + return false; + else if (theMap.IsEmpty()) + { + theMap.Assign(theOtherMap); + return true; + } + + const int anOldExtent = theMap.Extent(); + for (typename NCollection_PackedMap::Iterator anIter(theOtherMap); anIter.More(); + anIter.Next()) + { + const IntType aKey = anIter.Key(); + if (theMap.Contains(aKey)) + theMap.Remove(aKey); + else + theMap.Add(aKey); + } + return anOldExtent != theMap.Extent(); +} + +//! Sets theMap to be the result of symmetric difference (aka exclusive disjunction, +//! boolean XOR) operation between two given Maps. The new Map contains the values that +//! are contained only in the first or the second operand maps but not in both. +//! All previous content of theMap is cleared. theMap (result of the boolean operation) +//! can also be used as one of operands. +template +void Difference(NCollection_PackedMap& theMap, + const NCollection_PackedMap& theLeftMap, + const NCollection_PackedMap& theRightMap) +{ + if (&theLeftMap == &theRightMap) + { + theMap.Clear(); + return; + } + else if (&theMap == &theLeftMap) + { + Differ(theMap, theRightMap); + return; + } + else if (&theMap == &theRightMap) + { + Differ(theMap, theLeftMap); + return; + } + + theMap.Clear(); + for (typename NCollection_PackedMap::Iterator anIter(theLeftMap); anIter.More(); + anIter.Next()) + { + if (!theRightMap.Contains(anIter.Key())) + { + theMap.Add(anIter.Key()); + } + } + for (typename NCollection_PackedMap::Iterator anIter(theRightMap); anIter.More(); + anIter.Next()) + { + if (!theLeftMap.Contains(anIter.Key())) + { + theMap.Add(anIter.Key()); + } + } +} + +//! Returns True if theMap and theOtherMap have common elements. +template +bool HasIntersection(const NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (theMap.IsEmpty() || theOtherMap.IsEmpty()) + return false; + + if (&theMap == &theOtherMap) + return true; + + const NCollection_PackedMap* aSmaller = &theMap; + const NCollection_PackedMap* aLarger = &theOtherMap; + if (theMap.Extent() > theOtherMap.Extent()) + { + aSmaller = &theOtherMap; + aLarger = &theMap; + } + + for (typename NCollection_PackedMap::Iterator anIter(*aSmaller); anIter.More(); + anIter.Next()) + { + if (aLarger->Contains(anIter.Key())) + { + return true; + } + } + + return false; +} + +//! Checks if theMap contains all keys of theOtherMap. +//! Returns True if theMap is a superset of theOtherMap (theOtherMap is a subset of theMap). +template +bool Contains(const NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (&theMap == &theOtherMap || theOtherMap.IsEmpty()) + { + return true; + } + else if (theMap.Extent() < theOtherMap.Extent()) + { + return false; + } + + for (typename NCollection_PackedMap::Iterator anIter(theOtherMap); anIter.More(); + anIter.Next()) + { + if (!theMap.Contains(anIter.Key())) + { + return false; + } + } + + return true; +} + +//! Returns True if theMap is a subset of theOtherMap, i.e. all elements +//! contained in theMap are also contained in theOtherMap. +//! If theMap is empty, this method returns true for any operand map. +template +bool IsSubset(const NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + return Contains(theOtherMap, theMap); +} + +//! Checks if two maps contain exactly the same keys. +//! Returns True if theMap and theOtherMap are equal. +template +bool IsEqual(const NCollection_PackedMap& theMap, + const NCollection_PackedMap& theOtherMap) +{ + if (&theMap == &theOtherMap) + { + return true; + } + return theMap.Extent() == theOtherMap.Extent() && Contains(theMap, theOtherMap); +} + +} // namespace NCollection_PackedMapAlgo + +#endif // NCollection_PackedMapAlgo_HeaderFile diff --git a/src/FoundationClasses/TKernel/TColStd/FILES.cmake b/src/FoundationClasses/TKernel/TColStd/FILES.cmake index 64cd829a4c..cf821faf60 100644 --- a/src/FoundationClasses/TKernel/TColStd/FILES.cmake +++ b/src/FoundationClasses/TKernel/TColStd/FILES.cmake @@ -2,14 +2,6 @@ set(OCCT_TColStd_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}") set(OCCT_TColStd_FILES - - TColStd_HPackedMapOfInteger.cxx TColStd_HPackedMapOfInteger.hxx - TColStd_HPackedMapOfInteger.lxx - - TColStd_MapIteratorOfPackedMapOfInteger.hxx - - TColStd_PackedMapOfInteger.cxx TColStd_PackedMapOfInteger.hxx - ) diff --git a/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.cxx b/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.cxx deleted file mode 100644 index 500c15e3b8..0000000000 --- a/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.cxx +++ /dev/null @@ -1,30 +0,0 @@ -// Created on: 2006-12-05 -// Created by: Sergey KOCHETKOV -// Copyright (c) 2006-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -IMPLEMENT_STANDARD_RTTIEXT(TColStd_HPackedMapOfInteger, Standard_Transient) - -//! Constructor of empty map -TColStd_HPackedMapOfInteger::TColStd_HPackedMapOfInteger(const int NbBuckets) -{ - myMap.ReSize(NbBuckets); -} - -//! Constructor from already existing map; performs copying -TColStd_HPackedMapOfInteger::TColStd_HPackedMapOfInteger(const TColStd_PackedMapOfInteger& theOther) -{ - myMap.Assign(theOther); -} diff --git a/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.hxx b/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.hxx index 8351a8514b..e5b99b21eb 100644 --- a/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.hxx +++ b/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.hxx @@ -1,6 +1,4 @@ -// Created on: 2006-12-05 -// Created by: Sergey KOCHETKOV -// Copyright (c) 2006-2014 OPEN CASCADE SAS +// Copyright (c) 2006-2026 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -16,32 +14,46 @@ #ifndef _TColStd_HPackedMapOfInteger_HeaderFile #define _TColStd_HPackedMapOfInteger_HeaderFile -#include - -#include #include +#include #include -#include -//! Extension of TColStd_PackedMapOfInteger class to be manipulated by handle. +//! @deprecated This Handle wrapper class is deprecated. +//! Use TColStd_PackedMapOfInteger directly instead. class TColStd_HPackedMapOfInteger : public Standard_Transient { - public: - Standard_EXPORT TColStd_HPackedMapOfInteger(const int NbBuckets = 1); + //! Constructor of empty map. + //! @param theNbBuckets initial number of buckets + TColStd_HPackedMapOfInteger(const int theNbBuckets = 1) + : myMap(theNbBuckets) + { + } - Standard_EXPORT TColStd_HPackedMapOfInteger(const TColStd_PackedMapOfInteger& theOther); + //! Constructor from already existing map; performs copying. + //! @param theOther the map to copy + TColStd_HPackedMapOfInteger(const TColStd_PackedMapOfInteger& theOther) + : myMap(theOther) + { + } - const TColStd_PackedMapOfInteger& Map() const; + //! Constructor from already existing map; performs copying. + //! @param theOther the map to copy + TColStd_HPackedMapOfInteger(TColStd_PackedMapOfInteger&& theOther) + : myMap(std::move(theOther)) + { + } - TColStd_PackedMapOfInteger& ChangeMap(); + //! Returns const reference to the underlying map. + const TColStd_PackedMapOfInteger& Map() const { return myMap; } - DEFINE_STANDARD_RTTIEXT(TColStd_HPackedMapOfInteger, Standard_Transient) + //! Returns mutable reference to the underlying map. + TColStd_PackedMapOfInteger& ChangeMap() { return myMap; } + + DEFINE_STANDARD_RTTI_INLINE(TColStd_HPackedMapOfInteger, Standard_Transient) private: TColStd_PackedMapOfInteger myMap; }; -#include - #endif // _TColStd_HPackedMapOfInteger_HeaderFile diff --git a/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.lxx b/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.lxx deleted file mode 100644 index 9026b641f7..0000000000 --- a/src/FoundationClasses/TKernel/TColStd/TColStd_HPackedMapOfInteger.lxx +++ /dev/null @@ -1,26 +0,0 @@ -// Created on: 2006-12-05 -// Created by: Sergey KOCHETKOV -// Copyright (c) 2006-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -//! Access to the map -inline const TColStd_PackedMapOfInteger& TColStd_HPackedMapOfInteger::Map() const -{ - return myMap; -} - -//! Access to the map for modification -inline TColStd_PackedMapOfInteger& TColStd_HPackedMapOfInteger::ChangeMap() -{ - return myMap; -} diff --git a/src/FoundationClasses/TKernel/TColStd/TColStd_MapIteratorOfPackedMapOfInteger.hxx b/src/FoundationClasses/TKernel/TColStd/TColStd_MapIteratorOfPackedMapOfInteger.hxx deleted file mode 100644 index dcfc6ee5d7..0000000000 --- a/src/FoundationClasses/TKernel/TColStd/TColStd_MapIteratorOfPackedMapOfInteger.hxx +++ /dev/null @@ -1,24 +0,0 @@ -// Created on: 2005-11-26 -// Created by: Alexander GRIGORIEV -// Copyright (c) 2005-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef TColStd_MapIteratorOfPackedMapOfInteger_HeaderFile -#define TColStd_MapIteratorOfPackedMapOfInteger_HeaderFile - -#include - -//! Iterator of class TColStd_PackedMapOfInteger. -typedef TColStd_PackedMapOfInteger::Iterator TColStd_MapIteratorOfPackedMapOfInteger; - -#endif diff --git a/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.cxx b/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.cxx deleted file mode 100644 index 9d619ed19e..0000000000 --- a/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.cxx +++ /dev/null @@ -1,1196 +0,0 @@ -// Created on: 2005-11-05 -// Created by: Alexander GRIGORIEV -// Copyright (c) 2005-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -#include -#include - -namespace -{ -size_t HashCode(const int theKey, const size_t theBound) -{ - return static_cast(theKey) % theBound + 1; -} -} // namespace - -//================================================================================================= - -int TColStd_PackedMapOfInteger::TColStd_intMapNode_findNext(const TColStd_intMapNode* theNode, - unsigned int& theMask) -{ - const TColStd_intMapNode* aNode = reinterpret_cast(theNode); - unsigned int val = aNode->Data() & theMask; - int nZeros(0); - if (val == 0) - theMask = ~0U; // void, nothing to do - else - { - unsigned int aMask = ~0U; - if ((val & 0x0000ffff) == 0) - { - aMask = 0xffff0000; - nZeros = 16; - val >>= 16; - } - if ((val & 0x000000ff) == 0) - { - aMask <<= 8; - nZeros += 8; - val >>= 8; - } - if ((val & 0x0000000f) == 0) - { - aMask <<= 4; - nZeros += 4; - val >>= 4; - } - if ((val & 0x00000003) == 0) - { - aMask <<= 2; - nZeros += 2; - val >>= 2; - } - if ((val & 0x00000001) == 0) - { - aMask <<= 1; - nZeros++; - } - theMask = (aMask << 1); - } - return nZeros + aNode->Key(); -} - -//================================================================================================= - -int TColStd_PackedMapOfInteger::TColStd_intMapNode_findPrev(const TColStd_intMapNode* theNode, - unsigned int& theMask) -{ - const TColStd_intMapNode* aNode = reinterpret_cast(theNode); - unsigned int val = aNode->Data() & theMask; - int nZeros(0); - if (val == 0) - theMask = ~0U; // void, nothing to do - else - { - unsigned int aMask = ~0U; - if ((val & 0xffff0000) == 0) - { - aMask = 0x0000ffff; - nZeros = 16; - val <<= 16; - } - if ((val & 0xff000000) == 0) - { - aMask >>= 8; - nZeros += 8; - val <<= 8; - } - if ((val & 0xf0000000) == 0) - { - aMask >>= 4; - nZeros += 4; - val <<= 4; - } - if ((val & 0xc0000000) == 0) - { - aMask >>= 2; - nZeros += 2; - val <<= 2; - } - if ((val & 0x80000000) == 0) - { - aMask >>= 1; - nZeros++; - } - theMask = (aMask >> 1); - } - return (31 - nZeros) + aNode->Key(); -} - -//================================================================================================= - -TColStd_PackedMapOfInteger& TColStd_PackedMapOfInteger::Assign( - const TColStd_PackedMapOfInteger& theOther) -{ - if (this != &theOther) - { - Clear(); - if (!theOther.IsEmpty()) - { - ReSize(theOther.myNbPackedMapNodes); - const int nBucketsSrc = theOther.myNbBuckets; - const int nBuckets = myNbBuckets; - for (int i = 0; i <= nBucketsSrc; i++) - { - for (const TColStd_intMapNode* p = theOther.myData1[i]; p != nullptr;) - { - const size_t aHashCode = p->HashCode(nBuckets); - myData1[aHashCode] = new TColStd_intMapNode(p->Mask(), p->Data(), myData1[aHashCode]); - ++myNbPackedMapNodes; - p = p->Next(); - } - } - // TColStd_MapIteratorOfPackedMapOfInteger anIt (theOther); - // for (; anIt.More(); anIt.Next()) - // Add (anIt.Key()); - } - } - myExtent = theOther.myExtent; - return *this; -} - -//================================================================================================= - -void TColStd_PackedMapOfInteger::ReSize(const int theNbBuckets) -{ - int aNewBuck = NCollection_Primes::NextPrimeForMap(theNbBuckets); - if (aNewBuck <= myNbBuckets) - { - if (!IsEmpty()) - { - return; - } - aNewBuck = myNbBuckets; - } - - TColStd_intMapNode** aNewData = - (TColStd_intMapNode**)Standard::AllocateOptimal((aNewBuck + 1) * sizeof(TColStd_intMapNode*)); - memset(aNewData, 0, (aNewBuck + 1) * sizeof(TColStd_intMapNode*)); - if (myData1 != nullptr) - { - TColStd_intMapNode** anOldData = myData1; - for (int i = 0; i <= myNbBuckets; ++i) - { - for (TColStd_intMapNode* p = anOldData[i]; p != nullptr;) - { - size_t k = p->HashCode(aNewBuck); - TColStd_intMapNode* q = p->Next(); - p->SetNext(aNewData[k]); - aNewData[k] = p; - p = q; - } - } - } - - Standard::Free(myData1); - myNbBuckets = aNewBuck; - myData1 = aNewData; -} - -//================================================================================================= - -void TColStd_PackedMapOfInteger::Clear() -{ - if (!IsEmpty()) - { - for (int aBucketIter = 0; aBucketIter <= myNbBuckets; ++aBucketIter) - { - if (myData1[aBucketIter]) - { - for (TColStd_intMapNode* aSubNodeIter = myData1[aBucketIter]; aSubNodeIter != nullptr;) - { - TColStd_intMapNode* q = aSubNodeIter->Next(); - delete aSubNodeIter; - aSubNodeIter = q; - } - } - } - } - - myNbPackedMapNodes = 0; - Standard::Free(myData1); - myData1 = nullptr; - myExtent = 0; -} - -//================================================================================================= - -bool TColStd_PackedMapOfInteger::Add(const int aKey) -{ - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - - const int aKeyInt = packedKeyIndex(aKey); - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - TColStd_intMapNode* aBucketHead = myData1[aHashCode]; - for (TColStd_intMapNode* p = aBucketHead; p != nullptr; p = p->Next()) - { - if (p->IsEqual(aKeyInt)) - { - if (p->AddValue(aKey)) - { - ++myExtent; - return true; - } - return false; - } - } - - myData1[aHashCode] = new TColStd_intMapNode(aKey, aBucketHead); - ++myNbPackedMapNodes; - ++myExtent; - return true; -} - -//================================================================================================= - -bool TColStd_PackedMapOfInteger::Contains(const int aKey) const -{ - if (IsEmpty()) - { - return false; - } - - bool aResult = false; - const int aKeyInt = packedKeyIndex(aKey); - for (TColStd_intMapNode* p = myData1[HashCode(aKeyInt, myNbBuckets)]; p != nullptr;) - { - if (p->IsEqual(aKeyInt)) - { - aResult = (p->HasValue(aKey) != 0); - break; - } - p = p->Next(); - } - return aResult; -} - -//================================================================================================= - -bool TColStd_PackedMapOfInteger::Remove(const int aKey) -{ - if (IsEmpty()) - { - return false; - } - - bool aResult(false); - const int aKeyInt = packedKeyIndex(aKey); - TColStd_intMapNode*& aBucketHead = myData1[HashCode(aKeyInt, myNbBuckets)]; - TColStd_intMapNode* p = aBucketHead; - TColStd_intMapNode* q = nullptr; - while (p) - { - if (p->IsEqual(aKeyInt)) - { - aResult = p->DelValue(aKey); - if (aResult) - { - --myExtent; - if (!p->HasValues()) - { - --myNbPackedMapNodes; - if (q != nullptr) - { - q->SetNext(p->Next()); - } - else - { - aBucketHead = p->Next(); - } - delete p; - } - } - break; - } - q = p; - p = p->Next(); - } - return aResult; -} - -//======================================================================= -// function : GetMinimalMapped -// purpose : Query the minimal contained key value. -//======================================================================= - -int TColStd_PackedMapOfInteger::GetMinimalMapped() const -{ - if (IsEmpty()) - { - return IntegerLast(); - } - - int aResult(IntegerLast()); - const TColStd_intMapNode* pFoundNode = nullptr; - for (int i = 0; i <= myNbBuckets; i++) - { - for (const TColStd_intMapNode* p = myData1[i]; p != nullptr; p = p->Next()) - { - const int aKey = p->Key(); - if (aResult > aKey) - { - aResult = aKey; - pFoundNode = p; - } - } - } - if (pFoundNode) - { - unsigned int aFullMask(0xffffffff); - aResult = TColStd_intMapNode_findNext(pFoundNode, aFullMask); - } - return aResult; -} - -//======================================================================= -// function : GetMaximalMapped -// purpose : Query the maximal contained key value. -//======================================================================= - -int TColStd_PackedMapOfInteger::GetMaximalMapped() const -{ - if (IsEmpty()) - { - return IntegerFirst(); - } - - int aResult(IntegerFirst()); - const TColStd_intMapNode* pFoundNode = nullptr; - for (int i = 0; i <= myNbBuckets; i++) - { - for (const TColStd_intMapNode* p = myData1[i]; p != nullptr; p = p->Next()) - { - const int aKey = p->Key(); - if (aResult < aKey) - { - aResult = aKey; - pFoundNode = p; - } - } - } - if (pFoundNode) - { - unsigned int aFullMask(0xffffffff); - aResult = TColStd_intMapNode_findPrev(pFoundNode, aFullMask); - } - return aResult; -} - -//======================================================================= -// function : Union -// purpose : Boolean operation OR between 2 maps -//======================================================================= - -void TColStd_PackedMapOfInteger::Union(const TColStd_PackedMapOfInteger& theMap1, - const TColStd_PackedMapOfInteger& theMap2) -{ - if (theMap1.IsEmpty()) // 0 | B == B - Assign(theMap2); - else if (theMap2.IsEmpty()) // A | 0 == A - Assign(theMap1); - else if (myData1 == theMap1.myData1) - Unite(theMap2); - else if (myData1 == theMap2.myData1) - Unite(theMap1); - else - { - const int nBuckets1 = theMap1.myNbBuckets; - const int nBuckets2 = theMap2.myNbBuckets; - Clear(); - // Iteration of the 1st map. - for (int i = 0; i <= nBuckets1; i++) - { - const TColStd_intMapNode* p1 = theMap1.myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - unsigned int aNewMask = p1->Mask(); - unsigned int aNewData = p1->Data(); - size_t nValues(p1->NbValues()); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap2.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - aNewData |= p2->Data(); - nValues = TColStd_Population(aNewMask, aNewData); - break; - } - p2 = p2->Next(); - } - // Store the block - result of operation - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - myData1[aHashCode] = new TColStd_intMapNode(aNewMask, aNewData, myData1[aHashCode]); - ++myNbPackedMapNodes; - myExtent += nValues; - p1 = p1->Next(); - } - } - // Iteration of the 2nd map. - for (int i = 0; i <= nBuckets2; i++) - { - const TColStd_intMapNode* p2 = theMap2.myData1[i]; - while (p2 != nullptr) - { - // Find aKey - the base address of currently iterated block - const int aKey = p2->Key(); - const int aKeyInt = packedKeyIndex(aKey); - // Find the corresponding block in the 1st map - const TColStd_intMapNode* p1 = theMap1.myData1[HashCode(aKeyInt, nBuckets1)]; - while (p1) - { - if (p1->IsEqual(aKeyInt)) - break; - p1 = p1->Next(); - } - // Add the block from the 2nd map only in the case when the similar - // block has not been found in the 1st map - if (p1 == nullptr) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - myData1[aHashCode] = new TColStd_intMapNode(p2->Mask(), p2->Data(), myData1[aHashCode]); - ++myNbPackedMapNodes; - myExtent += p2->NbValues(); - } - p2 = p2->Next(); - } - } - } -} - -//======================================================================= -// function : Unite -// purpose : Boolean operation OR with the given map -//======================================================================= - -bool TColStd_PackedMapOfInteger::Unite(const TColStd_PackedMapOfInteger& theMap) -{ - if (theMap.IsEmpty() || myData1 == theMap.myData1) // A | 0 == A | A == A - return false; - else if (IsEmpty()) - { // 0 | B == B - Assign(theMap); - return true; - } - - size_t aNewExtent(myExtent); - const int nBuckets2 = theMap.myNbBuckets; - - // Iteration of the 2nd map. - for (int i = 0; i <= nBuckets2; i++) - { - const TColStd_intMapNode* p2 = theMap.myData1[i]; - while (p2 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p2->Key(); - const int aKeyInt = packedKeyIndex(aKey); - // Find the corresponding block in the 1st (this) map - size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - TColStd_intMapNode* p1 = myData1[aHashCode]; - while (p1) - { - if (p1->IsEqual(aKeyInt)) - { - const size_t anOldPop = p1->NbValues(); - unsigned int newData = p1->Data() | p2->Data(); - if (newData != p1->Data()) - { - p1->ChangeData() = newData; - aNewExtent = aNewExtent - anOldPop + TColStd_Population(p1->ChangeMask(), newData); - } - break; - } - p1 = p1->Next(); - } - // If the block is not found in the 1st map, add it to the 1st map - if (p1 == nullptr) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - aHashCode = HashCode(aKeyInt, myNbBuckets); - } - myData1[aHashCode] = new TColStd_intMapNode(p2->Mask(), p2->Data(), myData1[aHashCode]); - ++myNbPackedMapNodes; - aNewExtent += p2->NbValues(); - } - p2 = p2->Next(); - } - } - bool isChanged = (myExtent != aNewExtent); - myExtent = aNewExtent; - return isChanged; -} - -//======================================================================= -// function : Intersection -// purpose : Boolean operation AND between 2 maps -//======================================================================= - -void TColStd_PackedMapOfInteger::Intersection(const TColStd_PackedMapOfInteger& theMap1, - const TColStd_PackedMapOfInteger& theMap2) -{ - if (theMap1.IsEmpty() || theMap2.IsEmpty()) // A & 0 == 0 & B == 0 - Clear(); - else if (myData1 == theMap1.myData1) - Intersect(theMap2); - else if (myData1 == theMap2.myData1) - Intersect(theMap1); - else - { - const TColStd_intMapNode* const* aData1; - const TColStd_intMapNode* const* aData2; - int nBuckets1, nBuckets2; - if (theMap1.Extent() < theMap2.Extent()) - { - aData1 = theMap1.myData1; - aData2 = theMap2.myData1; - nBuckets1 = theMap1.myNbBuckets; - nBuckets2 = theMap2.myNbBuckets; - } - else - { - aData1 = theMap2.myData1; - aData2 = theMap1.myData1; - nBuckets1 = theMap2.myNbBuckets; - nBuckets2 = theMap1.myNbBuckets; - } - Clear(); - - // Iteration of the 1st map. - for (int i = 0; i <= nBuckets1; i++) - { - const TColStd_intMapNode* p1 = aData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = aData2[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - const unsigned int aNewData = p1->Data() & p2->Data(); - // Store the block - result of operation - if (aNewData) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - unsigned int aNewMask = p1->Mask(); - myExtent += TColStd_Population(aNewMask, aNewData); - myData1[aHashCode] = new TColStd_intMapNode(aNewMask, aNewData, myData1[aHashCode]); - ++myNbPackedMapNodes; - } - break; - } - p2 = p2->Next(); - } - p1 = p1->Next(); - } - } - } -} - -//======================================================================= -// function : Intersect -// purpose : Boolean operation AND with the given map -//======================================================================= - -bool TColStd_PackedMapOfInteger::Intersect(const TColStd_PackedMapOfInteger& theMap) -{ - if (IsEmpty()) // 0 & B == 0 - return false; - else if (theMap.IsEmpty()) - { // A & 0 == 0 - Clear(); - return true; - } - else if (myData1 == theMap.myData1) // A & A == A - return false; - - size_t aNewExtent(0); - const int nBuckets2 = theMap.myNbBuckets; - - // Iteration of this map. - for (int i = 0; i <= myNbBuckets; i++) - { - TColStd_intMapNode* q = nullptr; - TColStd_intMapNode* p1 = myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - const unsigned int aNewData = p1->Data() & p2->Data(); - // Store the block - result of operation - if (aNewData == 0) - p2 = nullptr; // no match - the block has to be removed - else - { - if (aNewData != p1->Data()) - p1->ChangeData() = aNewData; - aNewExtent += TColStd_Population(p1->ChangeMask(), aNewData); - } - break; - } - p2 = p2->Next(); - } - TColStd_intMapNode* pNext = p1->Next(); - // If p2!=NULL, then the map node is kept and we move to the next one - // Otherwise we should remove the current node - if (p2) - { - q = p1; - } - else - { - --myNbPackedMapNodes; - if (q) - q->SetNext(pNext); - else - myData1[i] = pNext; - delete p1; - } - p1 = pNext; - } - } - bool isChanged = (myExtent != aNewExtent); - myExtent = aNewExtent; - return isChanged; -} - -//======================================================================= -// function : Subtraction -// purpose : Boolean operation SUBTRACT between two maps -//======================================================================= - -void TColStd_PackedMapOfInteger::Subtraction(const TColStd_PackedMapOfInteger& theMap1, - const TColStd_PackedMapOfInteger& theMap2) -{ - if (theMap1.IsEmpty() || theMap2.myData1 == theMap1.myData1) // 0 \ A == A \ A == 0 - Clear(); - else if (theMap2.IsEmpty()) // A \ 0 == A - Assign(theMap1); - else if (myData1 == theMap1.myData1) - Subtract(theMap2); - else if (myData1 == theMap2.myData1) - { - TColStd_PackedMapOfInteger aMap; - aMap.Subtraction(theMap1, theMap2); - Assign(aMap); - } - else - { - const int nBuckets1 = theMap1.myNbBuckets; - const int nBuckets2 = theMap2.myNbBuckets; - Clear(); - - // Iteration of the 1st map. - for (int i = 0; i <= nBuckets1; i++) - { - const TColStd_intMapNode* p1 = theMap1.myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - unsigned int aNewMask = p1->Mask(); - unsigned int aNewData = p1->Data(); - size_t nValues(p1->NbValues()); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap2.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - aNewData &= ~p2->Data(); - nValues = TColStd_Population(aNewMask, aNewData); - break; - } - p2 = p2->Next(); - } - // Store the block - result of operation - if (aNewData) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - myData1[aHashCode] = new TColStd_intMapNode(aNewMask, aNewData, myData1[aHashCode]); - ++myNbPackedMapNodes; - myExtent += nValues; - } - p1 = p1->Next(); - } - } - } -} - -//======================================================================= -// function : Subtract -// purpose : Boolean operation SUBTRACT with the given map -//======================================================================= - -bool TColStd_PackedMapOfInteger::Subtract(const TColStd_PackedMapOfInteger& theMap) -{ - if (IsEmpty() || theMap.IsEmpty()) // 0 \ B == 0; A \ 0 == A - return false; - else if (myData1 == theMap.myData1) - { // A \ A == 0 - Clear(); - return true; - } - else - { - size_t aNewExtent(0); - const int nBuckets2 = theMap.myNbBuckets; - // Iteration of this map. - for (int i = 0; i <= myNbBuckets; i++) - { - TColStd_intMapNode* q = nullptr; - TColStd_intMapNode* p1 = myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - TColStd_intMapNode* pNext = p1->Next(); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - const unsigned int aNewData = p1->Data() & ~p2->Data(); - // Store the block - result of operation - if (aNewData == 0) - { - // no match - the block has to be removed - --myNbPackedMapNodes; - if (q) - q->SetNext(pNext); - else - myData1[i] = pNext; - delete p1; - } - else if (aNewData != p1->Data()) - { - p1->ChangeData() = aNewData; - aNewExtent += TColStd_Population(p1->ChangeMask(), aNewData); - q = p1; - } - else - { - aNewExtent += p1->NbValues(); - q = p1; - } - break; - } - p2 = p2->Next(); - } - if (p2 == nullptr) - { - aNewExtent += p1->NbValues(); - q = p1; - } - p1 = pNext; - } - } - bool isChanged = (myExtent != aNewExtent); - myExtent = aNewExtent; - return isChanged; - } -} - -//================================================================================================= - -void TColStd_PackedMapOfInteger::Difference(const TColStd_PackedMapOfInteger& theMap1, - const TColStd_PackedMapOfInteger& theMap2) -{ - if (theMap1.IsEmpty()) // 0 ^ B == B - Assign(theMap2); - else if (theMap2.IsEmpty()) // A ^ 0 == A - Assign(theMap1); - else if (myData1 == theMap1.myData1) - Differ(theMap2); - else if (myData1 == theMap2.myData1) - Differ(theMap1); - else - { - int i; - const int nBuckets1 = theMap1.myNbBuckets; - const int nBuckets2 = theMap2.myNbBuckets; - Clear(); - - // Iteration of the 1st map. - for (i = 0; i <= nBuckets1; i++) - { - const TColStd_intMapNode* p1 = theMap1.myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - unsigned int aNewMask = p1->Mask(); - unsigned int aNewData = p1->Data(); - size_t nValues(p1->NbValues()); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap2.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - aNewData ^= p2->Data(); - nValues = TColStd_Population(aNewMask, aNewData); - break; - } - p2 = p2->Next(); - } - // Store the block - result of operation - if (aNewData) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - myData1[aHashCode] = new TColStd_intMapNode(aNewMask, aNewData, myData1[aHashCode]); - ++myNbPackedMapNodes; - myExtent += nValues; - } - p1 = p1->Next(); - } - } - - // Iteration of the 2nd map. - for (i = 0; i <= nBuckets2; i++) - { - const TColStd_intMapNode* p2 = theMap2.myData1[i]; - while (p2 != nullptr) - { - // Find aKey - the base address of currently iterated block - const int aKey = p2->Key(); - const int aKeyInt = packedKeyIndex(aKey); - // Find the corresponding block in the 1st map - const TColStd_intMapNode* p1 = theMap1.myData1[HashCode(aKeyInt, nBuckets1)]; - while (p1) - { - if (p1->IsEqual(aKeyInt)) - break; - p1 = p1->Next(); - } - // Add the block from the 2nd map only in the case when the similar - // block has not been found in the 1st map - if (p1 == nullptr) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - myData1[aHashCode] = new TColStd_intMapNode(p2->Mask(), p2->Data(), myData1[aHashCode]); - ++myNbPackedMapNodes; - myExtent += p2->NbValues(); - } - p2 = p2->Next(); - } - } - } -} - -//================================================================================================= - -bool TColStd_PackedMapOfInteger::Differ(const TColStd_PackedMapOfInteger& theMap) -{ - if (theMap.IsEmpty()) // A ^ 0 = A - return false; - else if (IsEmpty()) - { // 0 ^ B = B - Assign(theMap); - return true; - } - else if (myData1 == theMap.myData1) - { // A ^ A == 0 - Clear(); - return true; - } - - size_t aNewExtent(0); - const int nBuckets2 = theMap.myNbBuckets; - bool isChanged = false; - // Iteration by other map - for (int i = 0; i <= nBuckets2; i++) - { - TColStd_intMapNode* q = nullptr; - const TColStd_intMapNode* p2 = theMap.myData1[i]; - while (p2 != nullptr) - { - // Find aKey - the base address of currently iterated block - const int aKey = p2->Key(); - const int aKeyInt = packedKeyIndex(aKey); - - // Find the corresponding block in the 1st map - TColStd_intMapNode* p1 = myData1[HashCode(aKeyInt, myNbBuckets)]; - TColStd_intMapNode* pNext = p1->Next(); - while (p1) - { - if (p1->IsEqual(aKeyInt)) - { - const unsigned int aNewData = p1->Data() ^ p2->Data(); - // Store the block - result of operation - if (aNewData == 0) - { - // no match - the block has to be removed - --myNbPackedMapNodes; - if (q) - q->SetNext(pNext); - else - myData1[i] = pNext; - delete p1; - } - else if (aNewData != p1->Data()) - { - p1->ChangeData() = aNewData; - isChanged = true; - aNewExtent += TColStd_Population(p1->ChangeMask(), aNewData); - q = p1; - } - break; - } - p1 = pNext; - } - // Add the block from the 2nd map only in the case when the similar - // block has not been found in the 1st map - if (p1 == nullptr) - { - if (Resizable()) - { - ReSize(myNbPackedMapNodes); - } - const size_t aHashCode = HashCode(aKeyInt, myNbBuckets); - myData1[aHashCode] = new TColStd_intMapNode(p2->Mask(), p2->Data(), myData1[aHashCode]); - ++myNbPackedMapNodes; - aNewExtent += p2->NbValues(); - isChanged = true; - } - p2 = p2->Next(); - } - } - myExtent = aNewExtent; - return isChanged; -} - -//======================================================================= -// function : IsEqual -// purpose : Boolean operation returns true if this map is equal to the other map -//======================================================================= - -bool TColStd_PackedMapOfInteger::IsEqual(const TColStd_PackedMapOfInteger& theMap) const -{ - if (IsEmpty() && theMap.IsEmpty()) - return true; - else if (Extent() != theMap.Extent()) - return false; - else if (myData1 == theMap.myData1) - return true; - - const int nBuckets2 = theMap.myNbBuckets; - // Iteration of this map. - for (int i = 0; i <= myNbBuckets; i++) - { - const TColStd_intMapNode* p1 = myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - TColStd_intMapNode* pNext = p1->Next(); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - if (p1->Data() != p2->Data()) - return false; - break; - } - p2 = p2->Next(); - } - // if the same block not found, maps are different - if (p2 == nullptr) - return false; - - p1 = pNext; - } - } - return true; -} - -//======================================================================= -// function : IsSubset -// purpose : Boolean operation returns true if this map if subset of other map -//======================================================================= - -bool TColStd_PackedMapOfInteger::IsSubset(const TColStd_PackedMapOfInteger& theMap) const -{ - if (IsEmpty()) // 0 <= A - return true; - else if (theMap.IsEmpty()) // ! ( A <= 0 ) - return false; - else if (Extent() > theMap.Extent()) - return false; - else if (myData1 == theMap.myData1) - return true; - - const int nBuckets2 = theMap.myNbBuckets; - // Iteration of this map. - for (int i = 0; i <= myNbBuckets; i++) - { - const TColStd_intMapNode* p1 = myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - TColStd_intMapNode* pNext = p1->Next(); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap.myData1[HashCode(aKeyInt, nBuckets2)]; - if (!p2) - return false; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - if (p1->Data() & ~p2->Data()) // at least one bit set in p1 is not set in p2 - return false; - break; - } - p2 = p2->Next(); - } - p1 = pNext; - } - } - return true; -} - -//======================================================================= -// function : HasIntersection -// purpose : Boolean operation returns true if this map intersects with other map -//======================================================================= - -bool TColStd_PackedMapOfInteger::HasIntersection(const TColStd_PackedMapOfInteger& theMap) const -{ - if (IsEmpty() || theMap.IsEmpty()) // A * 0 == 0 * B == 0 - return false; - - if (myData1 == theMap.myData1) - return true; - - const int nBuckets2 = theMap.myNbBuckets; - // Iteration of this map. - for (int i = 0; i <= myNbBuckets; i++) - { - const TColStd_intMapNode* p1 = myData1[i]; - while (p1 != nullptr) - { - // Find aKey - the base address of currently iterated block of integers - const int aKey = p1->Key(); - const int aKeyInt = packedKeyIndex(aKey); - TColStd_intMapNode* pNext = p1->Next(); - // Find the corresponding block in the 2nd map - const TColStd_intMapNode* p2 = theMap.myData1[HashCode(aKeyInt, nBuckets2)]; - while (p2) - { - if (p2->IsEqual(aKeyInt)) - { - if (p1->Data() & p2->Data()) - return true; - break; - } - p2 = p2->Next(); - } - p1 = pNext; - } - } - return false; -} - -//================================================================================================= - -void TColStd_PackedMapOfInteger::Statistics(Standard_OStream& theStream) const -{ - theStream << "\nMap Statistics\n---------------\n\n"; - theStream << "This Map has " << myNbBuckets << " Buckets and " << myNbPackedMapNodes - << " Keys\n\n"; - if (myNbPackedMapNodes == 0) - { - return; - } - - NCollection_Array1 aSizes(0, myNbPackedMapNodes); - aSizes.Init(0); - - theStream << "\nStatistics for the first Key\n"; - int aNbNonEmpty = 0; - for (int aBucketIter = 0; aBucketIter <= myNbBuckets; ++aBucketIter) - { - TColStd_intMapNode* aSubNodeIter = myData1[aBucketIter]; - if (aSubNodeIter != nullptr) - { - ++aNbNonEmpty; - } - - int aNbMapSubNodes = 0; - for (; aSubNodeIter != nullptr; aSubNodeIter = aSubNodeIter->Next()) - { - ++aNbMapSubNodes; - } - ++aSizes[aNbMapSubNodes]; - } - - // display results - int aNbMapSubNodesTotal = 0; - for (int aNbMapSubNodes = 0; aNbMapSubNodes <= myNbPackedMapNodes; ++aNbMapSubNodes) - { - if (aSizes[aNbMapSubNodes] > 0) - { - aNbMapSubNodesTotal += aSizes[aNbMapSubNodes] * aNbMapSubNodes; - theStream << std::setw(5) << aSizes[aNbMapSubNodes] << " buckets of size " << aNbMapSubNodes - << "\n"; - } - } - - const double aMean = ((double)aNbMapSubNodesTotal) / ((double)aNbNonEmpty); - theStream << "\n\nMean of length: " << aMean << "\n"; -} diff --git a/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.hxx b/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.hxx index 69331394e1..69f4a2ce16 100644 --- a/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.hxx +++ b/src/FoundationClasses/TKernel/TColStd/TColStd_PackedMapOfInteger.hxx @@ -16,482 +16,10 @@ #ifndef TColStd_PackedMapOfInteger_HeaderFile #define TColStd_PackedMapOfInteger_HeaderFile -#include -#include -#include -#include -#include -#include -#include +#include +#include -/** - * Optimized Map of integer values. Each block of 32 integers is stored in 8 bytes in memory. - */ -class TColStd_PackedMapOfInteger -{ -public: - DEFINE_STANDARD_ALLOC +//! @deprecated Use NCollection_PackedMapOfInteger instead. +typedef NCollection_PackedMap TColStd_PackedMapOfInteger; -private: - //! 5 lower bits - static const unsigned int MASK_LOW = 0x001f; - - //! 27 upper bits - static const unsigned int MASK_HIGH = ~MASK_LOW; - - //! Class implementing a block of 32 consecutive integer values as a node of a Map collection. - //! The data are stored in 64 bits as: - //! - bits 0 - 4 : (number of integers stored in the block) - 1; - //! - bits 5 - 31: base address of the block of integers (low bits assumed 0) - //! - bits 32 - 63: 32-bit field where each bit indicates the presence of the corresponding - //! integer in the block. - //! Number of non-zero bits must be equal to the number expressed in bits 0-4. - class TColStd_intMapNode - { - public: - TColStd_intMapNode(TColStd_intMapNode* thePtr = nullptr) - : myNext(thePtr), - myMask(0), - myData(0) - { - } - - TColStd_intMapNode(int theValue, TColStd_intMapNode*& thePtr) - : myNext(thePtr), - myMask((unsigned int)(theValue & MASK_HIGH)), - myData(1 << (theValue & MASK_LOW)) - { - } - - TColStd_intMapNode(unsigned int theMask, unsigned int theData, TColStd_intMapNode* thePtr) - : myNext(thePtr), - myMask(theMask), - myData(theData) - { - } - - unsigned int Mask() const { return myMask; } - - unsigned int Data() const { return myData; } - - unsigned int& ChangeMask() { return myMask; } - - unsigned int& ChangeData() { return myData; } - - //! Compute the sequential index of this packed node in the map. - int Key() const { return int(myMask & MASK_HIGH); } - - //! Return the number of set integer keys. - size_t NbValues() const { return size_t(myMask & MASK_LOW) + 1; } - - //! Return TRUE if this packed node is not empty. - bool HasValues() const { return (myData != 0); } - - //! Return TRUE if the given integer key is set within this packed node. - int HasValue(int theValue) const { return (myData & (1 << (theValue & MASK_LOW))); } - - //! Add integer key to this packed node. - //! @return TRUE if key has been added - bool AddValue(int theValue) - { - const int aValInt = (1 << (theValue & MASK_LOW)); - if ((myData & aValInt) == 0) - { - myData ^= aValInt; - ++myMask; - return true; - } - return false; - } - - //! Delete integer key from this packed node. - //! @return TRUE if key has been deleted - bool DelValue(int theValue) - { - const int aValInt = (1 << (theValue & MASK_LOW)); - if ((myData & aValInt) != 0) - { - myData ^= aValInt; - myMask--; - return true; - } - return false; - } - - //! Find the smallest non-zero bit under the given mask. Outputs the new mask - //! that does not contain the detected bit. - int FindNext(unsigned int& theMask) const; - - //! Return the next node having the same hash code. - TColStd_intMapNode* Next() const { return myNext; } - - //! Set the next node having the same hash code. - void SetNext(TColStd_intMapNode* theNext) { myNext = theNext; } - - public: - //! Support of Map interface. - int HashCode(int theUpper) const { return (myMask >> 5) % theUpper + 1; } - - //! Support of Map interface. - bool IsEqual(int theOther) const { return ((myMask >> 5) == (unsigned)theOther); } - - private: - TColStd_intMapNode* myNext; - unsigned int myMask; - unsigned int myData; - }; - -public: - //! Iterator of class TColStd_PackedMapOfInteger. - class Iterator - { - public: - /// Empty Constructor. - Iterator() - : myBuckets(nullptr), - myNode(nullptr), - myNbBuckets(-1), - myBucket(-1), - myIntMask(~0U), - myKey(0) - { - } - - /// Constructor. - Iterator(const TColStd_PackedMapOfInteger& theMap) - : myBuckets(theMap.myData1), - myNode(nullptr), - myNbBuckets(theMap.myData1 != nullptr ? theMap.myNbBuckets : -1), - myBucket(-1), - myIntMask(~0U) - { - next(); - myKey = myNode != nullptr ? TColStd_intMapNode_findNext(myNode, myIntMask) : 0; - } - - //! Re-initialize with the same or another Map instance. - void Initialize(const TColStd_PackedMapOfInteger& theMap) - { - myBuckets = theMap.myData1; - myBucket = -1; - myNode = nullptr; - myNbBuckets = theMap.myData1 != nullptr ? theMap.myNbBuckets : -1; - next(); - - myIntMask = ~0U; - myKey = myNode != nullptr ? TColStd_intMapNode_findNext(myNode, myIntMask) : 0; - } - - //! Restart the iteration - void Reset() - { - myBucket = -1; - myNode = nullptr; - next(); - - myIntMask = ~0U; - myKey = myNode != nullptr ? TColStd_intMapNode_findNext(myNode, myIntMask) : 0; - } - - //! Query the iterated key. - int Key() const - { - Standard_NoSuchObject_Raise_if((myIntMask == ~0U), - "TColStd_MapIteratorOfPackedMapOfInteger::Key"); - return myKey; - } - - //! Return TRUE if iterator points to the node. - bool More() const { return myNode != nullptr; } - - //! Increment the iterator - void Next() - { - for (; myNode != nullptr; next()) - { - myKey = TColStd_intMapNode_findNext(myNode, myIntMask); - if (myIntMask != ~0u) - { - break; - } - } - } - - private: - //! Go to the next bucket in the map. - void next() - { - if (myBuckets == nullptr) - { - return; - } - - if (myNode != nullptr) - { - myNode = myNode->Next(); - } - - while (myNode == nullptr) - { - ++myBucket; - if (myBucket > myNbBuckets) - { - return; - } - myNode = myBuckets[myBucket]; - } - } - - private: - TColStd_intMapNode** myBuckets; - TColStd_intMapNode* myNode; - int myNbBuckets; - int myBucket; - - unsigned int myIntMask; //!< all bits set above the iterated position - int myKey; //!< Currently iterated key - }; - -public: - //! Constructor - TColStd_PackedMapOfInteger(const int theNbBuckets = 1) - : myData1(nullptr), - myNbBuckets(theNbBuckets), - myNbPackedMapNodes(0), - myExtent(0) - { - } - - //! Copy constructor - TColStd_PackedMapOfInteger(const TColStd_PackedMapOfInteger& theOther) - : myData1(nullptr), - myNbBuckets(1), - myNbPackedMapNodes(0), - myExtent(0) - { - Assign(theOther); - } - - inline TColStd_PackedMapOfInteger& operator=(const TColStd_PackedMapOfInteger& Other) - { - return Assign(Other); - } - - Standard_EXPORT TColStd_PackedMapOfInteger& Assign(const TColStd_PackedMapOfInteger&); - Standard_EXPORT void ReSize(const int NbBuckets); - Standard_EXPORT void Clear(); - - ~TColStd_PackedMapOfInteger() { Clear(); } - - Standard_EXPORT bool Add(const int aKey); - Standard_EXPORT bool Contains(const int aKey) const; - Standard_EXPORT bool Remove(const int aKey); - - //! Returns the number of map buckets (not that since integers are packed in this map, the number - //! is smaller than extent). - int NbBuckets() const { return myNbBuckets; } - - //! Returns map extent. - int Extent() const { return int(myExtent); } - - //! Returns TRUE if map is empty. - bool IsEmpty() const { return myNbPackedMapNodes == 0; } - - /** - * Query the minimal contained key value. - */ - Standard_EXPORT int GetMinimalMapped() const; - - /** - * Query the maximal contained key value. - */ - Standard_EXPORT int GetMaximalMapped() const; - - //! Prints useful statistics about the map. - //! It can be used to test the quality of the hashcoding. - Standard_EXPORT void Statistics(Standard_OStream& theStream) const; - -public: - //!@name Boolean operations with maps as sets of integers - //!@{ - - /** - * Sets this Map to be the result of union (aka addition, fuse, merge, boolean OR) operation - * between two given Maps. The new Map contains the values that are contained either in the first - * map or in the second map or in both. All previous contents of this Map is cleared. This map - * (result of the boolean operation) can also be passed as one of operands. - */ - Standard_EXPORT void Union(const TColStd_PackedMapOfInteger&, const TColStd_PackedMapOfInteger&); - - /** - * Apply to this Map the boolean operation union (aka addition, fuse, merge, boolean OR) with - * another (given) Map. The result contains the values that were previously contained in this map - * or contained in the given (operand) map. This algorithm is similar to method Union(). - * @return True if content of this map is changed - */ - Standard_EXPORT bool Unite(const TColStd_PackedMapOfInteger&); - - /** - * Overloaded operator version of Unite(). - */ - TColStd_PackedMapOfInteger& operator|=(const TColStd_PackedMapOfInteger& MM) - { - Unite(MM); - return *this; - } - - /** - * Sets this Map to be the result of intersection (aka multiplication, common, boolean AND) - * operation between two given Maps. The new Map contains only the values that are contained in - * both map operands. All previous contents of this Map is cleared. This same map (result of the - * boolean operation) can also be used as one of operands. The order of operands makes no - * difference; the method minimizes internally the number of iterations using the smallest map for - * the loop. - */ - Standard_EXPORT void Intersection(const TColStd_PackedMapOfInteger&, - const TColStd_PackedMapOfInteger&); - - /** - * Apply to this Map the intersection operation (aka multiplication, common, boolean AND) with - * another (given) Map. The result contains only the values that are contained in both this and - * the given maps. This algorithm is similar to method Intersection(). - * @return True if content of this map is changed - */ - Standard_EXPORT bool Intersect(const TColStd_PackedMapOfInteger&); - - /** - * Overloaded operator version of Intersect(). - */ - TColStd_PackedMapOfInteger& operator&=(const TColStd_PackedMapOfInteger& MM) - { - Intersect(MM); - return *this; - } - - /** - * Sets this Map to be the result of subtraction - * (aka set-theoretic difference, relative complement, exclude, cut, boolean NOT) operation - * between two given Maps. The new Map contains only the values that are contained in the first - * map operands and not contained in the second one. All previous contents of this Map is cleared. - * This map (result of the boolean operation) can also be used as the first operand. - */ - Standard_EXPORT void Subtraction(const TColStd_PackedMapOfInteger&, - const TColStd_PackedMapOfInteger&); - - /** - * Apply to this Map the subtraction (aka set-theoretic difference, relative complement, exclude, - * cut, boolean NOT) operation with another (given) Map. The result contains only the values that - * were previously contained in this map and not contained in this map. This algorithm is similar - * to method Subtract() with two operands. - * @return True if contents of this map is changed - */ - Standard_EXPORT bool Subtract(const TColStd_PackedMapOfInteger&); - - /** - * Overloaded operator version of Subtract(). - */ - TColStd_PackedMapOfInteger& operator-=(const TColStd_PackedMapOfInteger& MM) - { - Subtract(MM); - return *this; - } - - /** - * Sets this Map to be the result of symmetric difference (aka exclusive disjunction, boolean XOR) - * operation between two given Maps. The new Map contains the values that are contained only in - * the first or the second operand maps but not in both. All previous contents of this Map is - * cleared. This map (result of the boolean operation) can also be used as one of operands. - */ - Standard_EXPORT void Difference(const TColStd_PackedMapOfInteger&, - const TColStd_PackedMapOfInteger&); - - /** - * Apply to this Map the symmetric difference (aka exclusive disjunction, boolean XOR) operation - * with another (given) Map. The result contains the values that are contained only in this or the - * operand map, but not in both. This algorithm is similar to method Difference(). - * @return True if contents of this map is changed - */ - Standard_EXPORT bool Differ(const TColStd_PackedMapOfInteger&); - - /** - * Overloaded operator version of Differ(). - */ - TColStd_PackedMapOfInteger& operator^=(const TColStd_PackedMapOfInteger& MM) - { - Differ(MM); - return *this; - } - - /** - * Returns True if this map is equal to the given one, i.e. they contain the - * same sets of elements - */ - Standard_EXPORT bool IsEqual(const TColStd_PackedMapOfInteger&) const; - - /** - * Overloaded operator version of IsEqual(). - */ - bool operator==(const TColStd_PackedMapOfInteger& MM) const { return IsEqual(MM); } - - /** - * Returns True if this map is subset of the given one, i.e. all elements - * contained in this map is contained also in the operand map. - * if this map is empty that this method returns true for any operand map. - */ - Standard_EXPORT bool IsSubset(const TColStd_PackedMapOfInteger&) const; - - /** - * Overloaded operator version of IsSubset(). - */ - bool operator<=(const TColStd_PackedMapOfInteger& MM) const { return IsSubset(MM); } - - /** - * Returns True if this map has common items with the given one. - */ - Standard_EXPORT bool HasIntersection(const TColStd_PackedMapOfInteger&) const; - - //!@} - -protected: - //! Returns TRUE if resizing the map should be considered. - bool Resizable() const { return IsEmpty() || (myNbPackedMapNodes > myNbBuckets); } - - //! Return an integer index for specified key. - static int packedKeyIndex(int theKey) { return (unsigned)theKey >> 5; } - -private: - //! Find the smallest non-zero bit under the given mask. - //! Outputs the new mask that does not contain the detected bit. - Standard_EXPORT static int TColStd_intMapNode_findNext(const TColStd_intMapNode* theNode, - unsigned int& theMask); - - //! Find the highest non-zero bit under the given mask. - //! Outputs the new mask that does not contain the detected bit. - Standard_EXPORT static int TColStd_intMapNode_findPrev(const TColStd_intMapNode* theNode, - unsigned int& theMask); - - //! Compute the population (i.e., the number of non-zero bits) of the 32-bit word theData. - //! The population is stored decremented as it is defined in TColStd_intMapNode. - //! Source: H.S.Warren, Hacker's Delight, Addison-Wesley Inc. 2002, Ch.5.1 - static size_t TColStd_Population(unsigned int& theMask, unsigned int theData) - { - unsigned int aRes = theData - ((theData >> 1) & 0x55555555); - aRes = (aRes & 0x33333333) + ((aRes >> 2) & 0x33333333); - aRes = (aRes + (aRes >> 4)) & 0x0f0f0f0f; - aRes = aRes + (aRes >> 8); - aRes = aRes + (aRes >> 16); - theMask = (theMask & TColStd_PackedMapOfInteger::MASK_HIGH) - | ((aRes - 1) & TColStd_PackedMapOfInteger::MASK_LOW); - return size_t(aRes & 0x3f); - } - -private: - TColStd_intMapNode** myData1; //!< data array - int myNbBuckets; //!< number of buckets (size of data array) - int myNbPackedMapNodes; //!< amount of packed map nodes - // clang-format off - size_t myExtent; //!< extent of this map (number of unpacked integer keys) - // clang-format on -}; - -#endif +#endif // TColStd_PackedMapOfInteger_HeaderFile diff --git a/src/ModelingAlgorithms/TKMesh/IMeshData/IMeshData_Types.hxx b/src/ModelingAlgorithms/TKMesh/IMeshData/IMeshData_Types.hxx index f1a50085fe..7ac8d51114 100644 --- a/src/ModelingAlgorithms/TKMesh/IMeshData/IMeshData_Types.hxx +++ b/src/ModelingAlgorithms/TKMesh/IMeshData/IMeshData_Types.hxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -120,7 +120,7 @@ typedef NCollection_Shared> ListOfPnt2d; typedef NCollection_Shared> ListOfIPCurves; typedef NCollection_Shared MapOfInteger; -typedef TColStd_MapIteratorOfPackedMapOfInteger IteratorOfMapOfInteger; +typedef TColStd_PackedMapOfInteger::Iterator IteratorOfMapOfInteger; typedef NCollection_CellFilter CircleCellFilter; typedef NCollection_CellFilter VertexCellFilter; diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_CommonSensitiveEntity.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_CommonSensitiveEntity.cxx index 7cb6c272b8..bc95c2d140 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_CommonSensitiveEntity.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_CommonSensitiveEntity.cxx @@ -19,7 +19,6 @@ #include #include #include -#include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_CommonSensitiveEntity, Select3D_SensitiveSet) @@ -44,7 +43,7 @@ MeshVS_CommonSensitiveEntity::MeshVS_CommonSensitiveEntity( { int aNbSelectableNodes = 0; const TColStd_PackedMapOfInteger& anAllNodesMap = myDataSource->GetAllNodes(); - for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter(anAllNodesMap); aNodesIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aNodesIter(anAllNodesMap); aNodesIter.More(); aNodesIter.Next()) { const int aNodeIdx = aNodesIter.Key(); @@ -65,7 +64,7 @@ MeshVS_CommonSensitiveEntity::MeshVS_CommonSensitiveEntity( else if (mySelMethod == MeshVS_MSM_PRECISE) { const TColStd_PackedMapOfInteger& anAllNodesMap = myDataSource->GetAllNodes(); - for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter(anAllNodesMap); aNodesIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aNodesIter(anAllNodesMap); aNodesIter.More(); aNodesIter.Next()) { const int aNodeIdx = aNodesIter.Key(); @@ -77,7 +76,7 @@ MeshVS_CommonSensitiveEntity::MeshVS_CommonSensitiveEntity( const TColStd_PackedMapOfInteger& anAllElementsMap = myDataSource->GetAllElements(); MeshVS_EntityType aType = MeshVS_ET_NONE; - for (TColStd_MapIteratorOfPackedMapOfInteger anElemIter(anAllElementsMap); anElemIter.More(); + for (TColStd_PackedMapOfInteger::Iterator anElemIter(anAllElementsMap); anElemIter.More(); anElemIter.Next()) { const int anElemIdx = anElemIter.Key(); diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_DataSource.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_DataSource.cxx index 3236b46667..10edf16b74 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_DataSource.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_DataSource.cxx @@ -22,7 +22,7 @@ #include #include #include -#include +#include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_DataSource, Standard_Transient) @@ -289,11 +289,11 @@ Bnd_Box MeshVS_DataSource::GetBoundingBox() const const TColStd_PackedMapOfInteger& aNodes = GetAllNodes(); if (aNodes.Extent()) { - double aCoordsBuf[3]; - NCollection_Array1 aCoords(*aCoordsBuf, 1, 3); - int nbNodes; - MeshVS_EntityType aType; - TColStd_MapIteratorOfPackedMapOfInteger anIter(aNodes); + double aCoordsBuf[3]; + NCollection_Array1 aCoords(*aCoordsBuf, 1, 3); + int nbNodes; + MeshVS_EntityType aType; + TColStd_PackedMapOfInteger::Iterator anIter(aNodes); for (; anIter.More(); anIter.Next()) { int aKey = anIter.Key(); diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx index f83844e209..798fd82ee6 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_ElementalColorPrsBuilder.cxx @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_ElementalColorPrsBuilder, MeshVS_PrsBuilder) @@ -94,8 +94,8 @@ void MeshVS_ElementalColorPrsBuilder::Build(const occ::handle aHiddenElems = myParentMesh->GetHiddenElems(); if (!aHiddenElems.IsNull()) - anIDs.Subtract(aHiddenElems->Map()); - anIDs.Subtract(IDsToExclude); + NCollection_PackedMapAlgo::Subtract(anIDs, aHiddenElems->Map()); + NCollection_PackedMapAlgo::Subtract(anIDs, IDsToExclude); // STEP 0: We looking for two colored elements, who has equal two colors and move it // to map of elements with one assigned color @@ -200,8 +200,8 @@ void MeshVS_ElementalColorPrsBuilder::Build(const occ::handle>> aTopo; - int PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0; - TColStd_MapIteratorOfPackedMapOfInteger it(anIDs); + int PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0; + TColStd_PackedMapOfInteger::Iterator it(anIDs); for (; it.More(); it.Next()) { int aKey = it.Key(); diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_Mesh.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_Mesh.cxx index 5e73079807..005994579e 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_Mesh.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_Mesh.cxx @@ -53,7 +53,8 @@ #include #include #include -#include +#include +#include class SelectMgr_EntityOwner; IMPLEMENT_STANDARD_RTTIEXT(MeshVS_Mesh, AIS_InteractiveObject) @@ -221,7 +222,7 @@ void MeshVS_Mesh::scanFacesForSharedNodes(const TColStd_PackedMapOfInteger& theA int aNbNodes; MeshVS_Buffer aCoordsBuf(3 * theNbMaxFaceNodes * sizeof(double)); NCollection_Array1 aCoords(aCoordsBuf, 1, 3 * theNbMaxFaceNodes); - for (TColStd_MapIteratorOfPackedMapOfInteger aFaceIter(theAllElements); aFaceIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aFaceIter(theAllElements); aFaceIter.More(); aFaceIter.Next()) { const int aFaceIdx = aFaceIter.Key(); @@ -321,7 +322,7 @@ void MeshVS_Mesh::ComputeSelection(const occ::handle& theSe { case MeshVS_SMF_Node: { myNodeOwners.Clear(); - for (TColStd_MapIteratorOfPackedMapOfInteger anIter(anAllNodesMap); anIter.More(); + for (TColStd_PackedMapOfInteger::Iterator anIter(anAllNodesMap); anIter.More(); anIter.Next()) { const int aKey = anIter.Key(); @@ -383,7 +384,7 @@ void MeshVS_Mesh::ComputeSelection(const occ::handle& theSe // create sensitive entities for free edges, if there are any int aNbNodes = 0; MeshVS_EntityType aType = MeshVS_ET_NONE; - for (TColStd_MapIteratorOfPackedMapOfInteger anElemIter(anAllElementsMap); + for (TColStd_PackedMapOfInteger::Iterator anElemIter(anAllElementsMap); anElemIter.More(); anElemIter.Next()) { @@ -426,8 +427,7 @@ void MeshVS_Mesh::ComputeSelection(const occ::handle& theSe } // create sensitive entities for free nodes, if there are any - for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter(anAllNodesMap); - aNodesIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aNodesIter(anAllNodesMap); aNodesIter.More(); aNodesIter.Next()) { const int aNodeIdx = aNodesIter.Key(); @@ -452,7 +452,7 @@ void MeshVS_Mesh::ComputeSelection(const occ::handle& theSe aSource->GetAllGroups(anAllGroupsMap); occ::handle>> aTopo; - for (TColStd_MapIteratorOfPackedMapOfInteger anIter(anAllGroupsMap); anIter.More(); + for (TColStd_PackedMapOfInteger::Iterator anIter(anAllGroupsMap); anIter.More(); anIter.Next()) { const int aKeyGroup = anIter.Key(); @@ -493,7 +493,7 @@ void MeshVS_Mesh::ComputeSelection(const occ::handle& theSe bool added = false; int aNbNodes = 0; MeshVS_EntityType aType = MeshVS_ET_NONE; - for (TColStd_MapIteratorOfPackedMapOfInteger anIterMG(aGroupMap); anIterMG.More(); + for (TColStd_PackedMapOfInteger::Iterator anIterMG(aGroupMap); anIterMG.More(); anIterMG.Next()) { int aKey = anIterMG.Key(); @@ -587,7 +587,7 @@ void MeshVS_Mesh::ComputeSelection(const occ::handle& theSe int aNbNodes = 0; MeshVS_EntityType aType = MeshVS_ET_NONE; - for (TColStd_MapIteratorOfPackedMapOfInteger anIterMV(anAllElementsMap); anIterMV.More(); + for (TColStd_PackedMapOfInteger::Iterator anIterMV(anAllElementsMap); anIterMV.More(); anIterMV.Next()) { int aKey = anIterMV.Key(); @@ -967,13 +967,13 @@ void MeshVS_Mesh::HilightSelected( { if (aGroupType == MeshVS_ET_Node) { - for (TColStd_MapIteratorOfPackedMapOfInteger anIt(aGroupMap); anIt.More(); anIt.Next()) + for (TColStd_PackedMapOfInteger::Iterator anIt(aGroupMap); anIt.More(); anIt.Next()) if (IsSelectableNode /*!IsHiddenNode*/ (anIt.Key())) aSelNodes.Add(anIt.Key()); } else { - for (TColStd_MapIteratorOfPackedMapOfInteger anIt(aGroupMap); anIt.More(); anIt.Next()) + for (TColStd_PackedMapOfInteger::Iterator anIt(aGroupMap); anIt.More(); anIt.Next()) if (IsSelectableElem /*!IsHiddenElem*/ (anIt.Key())) aSelElements.Add(anIt.Key()); } @@ -1004,12 +1004,12 @@ void MeshVS_Mesh::HilightSelected( // agv else if( theOwners.Value ( i )==myWholeMeshOwner ) else if (IsWholeMeshOwner(theOwners.Value(i))) { - TColStd_MapIteratorOfPackedMapOfInteger anIt(GetDataSource()->GetAllNodes()); + TColStd_PackedMapOfInteger::Iterator anIt(GetDataSource()->GetAllNodes()); for (; anIt.More(); anIt.Next()) if (!IsHiddenNode(anIt.Key())) aSelNodes.Add(anIt.Key()); - anIt = TColStd_MapIteratorOfPackedMapOfInteger(GetDataSource()->GetAllElements()); + anIt = TColStd_PackedMapOfInteger::Iterator(GetDataSource()->GetAllElements()); for (; anIt.More(); anIt.Next()) if (!IsHiddenElem(anIt.Key())) aSelElements.Add(anIt.Key()); @@ -1306,11 +1306,13 @@ void MeshVS_Mesh::UpdateSelectableNodes() // by default (i.e. if myHiddenNodes.IsNull()) all nodes are hidden if (!myHiddenNodes.IsNull()) { - mySelectableNodes->ChangeMap().Subtraction(aSource->GetAllNodes(), myHiddenNodes->Map()); + NCollection_PackedMapAlgo::Subtraction(mySelectableNodes->ChangeMap(), + aSource->GetAllNodes(), + myHiddenNodes->Map()); } // add all nodes belonging to non-hidden elements - TColStd_MapIteratorOfPackedMapOfInteger anIter(aSource->GetAllElements()); + TColStd_PackedMapOfInteger::Iterator anIter(aSource->GetAllElements()); for (; anIter.More(); anIter.Next()) { int aKey = anIter.Key(); diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshOwner.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshOwner.cxx index b55bc8c634..673adeb469 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshOwner.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshOwner.cxx @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_MeshOwner, SelectMgr_EntityOwner) @@ -68,11 +69,11 @@ void MeshVS_MeshOwner::AddSelectedEntities(const occ::handleChangeMap().Unite(Nodes->Map()); + NCollection_PackedMapAlgo::Unite(mySelectedNodes->ChangeMap(), Nodes->Map()); if (mySelectedElems.IsNull()) mySelectedElems = Elems; else if (!Elems.IsNull()) - mySelectedElems->ChangeMap().Unite(Elems->Map()); + NCollection_PackedMapAlgo::Unite(mySelectedElems->ChangeMap(), Elems->Map()); } //================================================================================================= @@ -125,7 +126,7 @@ void MeshVS_MeshOwner::HilightWithColor(const occ::handle aElems = GetDetectedElements(); if (!aNodes.IsNull() && aNodes->Map().Extent() == 1) { - TColStd_MapIteratorOfPackedMapOfInteger anIt(aNodes->Map()); + TColStd_PackedMapOfInteger::Iterator anIt(aNodes->Map()); if (myLastID != anIt.Key()) { myLastID = anIt.Key(); @@ -133,7 +134,7 @@ void MeshVS_MeshOwner::HilightWithColor(const occ::handleMap().Extent() == 1) { - TColStd_MapIteratorOfPackedMapOfInteger anIt(aElems->Map()); + TColStd_PackedMapOfInteger::Iterator anIt(aElems->Map()); if (myLastID != anIt.Key()) { myLastID = anIt.Key(); @@ -170,7 +171,7 @@ bool MeshVS_MeshOwner::IsForcedHilight() const occ::handle aNodes = GetDetectedNodes(); if (!aNodes.IsNull() && aNodes->Map().Extent() == 1) { - TColStd_MapIteratorOfPackedMapOfInteger anIt(aNodes->Map()); + TColStd_PackedMapOfInteger::Iterator anIt(aNodes->Map()); aKey = anIt.Key(); if (myLastID == aKey) { @@ -180,7 +181,7 @@ bool MeshVS_MeshOwner::IsForcedHilight() const occ::handle aElems = GetDetectedElements(); if (!aElems.IsNull() && aElems->Map().Extent() == 1) { - TColStd_MapIteratorOfPackedMapOfInteger anIt(aElems->Map()); + TColStd_PackedMapOfInteger::Iterator anIt(aElems->Map()); aKey = anIt.Key(); if (myLastID == aKey) { diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshPrsBuilder.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshPrsBuilder.cxx index 80659b54ca..28b8d2f210 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshPrsBuilder.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_MeshPrsBuilder.cxx @@ -39,8 +39,8 @@ #include #include #include -#include #include +#include #include #ifdef _WIN32 @@ -192,17 +192,17 @@ void MeshVS_MeshPrsBuilder::BuildNodes(const occ::handle& Pr // subtract the hidden nodes and ids to exclude (to minimize allocated memory) occ::handle aHiddenNodes = myParentMesh->GetHiddenNodes(); if (!aHiddenNodes.IsNull()) - anIDs.Subtract(aHiddenNodes->Map()); + NCollection_PackedMapAlgo::Subtract(anIDs, aHiddenNodes->Map()); } - anIDs.Subtract(IDsToExclude); + NCollection_PackedMapAlgo::Subtract(anIDs, IDsToExclude); int upper = anIDs.Extent(); if (upper <= 0) return; - occ::handle aNodePoints = new Graphic3d_ArrayOfPoints(upper); - int k = 0; - TColStd_MapIteratorOfPackedMapOfInteger it(anIDs); + occ::handle aNodePoints = new Graphic3d_ArrayOfPoints(upper); + int k = 0; + TColStd_PackedMapOfInteger::Iterator it(anIDs); for (; it.More(); it.Next()) { int aKey = it.Key(); @@ -290,11 +290,11 @@ void MeshVS_MeshPrsBuilder::BuildElements(const occ::handle& anIDs.Assign(IDs); occ::handle aHiddenElems = myParentMesh->GetHiddenElems(); if (!aHiddenElems.IsNull()) - anIDs.Subtract(aHiddenElems->Map()); - anIDs.Subtract(IDsToExclude); + NCollection_PackedMapAlgo::Subtract(anIDs, aHiddenElems->Map()); + NCollection_PackedMapAlgo::Subtract(anIDs, IDsToExclude); occ::handle>> aTopo; - TColStd_MapIteratorOfPackedMapOfInteger it(anIDs); + TColStd_PackedMapOfInteger::Iterator it(anIDs); bool showEdges = true; aDrawer->GetBoolean(MeshVS_DA_ShowEdges, showEdges); @@ -621,9 +621,9 @@ void MeshVS_MeshPrsBuilder::BuildHilightPrs(const occ::handle aNodeMark = MeshVS_Tool::CreateAspectMarker3d(GetDrawer()); // Hilight one element or node - TColStd_MapIteratorOfPackedMapOfInteger it(IDs); - int ID = it.Key(), NbNodes; - MeshVS_EntityType aType; + TColStd_PackedMapOfInteger::Iterator it(IDs); + int ID = it.Key(), NbNodes; + MeshVS_EntityType aType; if (!aSource->GetGeom(ID, IsElement, aCoords, NbNodes, aType)) return; diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_NodalColorPrsBuilder.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_NodalColorPrsBuilder.cxx index 515a17c723..7d4b98a152 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_NodalColorPrsBuilder.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_NodalColorPrsBuilder.cxx @@ -45,7 +45,8 @@ #include #include #include -#include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_NodalColorPrsBuilder, MeshVS_PrsBuilder) @@ -138,8 +139,8 @@ void MeshVS_NodalColorPrsBuilder::Build(const occ::handle& P anIDs.Assign(IDs); occ::handle aHiddenElems = myParentMesh->GetHiddenElems(); if (!aHiddenElems.IsNull()) - anIDs.Subtract(aHiddenElems->Map()); - anIDs.Subtract(IDsToExclude); + NCollection_PackedMapAlgo::Subtract(anIDs, aHiddenElems->Map()); + NCollection_PackedMapAlgo::Subtract(anIDs, IDsToExclude); bool IsReflect = false, IsMeshSmoothShading = false; aDrawer->GetBoolean(MeshVS_DA_ColorReflection, IsReflect); @@ -158,8 +159,8 @@ void MeshVS_NodalColorPrsBuilder::Build(const occ::handle& P // Calculate maximum possible number of vertices and bounds occ::handle>> aTopo; - int PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0; - TColStd_MapIteratorOfPackedMapOfInteger it(anIDs); + int PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0; + TColStd_PackedMapOfInteger::Iterator it(anIDs); for (; it.More(); it.Next()) { int aKey = it.Key(); diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_TextPrsBuilder.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_TextPrsBuilder.cxx index 6b25e0846d..3c31ffe18f 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_TextPrsBuilder.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_TextPrsBuilder.cxx @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_TextPrsBuilder, MeshVS_PrsBuilder) @@ -190,12 +191,12 @@ void MeshVS_TextPrsBuilder::Build(const occ::handle& Prs, { occ::handle aHiddenElems = myParentMesh->GetHiddenElems(); if (!aHiddenElems.IsNull()) - anIDs.Subtract(aHiddenElems->Map()); + NCollection_PackedMapAlgo::Subtract(anIDs, aHiddenElems->Map()); } - anIDs.Subtract(IDsToExclude); + NCollection_PackedMapAlgo::Subtract(anIDs, IDsToExclude); NCollection_Sequence> aPnts; - for (TColStd_MapIteratorOfPackedMapOfInteger it(anIDs); it.More(); it.Next()) + for (TColStd_PackedMapOfInteger::Iterator it(anIDs); it.More(); it.Next()) { int aKey = it.Key(); if (GetText(IsElement, aKey, aStr)) diff --git a/src/Visualization/TKMeshVS/MeshVS/MeshVS_VectorPrsBuilder.cxx b/src/Visualization/TKMeshVS/MeshVS/MeshVS_VectorPrsBuilder.cxx index 2252194b5d..56acd2208f 100644 --- a/src/Visualization/TKMeshVS/MeshVS/MeshVS_VectorPrsBuilder.cxx +++ b/src/Visualization/TKMeshVS/MeshVS/MeshVS_VectorPrsBuilder.cxx @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(MeshVS_VectorPrsBuilder, MeshVS_PrsBuilder) @@ -225,11 +226,11 @@ void MeshVS_VectorPrsBuilder::Build(const occ::handle& Prs, { occ::handle aHiddenElems = myParentMesh->GetHiddenElems(); if (!aHiddenElems.IsNull()) - anIDs.Subtract(aHiddenElems->Map()); + NCollection_PackedMapAlgo::Subtract(anIDs, aHiddenElems->Map()); } - anIDs.Subtract(IDsToExclude); + NCollection_PackedMapAlgo::Subtract(anIDs, IDsToExclude); - TColStd_MapIteratorOfPackedMapOfInteger it(anIDs); + TColStd_PackedMapOfInteger::Iterator it(anIDs); for (; it.More(); it.Next()) { int aKey = it.Key(); diff --git a/src/Visualization/TKService/Image/Image_Diff.cxx b/src/Visualization/TKService/Image/Image_Diff.cxx index 7140ca2608..dcb5ad2d7a 100644 --- a/src/Visualization/TKService/Image/Image_Diff.cxx +++ b/src/Visualization/TKService/Image/Image_Diff.cxx @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include @@ -322,7 +322,7 @@ bool Image_Diff::SaveDiffImage(Image_PixMap& theDiffImage) const { case Image_Format_Gray: case Image_Format_Alpha: { - for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter(aGroup->Map()); aPixelIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aPixelIter(aGroup->Map()); aPixelIter.More(); aPixelIter.Next()) { int aDiffPixel(aPixelIter.Key()); @@ -336,7 +336,7 @@ bool Image_Diff::SaveDiffImage(Image_PixMap& theDiffImage) const case Image_Format_BGR32: case Image_Format_RGBA: case Image_Format_BGRA: { - for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter(aGroup->Map()); aPixelIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aPixelIter(aGroup->Map()); aPixelIter.More(); aPixelIter.Next()) { int aDiffPixel(aPixelIter.Key()); @@ -347,7 +347,7 @@ bool Image_Diff::SaveDiffImage(Image_PixMap& theDiffImage) const break; } default: { - for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter(aGroup->Map()); aPixelIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aPixelIter(aGroup->Map()); aPixelIter.More(); aPixelIter.Next()) { int aDiffPixel(aPixelIter.Key()); @@ -462,7 +462,7 @@ int Image_Diff::ignoreBorderEffect() } int aDiffPixel = 0; - for (TColStd_MapIteratorOfPackedMapOfInteger aPixelIter(aGroup->Map()); aPixelIter.More(); + for (TColStd_PackedMapOfInteger::Iterator aPixelIter(aGroup->Map()); aPixelIter.More(); aPixelIter.Next()) { aDiffPixel = aPixelIter.Key(); diff --git a/src/Visualization/TKV3d/Select3D/Select3D_SensitivePrimitiveArray.cxx b/src/Visualization/TKV3d/Select3D/Select3D_SensitivePrimitiveArray.cxx index 9f47c9e14e..d43eb13d99 100644 --- a/src/Visualization/TKV3d/Select3D/Select3D_SensitivePrimitiveArray.cxx +++ b/src/Visualization/TKV3d/Select3D/Select3D_SensitivePrimitiveArray.cxx @@ -15,6 +15,7 @@ #include +#include #include #include @@ -906,11 +907,13 @@ bool Select3D_SensitivePrimitiveArray::Matches(SelectBasics_SelectingVolumeManag hasResults = true; if (!myDetectedElemMap.IsNull()) { - myDetectedElemMap->ChangeMap().Unite(aChild->myDetectedElemMap->Map()); + NCollection_PackedMapAlgo::Unite(myDetectedElemMap->ChangeMap(), + aChild->myDetectedElemMap->Map()); } if (!myDetectedNodeMap.IsNull()) { - myDetectedNodeMap->ChangeMap().Unite(aChild->myDetectedNodeMap->Map()); + NCollection_PackedMapAlgo::Unite(myDetectedNodeMap->ChangeMap(), + aChild->myDetectedNodeMap->Map()); } if (thePickResult.Depth() > aPickResult.Depth()) {