From 17810a58bf3fe40106d4dda4bec29e509b657cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Thu, 9 Nov 2017 09:36:06 +0100 Subject: [PATCH] Sets - Index-backed implementation --- Sets-inline.hh | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ Sets.hh | 12 ++++- 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/Sets-inline.hh b/Sets-inline.hh index 95599e3..544196f 100644 --- a/Sets-inline.hh +++ b/Sets-inline.hh @@ -212,6 +212,139 @@ M_TMPL_ void M_TYPE_::clear( ) noexcept #undef M_TYPE_ +/*= SET IMPLEMENTATION - INDEX ===============================================*/ + +template< + typename Type , + uint32_t InitialSize , + uint32_t HashSize , + uint32_t Growth +> class T_SetImplementation< Type , IndexBacked< InitialSize , HashSize , Growth > > +{ + static_assert( InitialSize > 0 , "invalid initial size" ); + static_assert( HashSize > 0 , "invalid hash array size" ); + static_assert( Growth > 0 , "invalid growth" ); + + private: + T_HashIndex index_{ HashSize , InitialSize , Growth }; + T_Array< Type > items_{ Growth }; + + public: + uint32_t size( ) const noexcept; + int32_t indexOf( Type const& item ) const noexcept; + Type const* access( uint32_t item ) const noexcept; + + bool add( Type const& item ) noexcept; + bool add( Type&& item ) noexcept; + bool remove( Type const& item ) noexcept; + + void free( ) noexcept; + void clear( ) noexcept; + + private: + uint32_t find( Type const& k , + const uint32_t hash ) const noexcept; +}; + +/*----------------------------------------------------------------------------*/ + +#define M_TMPL_ template< typename Type , uint32_t ISize , uint32_t HSize , uint32_t Growth > +#define M_TYPE_ T_SetImplementation< Type , IndexBacked< ISize , HSize , Growth > > + +M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept +{ + return items_.size( ); +} + +M_TMPL_ int32_t M_TYPE_::indexOf( + Type const& item ) const noexcept +{ + const auto idx{ find( item , ComputeHash( item ) ) }; + return idx == T_HashIndex::INVALID_INDEX ? -1 : int32_t( idx ); +} + +M_TMPL_ Type const* M_TYPE_::access( + const uint32_t item ) const noexcept +{ + return &items_[ item ]; +} + +/*----------------------------------------------------------------------------*/ + +M_TMPL_ bool M_TYPE_::add( + Type const& item ) noexcept +{ + const auto hash{ ComputeHash( item ) }; + const auto idx{ find( item , hash ) }; + if ( idx == T_HashIndex::INVALID_INDEX ) { + index_.add( hash ); + items_.add( item ); + } + return idx == T_HashIndex::INVALID_INDEX; +} + +M_TMPL_ bool M_TYPE_::add( + Type&& item ) noexcept +{ + const auto hash{ ComputeHash( item ) }; + const auto idx{ find( item , hash ) }; + if ( idx == T_HashIndex::INVALID_INDEX ) { + index_.add( hash ); + items_.add( std::move( item ) ); + } + return idx == T_HashIndex::INVALID_INDEX; +} + +M_TMPL_ bool M_TYPE_::remove( + Type const& item ) noexcept +{ + const auto hash{ ComputeHash( item ) }; + const auto idx{ find( item , hash ) }; + if ( idx != T_HashIndex::INVALID_INDEX ) { + items_.removeSwap( idx ); + index_.remove( idx ); + } + return idx != T_HashIndex::INVALID_INDEX; +} + +/*----------------------------------------------------------------------------*/ + +M_TMPL_ void M_TYPE_::free( ) noexcept +{ + index_.free( ); + items_.free( ); +} + +M_TMPL_ void M_TYPE_::clear( ) noexcept +{ + index_.clear( ); + items_.clear( ); +} + +/*----------------------------------------------------------------------------*/ + +M_TMPL_ uint32_t M_TYPE_::find( + Type const& k , + const uint32_t hash ) const noexcept +{ + uint32_t idx = index_.first( hash ); + while ( idx != T_HashIndex::INVALID_INDEX ) { + // XXX use a match function? +// if ( match_( keys_[ idx ] , k ) ) { +// break; +// } + if ( items_[ idx ] == k ) { + break; + } + idx = index_.next( idx ); + } + return idx; +} + +#undef M_TMPL_ +#undef M_TYPE_ + + /*= COMMON HANDLER ===========================================================*/ // In-place version diff --git a/Sets.hh b/Sets.hh index f8836fc..d15b9ed 100644 --- a/Sets.hh +++ b/Sets.hh @@ -5,6 +5,7 @@ #ifndef _H_EBCL_SETS #define _H_EBCL_SETS #include +#include namespace ebcl { // FIXME move this to utilities \/ @@ -41,7 +42,14 @@ M_DEFINE_TEMPLATE_TAG( ArrayBacked , uint32_t InPlace , uint32_t Growth = 0 ); -//M_DEFINE_TAG( IndexBacked ); + +// IndexBacked implementation tag - the implementation will use a +// T_HashIndex and an array. InitialSize and HashSize affect the index, +// Growth affects both the index and the array. +M_DEFINE_TEMPLATE_TAG( IndexBacked , + uint32_t InitialSize = T_HashIndex::DEFAULT_SIZE , + uint32_t HashSize = T_HashIndex::DEFAULT_SIZE , + uint32_t Growth = T_HashIndex::DEFAULT_GROWTH ); // Templated horrors used by the main T_Set class. @@ -49,7 +57,7 @@ struct T_SetHelper { // Default implementation to use; also determines the in-place // storage size - using DefaultImplementation = ArrayBacked< 8 >; // FIXME should use Index by default + using DefaultImplementation = IndexBacked< >; // Default implementation class template< typename Type