CnC
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends
cnc_tag_hash_compare.h
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
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends