$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 #ifndef LIBMESH_HASHWORD_H 00019 #define LIBMESH_HASHWORD_H 00020 00021 // ::size_t is defined in the backward compatibility header stddef.h. 00022 // It's been part of ANSI/ISO C and ISO C++ since their very 00023 // beginning. Every C++ implementation has to ship with stddef.h 00024 // (compatibility) and cstddef where only the latter defines 00025 // std::size_t and not necessarily ::size_t. See Annex D of the C++ 00026 // Standard. 00027 // 00028 // http://stackoverflow.com/questions/237370/does-stdsize-t-make-sense-in-c 00029 #include <stddef.h> 00030 #include <stdint.h> // uint32_t, uint64_t 00031 00032 #include "libmesh_common.h" // libmesh_error_msg() 00033 00034 // Anonymous namespace for utility functions used locally 00035 namespace 00036 { 00037 // Rotate x by k bits 00038 // @author Bob Jenkins, May 2006, Public Domain. 00039 // http://burtleburtle.net/bob/hash/index.html 00040 inline 00041 uint32_t rot(uint32_t x, uint32_t k) 00042 { 00043 return (x<<k) | (x>>(32-k)); 00044 } 00045 00046 00047 00048 // mix 3 32-bit values reversibly 00049 // @author Bob Jenkins, May 2006, Public Domain. 00050 // http://burtleburtle.net/bob/hash/index.html 00051 inline 00052 void mix(uint32_t& a, uint32_t& b, uint32_t& c) 00053 { 00054 a -= c; a ^= rot(c, 4); c += b; 00055 b -= a; b ^= rot(a, 6); a += c; 00056 c -= b; c ^= rot(b, 8); b += a; 00057 a -= c; a ^= rot(c,16); c += b; 00058 b -= a; b ^= rot(a,19); a += c; 00059 c -= b; c ^= rot(b, 4); b += a; 00060 } 00061 00062 00063 // 'final' mixing of 3 32-bit numbers, result is stored in c. 00064 // @author Bob Jenkins, May 2006, Public Domain. 00065 // http://burtleburtle.net/bob/hash/index.html 00066 inline 00067 void final(uint32_t& a, uint32_t& b, uint32_t& c) 00068 { 00069 c ^= b; c -= rot(b,14); 00070 a ^= c; a -= rot(c,11); 00071 b ^= a; b -= rot(a,25); 00072 c ^= b; c -= rot(b,16); 00073 a ^= c; a -= rot(c,4); 00074 b ^= a; b -= rot(a,14); 00075 c ^= b; c -= rot(b,24); 00076 } 00077 00078 00079 // fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer. 00080 // http://www.isthe.com/chongo/tech/comp/fnv/index.html 00081 // Code is in the public domain. 00082 // 00083 // Authors: 00084 // Phong Vo (http://www.research.att.com/info/kpv/) 00085 // Glenn Fowler (http://www.research.att.com/~gsf/) 00086 // Landon Curt Noll (http://www.isthe.com/chongo/) 00087 // 00088 // input: 00089 // buf - start of buffer to hash 00090 // len - length of buffer in octets 00091 // 00092 // returns: 64 bit hash as a static hash type 00093 uint64_t fnv_64_buf(const void *buf, size_t len) 00094 { 00095 // Initializing hval with this value corresponds to the FNV-1 hash algorithm. 00096 uint64_t hval = static_cast<uint64_t>(0xcbf29ce484222325ULL); 00097 00098 // start of buffer 00099 const unsigned char *bp = static_cast<const unsigned char *>(buf); 00100 00101 // beyond end of buffer 00102 const unsigned char *be = bp + len; 00103 00104 // FNV-1 hash each octet of the buffer 00105 while (bp < be) 00106 { 00107 hval += 00108 (hval << 1) + (hval << 4) + (hval << 5) + 00109 (hval << 7) + (hval << 8) + (hval << 40); 00110 00111 // xor the bottom with the current octet 00112 hval ^= static_cast<uint64_t>(*bp++); 00113 } 00114 00115 // return our new hash value 00116 return hval; 00117 } 00118 00119 } // end anonymous namespace 00120 00121 00122 00123 namespace libMesh 00124 { 00125 namespace Utility 00126 { 00127 // The hashword function takes an array of uint32_t's of length 'length' 00128 // and computes a single key from it. 00129 // @author Bob Jenkins, May 2006, Public Domain. 00130 // http://burtleburtle.net/bob/hash/index.html 00131 inline 00132 uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval=0) 00133 { 00134 uint32_t a,b,c; 00135 00136 // Set up the internal state 00137 a = b = c = 0xdeadbeef + ((static_cast<uint32_t>(length))<<2) + initval; 00138 00139 //------------------------------------------------- handle most of the key 00140 while (length > 3) 00141 { 00142 a += k[0]; 00143 b += k[1]; 00144 c += k[2]; 00145 mix(a,b,c); 00146 length -= 3; 00147 k += 3; 00148 } 00149 00150 //------------------------------------------- handle the last 3 uint32_t's 00151 switch(length) // all the case statements fall through 00152 { 00153 case 3 : c+=k[2]; 00154 case 2 : b+=k[1]; 00155 case 1 : a+=k[0]; 00156 final(a,b,c); 00157 default: // case 0: nothing left to add 00158 break; 00159 } 00160 00161 //------------------------------------------------------ report the result 00162 return c; 00163 } 00164 00165 00166 // This is a hard-coded version of hashword for hashing exactly 2 numbers 00167 // @author Bob Jenkins, May 2006, Public Domain. 00168 // http://burtleburtle.net/bob/hash/index.html 00169 inline 00170 uint32_t hashword2(const uint32_t& first, const uint32_t& second, uint32_t initval=0) 00171 { 00172 uint32_t a,b,c; 00173 00174 // Set up the internal state 00175 a = b = c = 0xdeadbeef + 8 + initval; 00176 00177 b+=second; 00178 a+=first; 00179 final(a,b,c); 00180 00181 return c; 00182 } 00183 00184 // Call the 64-bit FNV hash function. 00185 inline 00186 uint64_t hashword2(const uint64_t first, const uint64_t second) 00187 { 00188 // This isn't optimal (it would be nice to avoid this packing step) 00189 // but we are going to go ahead and conform to the 32-bit 00190 // hashword2() interface. 00191 uint64_t k[2] = {first, second}; 00192 00193 // len is the total number of bytes in two 64-bit ints 00194 return fnv_64_buf(k, /*len=*/8*2); 00195 } 00196 00197 inline 00198 uint16_t hashword2(const uint16_t first, const uint16_t second) 00199 { 00200 return static_cast<uint16_t>(first%65449 + (second<<5)%65449); 00201 } 00202 00203 // Call the 64-bit FNV hash function. 00204 inline 00205 uint64_t hashword(const uint64_t *k, size_t length) 00206 { 00207 return fnv_64_buf(k, 8*length); 00208 } 00209 00210 // In a personal communication from Bob Jenkins, he recommended using 00211 // "Probably final() from lookup3.c... You could hash up to 6 16-bit 00212 // integers that way. The output is c, or the top or bottom 16 bits 00213 // of c if you only need 16 bit hash values." [JWP] 00214 inline 00215 uint16_t hashword(const uint16_t *k, size_t length) 00216 { 00217 // Three values that will be passed to final() after they are initialized. 00218 uint32_t a = 0; 00219 uint32_t b = 0; 00220 uint32_t c = 0; 00221 00222 switch (length) 00223 { 00224 case 3: 00225 { 00226 // Cast the inputs to 32 bit integers and call final(). 00227 a = k[0]; 00228 b = k[1]; 00229 c = k[2]; 00230 break; 00231 } 00232 case 4: 00233 { 00234 // Combine the 4 16-bit inputs, "w, x, y, z" into two 32-bit 00235 // inputs "wx" and "yz" using bit operations and call final. 00236 a = ((k[0]<<16) | (k[1] & 0xffff)); // wx 00237 b = ((k[2]<<16) | (k[3] & 0xffff)); // yz 00238 break; 00239 } 00240 default: 00241 libmesh_error_msg("Unsupported length: " << length); 00242 } 00243 00244 // Result is returned in c 00245 final(a,b,c); 00246 return static_cast<uint16_t>(c); 00247 } 00248 00249 } // end Utility namespace 00250 } // end libMesh namespace 00251 00252 #endif // LIBMESH_HASHWORD_H