11debfc3dSmrg // Definition of _Hash_bytes. -*- C++ -*- 21debfc3dSmrg 3*8feb0f0bSmrg // Copyright (C) 2010-2020 Free Software Foundation, Inc. 41debfc3dSmrg // 51debfc3dSmrg // This file is part of the GNU ISO C++ Library. This library is free 61debfc3dSmrg // software; you can redistribute it and/or modify it under the 71debfc3dSmrg // terms of the GNU General Public License as published by the 81debfc3dSmrg // Free Software Foundation; either version 3, or (at your option) 91debfc3dSmrg // any later version. 101debfc3dSmrg 111debfc3dSmrg // This library is distributed in the hope that it will be useful, 121debfc3dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of 131debfc3dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141debfc3dSmrg // GNU General Public License for more details. 151debfc3dSmrg 161debfc3dSmrg // Under Section 7 of GPL version 3, you are granted additional 171debfc3dSmrg // permissions described in the GCC Runtime Library Exception, version 181debfc3dSmrg // 3.1, as published by the Free Software Foundation. 191debfc3dSmrg 201debfc3dSmrg // You should have received a copy of the GNU General Public License and 211debfc3dSmrg // a copy of the GCC Runtime Library Exception along with this program; 221debfc3dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 231debfc3dSmrg // <http://www.gnu.org/licenses/>. 241debfc3dSmrg 251debfc3dSmrg // This file defines Hash_bytes, a primitive used for defining hash 261debfc3dSmrg // functions. Based on public domain MurmurHashUnaligned2, by Austin 271debfc3dSmrg // Appleby. http://murmurhash.googlepages.com/ 281debfc3dSmrg 291debfc3dSmrg // This file also defines _Fnv_hash_bytes, another primitive with 301debfc3dSmrg // exactly the same interface but using a different hash algorithm, 311debfc3dSmrg // Fowler / Noll / Vo (FNV) Hash (type FNV-1a). The Murmur hash 321debfc3dSmrg // function apears to be better in both speed and hash quality, and 331debfc3dSmrg // FNV is provided primarily for backward compatibility. 341debfc3dSmrg 351debfc3dSmrg #include <bits/hash_bytes.h> 361debfc3dSmrg 371debfc3dSmrg namespace 381debfc3dSmrg { 391debfc3dSmrg inline std::size_t unaligned_load(const char * p)401debfc3dSmrg unaligned_load(const char* p) 411debfc3dSmrg { 421debfc3dSmrg std::size_t result; 431debfc3dSmrg __builtin_memcpy(&result, p, sizeof(result)); 441debfc3dSmrg return result; 451debfc3dSmrg } 461debfc3dSmrg 471debfc3dSmrg #if __SIZEOF_SIZE_T__ == 8 481debfc3dSmrg // Loads n bytes, where 1 <= n < 8. 491debfc3dSmrg inline std::size_t load_bytes(const char * p,int n)501debfc3dSmrg load_bytes(const char* p, int n) 511debfc3dSmrg { 521debfc3dSmrg std::size_t result = 0; 531debfc3dSmrg --n; 541debfc3dSmrg do 551debfc3dSmrg result = (result << 8) + static_cast<unsigned char>(p[n]); 561debfc3dSmrg while (--n >= 0); 571debfc3dSmrg return result; 581debfc3dSmrg } 591debfc3dSmrg 601debfc3dSmrg inline std::size_t shift_mix(std::size_t v)611debfc3dSmrg shift_mix(std::size_t v) 621debfc3dSmrg { return v ^ (v >> 47);} 631debfc3dSmrg #endif 641debfc3dSmrg } 651debfc3dSmrg 661debfc3dSmrg namespace std 671debfc3dSmrg { 681debfc3dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION 691debfc3dSmrg 701debfc3dSmrg #if __SIZEOF_SIZE_T__ == 4 711debfc3dSmrg 721debfc3dSmrg // Implementation of Murmur hash for 32-bit size_t. 731debfc3dSmrg size_t _Hash_bytes(const void * ptr,size_t len,size_t seed)741debfc3dSmrg _Hash_bytes(const void* ptr, size_t len, size_t seed) 751debfc3dSmrg { 761debfc3dSmrg const size_t m = 0x5bd1e995; 771debfc3dSmrg size_t hash = seed ^ len; 781debfc3dSmrg const char* buf = static_cast<const char*>(ptr); 791debfc3dSmrg 801debfc3dSmrg // Mix 4 bytes at a time into the hash. 811debfc3dSmrg while(len >= 4) 821debfc3dSmrg { 831debfc3dSmrg size_t k = unaligned_load(buf); 841debfc3dSmrg k *= m; 851debfc3dSmrg k ^= k >> 24; 861debfc3dSmrg k *= m; 871debfc3dSmrg hash *= m; 881debfc3dSmrg hash ^= k; 891debfc3dSmrg buf += 4; 901debfc3dSmrg len -= 4; 911debfc3dSmrg } 921debfc3dSmrg 931debfc3dSmrg // Handle the last few bytes of the input array. 941debfc3dSmrg switch(len) 951debfc3dSmrg { 961debfc3dSmrg case 3: 971debfc3dSmrg hash ^= static_cast<unsigned char>(buf[2]) << 16; 981debfc3dSmrg [[gnu::fallthrough]]; 991debfc3dSmrg case 2: 1001debfc3dSmrg hash ^= static_cast<unsigned char>(buf[1]) << 8; 1011debfc3dSmrg [[gnu::fallthrough]]; 1021debfc3dSmrg case 1: 1031debfc3dSmrg hash ^= static_cast<unsigned char>(buf[0]); 1041debfc3dSmrg hash *= m; 1051debfc3dSmrg }; 1061debfc3dSmrg 1071debfc3dSmrg // Do a few final mixes of the hash. 1081debfc3dSmrg hash ^= hash >> 13; 1091debfc3dSmrg hash *= m; 1101debfc3dSmrg hash ^= hash >> 15; 1111debfc3dSmrg return hash; 1121debfc3dSmrg } 1131debfc3dSmrg 1141debfc3dSmrg // Implementation of FNV hash for 32-bit size_t. 1151debfc3dSmrg // N.B. This function should work on unsigned char, otherwise it does not 1161debfc3dSmrg // correctly implement the FNV-1a algorithm (see PR59406). 1171debfc3dSmrg // The existing behaviour is retained for backwards compatibility. 1181debfc3dSmrg size_t _Fnv_hash_bytes(const void * ptr,size_t len,size_t hash)1191debfc3dSmrg _Fnv_hash_bytes(const void* ptr, size_t len, size_t hash) 1201debfc3dSmrg { 1211debfc3dSmrg const char* cptr = static_cast<const char*>(ptr); 1221debfc3dSmrg for (; len; --len) 1231debfc3dSmrg { 1241debfc3dSmrg hash ^= static_cast<size_t>(*cptr++); 1251debfc3dSmrg hash *= static_cast<size_t>(16777619UL); 1261debfc3dSmrg } 1271debfc3dSmrg return hash; 1281debfc3dSmrg } 1291debfc3dSmrg 1301debfc3dSmrg #elif __SIZEOF_SIZE_T__ == 8 1311debfc3dSmrg 1321debfc3dSmrg // Implementation of Murmur hash for 64-bit size_t. 1331debfc3dSmrg size_t 1341debfc3dSmrg _Hash_bytes(const void* ptr, size_t len, size_t seed) 1351debfc3dSmrg { 1361debfc3dSmrg static const size_t mul = (((size_t) 0xc6a4a793UL) << 32UL) 1371debfc3dSmrg + (size_t) 0x5bd1e995UL; 1381debfc3dSmrg const char* const buf = static_cast<const char*>(ptr); 1391debfc3dSmrg 1401debfc3dSmrg // Remove the bytes not divisible by the sizeof(size_t). This 1411debfc3dSmrg // allows the main loop to process the data as 64-bit integers. 142a2dc1f3fSmrg const size_t len_aligned = len & ~(size_t)0x7; 1431debfc3dSmrg const char* const end = buf + len_aligned; 1441debfc3dSmrg size_t hash = seed ^ (len * mul); 1451debfc3dSmrg for (const char* p = buf; p != end; p += 8) 1461debfc3dSmrg { 1471debfc3dSmrg const size_t data = shift_mix(unaligned_load(p) * mul) * mul; 1481debfc3dSmrg hash ^= data; 1491debfc3dSmrg hash *= mul; 1501debfc3dSmrg } 1511debfc3dSmrg if ((len & 0x7) != 0) 1521debfc3dSmrg { 1531debfc3dSmrg const size_t data = load_bytes(end, len & 0x7); 1541debfc3dSmrg hash ^= data; 1551debfc3dSmrg hash *= mul; 1561debfc3dSmrg } 1571debfc3dSmrg hash = shift_mix(hash) * mul; 1581debfc3dSmrg hash = shift_mix(hash); 1591debfc3dSmrg return hash; 1601debfc3dSmrg } 1611debfc3dSmrg 1621debfc3dSmrg // Implementation of FNV hash for 64-bit size_t. 1631debfc3dSmrg // N.B. This function should work on unsigned char, otherwise it does not 1641debfc3dSmrg // correctly implement the FNV-1a algorithm (see PR59406). 1651debfc3dSmrg // The existing behaviour is retained for backwards compatibility. 1661debfc3dSmrg size_t 1671debfc3dSmrg _Fnv_hash_bytes(const void* ptr, size_t len, size_t hash) 1681debfc3dSmrg { 1691debfc3dSmrg const char* cptr = static_cast<const char*>(ptr); 1701debfc3dSmrg for (; len; --len) 1711debfc3dSmrg { 1721debfc3dSmrg hash ^= static_cast<size_t>(*cptr++); 1731debfc3dSmrg hash *= static_cast<size_t>(1099511628211ULL); 1741debfc3dSmrg } 1751debfc3dSmrg return hash; 1761debfc3dSmrg } 1771debfc3dSmrg 1781debfc3dSmrg #else 1791debfc3dSmrg 1801debfc3dSmrg // Dummy hash implementation for unusual sizeof(size_t). 1811debfc3dSmrg size_t 1821debfc3dSmrg _Hash_bytes(const void* ptr, size_t len, size_t seed) 1831debfc3dSmrg { 1841debfc3dSmrg size_t hash = seed; 1851debfc3dSmrg const char* cptr = reinterpret_cast<const char*>(ptr); 1861debfc3dSmrg for (; len; --len) 1871debfc3dSmrg hash = (hash * 131) + *cptr++; 1881debfc3dSmrg return hash; 1891debfc3dSmrg } 1901debfc3dSmrg 1911debfc3dSmrg size_t 1921debfc3dSmrg _Fnv_hash_bytes(const void* ptr, size_t len, size_t seed) 1931debfc3dSmrg { return _Hash_bytes(ptr, len, seed); } 1941debfc3dSmrg 1951debfc3dSmrg #endif /* __SIZEOF_SIZE_T__ */ 1961debfc3dSmrg 1971debfc3dSmrg _GLIBCXX_END_NAMESPACE_VERSION 1981debfc3dSmrg } // namespace 199