/packages/src/gcc-5.3.0-build/x86_64-unknown-linux-gnu/libstdc++-v3/libsupc++/../../../../gcc-5.3.0/libstdc++-v3/libsupc++/hash_bytes.cc

Line% of fetchesSource
1  
// Definition of _Hash_bytes. -*- C++ -*-
2  
3  
// Copyright (C) 2010-2015 Free Software Foundation, Inc.
4  
//
5  
// This file is part of the GNU ISO C++ Library.  This library is free
6  
// software; you can redistribute it and/or modify it under the
7  
// terms of the GNU General Public License as published by the
8  
// Free Software Foundation; either version 3, or (at your option)
9  
// any later version.
10  
11  
// This library is distributed in the hope that it will be useful,
12  
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  
// GNU General Public License for more details.
15  
16  
// Under Section 7 of GPL version 3, you are granted additional
17  
// permissions described in the GCC Runtime Library Exception, version
18  
// 3.1, as published by the Free Software Foundation.
19  
20  
// You should have received a copy of the GNU General Public License and
21  
// a copy of the GCC Runtime Library Exception along with this program;
22  
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23  
// <http://www.gnu.org/licenses/>.
24  
25  
// This file defines Hash_bytes, a primitive used for defining hash
26  
// functions. Based on public domain MurmurHashUnaligned2, by Austin
27  
// Appleby.  http://murmurhash.googlepages.com/
28  
29  
// This file also defines _Fnv_hash_bytes, another primitive with
30  
// exactly the same interface but using a different hash algorithm,
31  
// Fowler / Noll / Vo (FNV) Hash (type FNV-1a). The Murmur hash
32  
// function apears to be better in both speed and hash quality, and
33  
// FNV is provided primarily for backward compatibility.
34  
35  
#include <bits/hash_bytes.h>
36  
37  
namespace
38  
{
39  
  inline std::size_t
40  
  unaligned_load(const char* p)
41  
  {
42  
    std::size_t result;
43  
    __builtin_memcpy(&result, p, sizeof(result));
44  
    return result;
45  
  }
46  
47  
#if __SIZEOF_SIZE_T__ == 8
48  
  // Loads n bytes, where 1 <= n < 8.
49  
  inline std::size_t
50  
  load_bytes(const char* p, int n)
51  
  {
52  
    std::size_t result = 0;
53  
    --n;
54  
    do
55  
      result = (result << 8) + static_cast<unsigned char>(p[n]);
56  
    while (--n >= 0);
57  
    return result;
58  
  }
59  
60  
  inline std::size_t
61  
  shift_mix(std::size_t v)
62  
  { return v ^ (v >> 47);}
63  
#endif
64  
}
65  
66  
namespace std
67  
{
68  
_GLIBCXX_BEGIN_NAMESPACE_VERSION
69  
70  
#if __SIZEOF_SIZE_T__ == 4
71  
72  
  // Implementation of Murmur hash for 32-bit size_t.
73  
  size_t
74  
  _Hash_bytes(const void* ptr, size_t len, size_t seed)
75  
  {
76  
    const size_t m = 0x5bd1e995;
77  
    size_t hash = seed ^ len;
78  
    const char* buf = static_cast<const char*>(ptr);
79  
80  
    // Mix 4 bytes at a time into the hash.
81  
    while(len >= 4)
82  
      {
83  
	size_t k = unaligned_load(buf);
84  
	k *= m;
85  
	k ^= k >> 24;
86  
	k *= m;
87  
	hash *= m;
88  
	hash ^= k;
89  
	buf += 4;
90  
	len -= 4;
91  
      }
92  
93  
    // Handle the last few bytes of the input array.
94  
    switch(len)
95  
      {
96  
      case 3:
97  
	hash ^= static_cast<unsigned char>(buf[2]) << 16;
98  
      case 2:
99  
	hash ^= static_cast<unsigned char>(buf[1]) << 8;
100  
      case 1:
101  
	hash ^= static_cast<unsigned char>(buf[0]);
102  
	hash *= m;
103  
      };
104  
105  
    // Do a few final mixes of the hash.
106  
    hash ^= hash >> 13;
107  
    hash *= m;
108  
    hash ^= hash >> 15;
109  
    return hash;
110  
  }
111  
112  
  // Implementation of FNV hash for 32-bit size_t.
113  
  size_t
114  
  _Fnv_hash_bytes(const void* ptr, size_t len, size_t hash)
115  
  {
116  
    const char* cptr = static_cast<const char*>(ptr);
117  
    for (; len; --len)
118  
      {
119  
	hash ^= static_cast<size_t>(*cptr++);
120  
	hash *= static_cast<size_t>(16777619UL);
121  
      }
122  
    return hash;
123  
  }
124  
125  
#elif __SIZEOF_SIZE_T__ == 8
126  
127  
  // Implementation of Murmur hash for 64-bit size_t.
128  
  size_t
129  
  _Hash_bytes(const void* ptr, size_t len, size_t seed)
130  
  {
131  
    static const size_t mul = (((size_t) 0xc6a4a793UL) << 32UL)
132  
			      + (size_t) 0x5bd1e995UL;
133  
    const char* const buf = static_cast<const char*>(ptr);
134  
135  
    // Remove the bytes not divisible by the sizeof(size_t).  This
136  
    // allows the main loop to process the data as 64-bit integers.
137  
    const int len_aligned = len & ~0x7;
138  
    const char* const end = buf + len_aligned;
139  
    size_t hash = seed ^ (len * mul);
140  
    for (const char* p = buf; p != end; p += 8)
141  
      {
142 0.2%
	const size_t data = shift_mix(unaligned_load(p) * mul) * mul;
143  
	hash ^= data;
144  
	hash *= mul;
145  
      }
146  
    if ((len & 0x7) != 0)
147  
      {
148  
	const size_t data = load_bytes(end, len & 0x7);
149  
	hash ^= data;
150  
	hash *= mul;
151  
      }
152  
    hash = shift_mix(hash) * mul;
153  
    hash = shift_mix(hash);
154  
    return hash;
155  
  }
156  
157  
  // Implementation of FNV hash for 64-bit size_t.
158  
  size_t
159  
  _Fnv_hash_bytes(const void* ptr, size_t len, size_t hash)
160  
  {
161  
    const char* cptr = static_cast<const char*>(ptr);
162  
    for (; len; --len)
163  
      {
164  
	hash ^= static_cast<size_t>(*cptr++);
165  
	hash *= static_cast<size_t>(1099511628211ULL);
166  
      }
167  
    return hash;
168  
  }
169  
170  
#else
171  
172  
  // Dummy hash implementation for unusual sizeof(size_t).
173  
  size_t
174  
  _Hash_bytes(const void* ptr, size_t len, size_t seed)
175  
  {
176  
    size_t hash = seed;
177  
    const char* cptr = reinterpret_cast<const char*>(ptr);
178  
    for (; len; --len)
179  
      hash = (hash * 131) + *cptr++;
180  
    return hash;
181  
  }
182  
183  
  size_t
184  
  _Fnv_hash_bytes(const void* ptr, size_t len, size_t seed)
185  
  { return _Hash_bytes(ptr, len, seed); }
186  
187  
#endif /* __SIZEOF_SIZE_T__ */
188  
189  
_GLIBCXX_END_NAMESPACE_VERSION
190  
} // namespace
191  

Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.