26 #ifndef UNORDEREDSETBYBLOCK_HPP
27 #define UNORDEREDSETBYBLOCK_HPP
29 #include <unordered_map>
30 #include <boost/iterator/iterator_facade.hpp>
32 #include "DGtal/base/Common.h"
33 #include "DGtal/base/Bits.h"
34 #include "DGtal/kernel/CUnsignedNumber.h"
35 #include "DGtal/kernel/CBoundedNumber.h"
36 #include "DGtal/kernel/PointVector.h"
37 #include "DGtal/kernel/PointHashFunctions.h"
66 template <
typename TElement,
typename TWord = u
int32_t >
84 std::pair< Element, Coordinate >
88 ( e[ 0 ] &
static_cast<Coordinate>(
sizeof(
Word ) * CHAR_BIT - 1 ) );
89 e[ 0 ] -= block_coords;
90 return { e, block_coords };
115 join(
const std::pair< Element, Coordinate >& p )
155 template <
typename Key,
157 class Hash = std::hash<Key>,
158 class KeyEqual = std::equal_to<Key>,
159 class UnorderedMapAllocator = std::allocator<
160 std::pair<const Key, typename TSplitter::Word >
169 typedef std::unordered_map< Key,
Word, Hash, KeyEqual,
201 :
public boost::iterator_facade< const_iterator, Key const,
202 boost::forward_traversal_tag,
258 -
static_cast<Word>(1) );
272 &&
"Invalid increment on const_iterator" );
306 typename Container::const_iterator
it;
316 :
public boost::iterator_facade< iterator, Key const,
317 boost::forward_traversal_tag,
355 -
static_cast<Word>(1) );
375 -
static_cast<Word>(1) );
395 it( std::move( other.
it ) ),
396 bit( std::move( other.
bit ) ),
412 &&
"Invalid increment on iterator" );
455 typename Container::iterator
it;
476 const Hash& hash = Hash(),
478 const UnorderedMapAllocator& alloc = UnorderedMapAllocator())
507 if (
this != &other )
522 my_size = std::move( other.my_size );
547 return const_iterator( *
this,
my_elements.cbegin() );
550 const_iterator
end()
const
552 return const_iterator( *
this,
my_elements.cend() );
558 return const_iterator( *
this,
my_elements.cbegin() );
563 return const_iterator( *
this,
my_elements.cend() );
590 mem +=
blocks() * (
sizeof(
void* )
605 mem +=
size() * (
sizeof(
void* )
640 std::swap(
my_size, other.my_size );
663 ( std::make_pair( se.first,
664 static_cast<Word>(1) << se.second ) );
666 return std::make_pair( iterator( *
this, p.first, se.second ),
true );
670 bool exist = it->second & (
static_cast<Word>(1) << se.second );
673 it->second |=
static_cast<Word>(1) << se.second;
676 return std::make_pair( iterator( *
this, it, se.second ), ! exist );
693 template<
typename... _Args>
694 std::pair<iterator, bool>
697 const auto se =
my_splitter.split( Key( std::forward<_Args>(__args)... ) );
703 static_cast<Word>(1) << se.second ) );
705 return std::make_pair( iterator( *
this, p.first, se.second ),
true );
709 bool exist = it->second & (
static_cast<Word>(1) << se.second );
712 it->second |=
static_cast<Word>(1) << se.second;
715 return std::make_pair( iterator( *
this, it, se.second ), ! exist );
730 iterator
erase( const_iterator pos ) noexcept
732 ASSERT(
this == pos.collection );
733 ASSERT( pos !=
cend() );
734 ASSERT( ( pos.it->second & (
static_cast<Word>(1) << pos.bit ) )
735 !=
static_cast<Word>(0) );
737 Word & w =
const_cast< Word&
>( pos.it->second );
738 if ( ( w &= ~(
static_cast<Word>(1) << pos.bit ) )
739 ==
static_cast<Word>(0) )
740 return iterator( *
this,
my_elements.erase( pos.it ) );
742 return iterator( *
this,
my_elements.erase( pos.it, pos.it ), pos.bit );
760 iterator
erase( const_iterator first, const_iterator last ) noexcept
762 ASSERT(
this == first.collection );
763 ASSERT(
this == last.collection );
764 if ( first ==
cend() )
return end();
771 while ( first != last )
773 mask |=
static_cast<Word>(1) << first.bit;
778 return iterator( *
this,
783 while ( first.it == itB )
785 mask |=
static_cast<Word>(1) << first.bit;
791 ==
static_cast<Word>(0) )
794 for ( itB = first.it; itB != itE; ++itB )
801 first = const_iterator( *
this, itB );
802 mask =
static_cast<Word>(0);
803 while ( first != last )
805 mask |=
static_cast<Word>(1) << first.bit;
811 ==
static_cast<Word>(0) )
813 return iterator( *
this,
827 auto it =
find( key );
848 iterator
find(
const Key& key )
853 const bool exist = it->second & (
static_cast<Word>(1) << se.second );
854 if ( exist )
return iterator( *
this, it, se.second );
863 const_iterator
find(
const Key& key )
const
868 const bool exist = it->second & (
static_cast<Word>(1) << se.second );
869 if ( exist )
return const_iterator( *
this, it, se.second );
882 const bool exist = it->second & (
static_cast<Word>(1) << se.second );
883 return exist ? 1 : 0;
894 std::pair<iterator,iterator>
897 iterator first =
find( key );
898 if ( first !=
end() )
900 iterator last = first;
901 return std::make_pair( first, ++last );
903 else return std::make_pair( first, first );
914 std::pair<const_iterator,const_iterator>
917 const_iterator first =
find( key );
918 if ( first !=
end() )
920 const_iterator last = first;
921 return std::make_pair( first, ++last );
923 else return std::make_pair( first, first );
952 const auto itEndMap_other = other.
my_elements.cend();
954 for ( ; itMap_other != itEndMap_other; ++itMap_other )
956 const auto itMap_this =
my_elements.find( itMap_other->first );
957 if ( itMap_this == itEndMap_this )
return false;
958 const Word w_this = itMap_this->second;
959 const Word w_other = itMap_other->second;
960 if ( ( w_this & w_other ) != w_other )
return false;
973 <<
" #other=" << other.
size() << std::endl;
975 const auto itEndMap_other = other.
my_elements.cend();
977 for ( ; itMap_other != itEndMap_other; ++itMap_other )
979 trace.
info() <<
"other: cell=" << itMap_other->first
980 <<
" value=" << std::hex << itMap_other->second << std::endl;
981 const auto itMap_this =
my_elements.find( itMap_other->first );
982 if ( itMap_this != itEndMap_this )
983 trace.
info() <<
"this : cell=" << itMap_this->first
984 <<
" value=" << std::hex << itMap_this->second << std::endl;
986 trace.
info() <<
"this : end cell" << std::endl;
987 if ( itMap_this == itEndMap_this )
return false;
988 const Word w_this = itMap_this->second;
989 const Word w_other = itMap_other->second;
990 if ( ( w_this & w_other ) != w_other )
return false;
1002 auto it_other = other.
cbegin();
1003 auto itEnd_other = other.
cend();
1004 while ( it_other != itEnd_other )
1006 const auto it_this =
find( *it_other );
1007 if ( it_this ==
cend() )
return false;
1008 auto itMap_other = it_other.it;
1009 const Word w_this = it_this.it->second;
1010 const Word w_other = itMap_other->second;
1011 if ( ( w_this & w_other ) != w_other )
return false;
1012 it_other = const_iterator( other, ++itMap_other );
1027 <<
" #other=" << other.
size() << std::endl;
1028 auto it_other = other.
cbegin();
1029 auto itEnd_other = other.
cend();
1030 while ( it_other != itEnd_other )
1032 trace.
info() <<
"other: cell=" << it_other.it->first
1033 <<
" value=" << std::hex << it_other.it->second << std::endl;
1034 const auto it_this =
find( *it_other );
1035 if ( it_this !=
cend() )
1036 trace.
info() <<
"this : cell=" << it_this.it->first
1037 <<
" value=" << std::hex << it_this.it->second << std::endl;
1039 trace.
info() <<
"this : end cell" << std::endl;
1040 if ( it_this ==
cend() )
return false;
1041 auto itMap_other = it_other.it;
1042 const Word w_this = it_this.it->second;
1043 const Word w_other = itMap_other->second;
1044 if ( ( w_this & w_other ) != w_other )
return false;
1045 it_other = const_iterator( other, ++itMap_other );
1094 template <
typename Key,
1098 class UnorderedMapAllocator >
1109 #endif // #ifndef UNORDEREDSETBYBLOCK_HPP