00001 /* ******************************************************************************* 00002 * Copyright (c) 2007-2014, Intel Corporation 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * 00007 * * Redistributions of source code must retain the above copyright notice, 00008 * this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of Intel Corporation nor the names of its contributors 00013 * may be used to endorse or promote products derived from this software 00014 * without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 00020 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00021 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00022 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00023 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00024 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00025 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 ********************************************************************************/ 00027 00028 /* 00029 hashing and comparing tags and items. 00030 */ 00031 00032 #ifndef _TAG_HASH_COMPARE_HH_ALREADY_INCLUDED 00033 #define _TAG_HASH_COMPARE_HH_ALREADY_INCLUDED 00034 00035 #include <string> 00036 #include <vector> 00037 #include <cnc/internal/cnc_stddef.h> 00038 #include <cstring> 00039 #include <tbb/concurrent_hash_map.h> 00040 00041 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00042 00043 /// \brief Provides hash operators for hashing 00044 /// 00045 /// Specializations for custom data types must implement 00046 /// hash and equal to work with preserving tag-collections (CnC::preserve_tuner) 00047 /// and/or (default) CnC::item_collection using hashmaps. 00048 /// 00049 /// Standard data types are supported out-of-the-box as 00050 /// well as std::vector and std:pair thereof, char*, std::string 00051 /// and pointers (which you better avoid if ever possible, because it 00052 /// pointers as tags are not portable, e.g. to distributed memory). 00053 /// \return a unique integer for the given tag 00054 template< typename T > 00055 struct cnc_hash : public tbb::tbb_hash< T > 00056 { 00057 }; 00058 00059 /// \brief Provides equality operators for hashing 00060 /// 00061 /// Specializations for custom data types must implement 00062 /// hash and equal to work with preserving tag-collections (CnC::preserve_tuner) 00063 /// and/or (default) CnC::item_collection using hashmaps. 00064 /// 00065 /// Standard data types are supported out-of-the-box as 00066 /// well as std::vector and std:pair thereof, char*, std::string 00067 /// and pointers (which you better avoid if ever possible, because it 00068 /// pointers as tags are not portable, e.g. to distributed memory). 00069 /// \return true if a equals b, false otherwise 00070 template< typename T > 00071 struct cnc_equal : public std::equal_to< T > 00072 { 00073 }; 00074 00075 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00076 00077 // \brief hash for pointer types, but you better avoid tags being pointers 00078 template< class T > 00079 struct cnc_hash< T* > 00080 { 00081 size_t operator()( const T * x ) const 00082 { 00083 return reinterpret_cast< size_t >( x ) * 2654435761; 00084 } 00085 }; 00086 00087 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00088 00089 // \brief hash for const char * 00090 template<> 00091 struct cnc_hash< char * > 00092 { 00093 size_t operator()( const char * x ) const 00094 { 00095 // suggested by Paul Larson of Microsoft Research 00096 size_t _n = 0; 00097 while ( *x ) { 00098 _n = _n * 101 + *x; 00099 ++x; 00100 } 00101 return _n; 00102 } 00103 }; 00104 00105 // \brief equality for const char * 00106 template<> 00107 struct cnc_equal< char * > 00108 { 00109 bool operator()( const char * x, const char * y ) const 00110 { 00111 return ( strcmp( x, y ) == 0 ); 00112 } 00113 }; 00114 00115 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00116 00117 /// \brief hash for std::string 00118 template<> 00119 struct cnc_hash< std::string > 00120 { 00121 size_t operator()( const std::string & x ) const 00122 { 00123 // suggested by Paul Larson of Microsoft Research 00124 size_t _n = 0; 00125 for( std::string::const_iterator i = x.begin(); i != x.end(); ++ i ) { 00126 _n = _n * 101 + *i; 00127 } 00128 return _n; 00129 } 00130 }; 00131 00132 /// \brief equality for std::string 00133 template<> 00134 struct cnc_equal< std::string > 00135 { 00136 bool operator()( const std::string & a, const std::string & b ) const 00137 { 00138 return ( a.compare( b ) == 0 ); 00139 } 00140 }; 00141 00142 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00143 00144 // \brief hash/equality for std::vector 00145 template< class T, class Allocator > 00146 struct cnc_hash< std::vector< T, Allocator > > 00147 { 00148 public: 00149 size_t operator()( const std::vector< T, Allocator > & x ) const 00150 { 00151 size_t _n = x.size(); 00152 CNC_ASSERT( _n > 0 ); 00153 cnc_hash< T > _hasher; 00154 switch( _n ) { 00155 case 0 : return 0; 00156 case 1 : return _hasher.operator()( x[0] ); 00157 case 2 : return ( _hasher.operator()( x[0] ) 00158 + ( _hasher.operator()( x[1] ) << 10 ) );; 00159 case 3 : return ( _hasher.operator()( x[0] ) 00160 + ( _hasher.operator()( x[1] ) << 9 ) 00161 + ( _hasher.operator()( x[2] ) << 18 ) ); 00162 case 4 : return ( _hasher.operator()( x[0] ) 00163 + ( _hasher.operator()( x[3] ) << 8 ) 00164 + ( _hasher.operator()( x[1] ) << 16 ) 00165 + ( _hasher.operator()( x[2] ) << 24 ) ); 00166 default : { 00167 size_t _n = 0; 00168 for( typename std::vector< T, Allocator >::const_iterator i = x.begin(); i != x.end(); ++ i ) { 00169 _n = _n * 3 + _hasher.operator()( *i ); 00170 } 00171 return _n; 00172 } 00173 } 00174 } 00175 }; 00176 00177 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00178 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00179 00180 00181 /// \brief Provides hash and equality operators for hashing as used by item_collections 00182 /// 00183 /// It is recommended to specilialize cnc_hash and/or cnc_equal rather than cnc_tag_hash_compare 00184 template< class T > 00185 struct cnc_tag_hash_compare : public cnc_hash< T >, public cnc_equal< T > 00186 { 00187 /// \return a unique integer for the given tag 00188 size_t hash( const T & x ) const 00189 { 00190 return cnc_hash< T >::operator()( x ); 00191 } 00192 /// \return true if a equals b, false otherwise 00193 bool equal( const T & x, const T & y ) const 00194 { 00195 return cnc_equal< T >::operator()( x, y ); 00196 } 00197 }; 00198 00199 #endif // _TAG_HASH_COMPARE_HH_ALREADY_INCLUDED