Embedded Template Library  1.0
murmur3.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2014 jwellbelove
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29 ******************************************************************************/
30 
31 #ifndef ETL_MURMUR3_INCLUDED
32 #define ETL_MURMUR3_INCLUDED
33 
34 #include <stdint.h>
35 
36 #include "platform.h"
37 #include "ihash.h"
38 #include "binary.h"
39 #include "error_handler.h"
40 
41 #if defined(ETL_COMPILER_KEIL)
42 #pragma diag_suppress 1300
43 #endif
44 
47 
48 namespace etl
49 {
50  //***************************************************************************
54  //***************************************************************************
55  template <typename THash>
56  class murmur3
57  {
58  public:
59 
60 #if ETL_NOT_USING_64BIT_TYPES
61  ETL_STATIC_ASSERT((etl::is_same<THash, uint32_t>::value), "Only 32 bit types supported");
62 #else
63  ETL_STATIC_ASSERT((etl::is_same<THash, uint32_t>::value || etl::is_same<THash, uint64_t>::value), "Only 32 & 64 bit types supported");
64 #endif
65 
66  typedef THash value_type;
67 
68  //*************************************************************************
71  //*************************************************************************
72  murmur3(value_type seed_ = 0)
73  : seed(seed_)
74  {
75  reset();
76  }
77 
78  //*************************************************************************
83  //*************************************************************************
84  template<typename TIterator>
85  murmur3(TIterator begin, const TIterator end, value_type seed_ = 0)
86  : seed(seed_)
87  {
88  ETL_STATIC_ASSERT(sizeof(typename etl::iterator_traits<TIterator>::value_type) == 1, "Incompatible type");
89 
90  reset();
91  while (begin != end)
92  {
93  block |= (*begin++) << (block_fill_count * 8);
94 
95  if (++block_fill_count == FULL_BLOCK)
96  {
97  add_block();
98  block_fill_count = 0;
99  block = 0;
100  }
101 
102  ++char_count;
103  }
104  }
105 
106  //*************************************************************************
108  //*************************************************************************
109  void reset()
110  {
111  hash = seed;
112  char_count = 0;
113  block = 0;
114  block_fill_count = 0;
115  is_finalised = false;
116  }
117 
118  //*************************************************************************
122  //*************************************************************************
123  template<typename TIterator>
124  void add(TIterator begin, const TIterator end)
125  {
126  ETL_STATIC_ASSERT(sizeof(typename etl::iterator_traits<TIterator>::value_type) == 1, "Incompatible type");
127  ETL_ASSERT(!is_finalised, ETL_ERROR(hash_finalised));
128 
129  while (begin != end)
130  {
131  block |= (*begin++) << (block_fill_count * 8);
132 
133  if (++block_fill_count == FULL_BLOCK)
134  {
135  add_block();
136  block_fill_count = 0;
137  block = 0;
138  }
139 
140  ++char_count;
141  }
142  }
143 
144  //*************************************************************************
148  //*************************************************************************
149  void add(uint8_t value_)
150  {
151  // We can't add to a finalised hash!
152  ETL_ASSERT(!is_finalised, ETL_ERROR(hash_finalised));
153 
154  block |= value_ << (block_fill_count * 8);
155 
156  if (++block_fill_count == FULL_BLOCK)
157  {
158  add_block();
159  block_fill_count = 0;
160  block = 0;
161  }
162 
163  ++char_count;
164  }
165 
166  //*************************************************************************
168  //*************************************************************************
169  value_type value()
170  {
171  finalise();
172  return hash;
173  }
174 
175  //*************************************************************************
177  //*************************************************************************
178  operator value_type ()
179  {
180  return value();
181  }
182 
183  private:
184 
185  //*************************************************************************
187  //*************************************************************************
188  void add_block()
189  {
190  block *= CONSTANT1;
191  block = rotate_left(block, SHIFT1);
192  block *= CONSTANT2;
193 
194  hash ^= block;
195  hash = rotate_left(hash, SHIFT2);
196  hash = (hash * MULTIPLY) + ADD;
197  }
198 
199  //*************************************************************************
201  //*************************************************************************
202  void finalise()
203  {
204  if (!is_finalised)
205  {
206  block *= CONSTANT1;
207  block = rotate_left(block, SHIFT1);
208  block *= CONSTANT2;
209 
210  hash ^= block;
211  hash ^= char_count;
212  hash ^= (hash >> 16);
213  hash *= 0x85EBCA6B;
214  hash ^= (hash >> 13);
215  hash *= 0xC2B2AE35;
216  hash ^= (hash >> 16);
217 
218  is_finalised = true;
219  }
220  }
221 
222  bool is_finalised;
223  uint8_t block_fill_count;
224  size_t char_count;
225  value_type block;
226  value_type hash;
227  value_type seed;
228 
229  static const uint8_t FULL_BLOCK = 4;
230  static const value_type CONSTANT1 = 0xCC9E2D51;
231  static const value_type CONSTANT2 = 0x1B873593;
232  static const value_type SHIFT1 = 15;
233  static const value_type SHIFT2 = 13;
234  static const value_type MULTIPLY = 5;
235  static const value_type ADD = 0xE6546B64;
236  };
237 }
238 
239 #endif
ETL_CONSTEXPR14 T rotate_left(T value)
Definition: binary.h:115
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition: container.h:49
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition: container.h:99
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
Definition: hash.h:93
void reset()
Resets the hash to the initial state.
Definition: murmur3.h:109
murmur3(value_type seed_=0)
Definition: murmur3.h:72
murmur3(TIterator begin, const TIterator end, value_type seed_=0)
Definition: murmur3.h:85
void add(TIterator begin, const TIterator end)
Definition: murmur3.h:124
value_type value()
Gets the hash value.
Definition: murmur3.h:169
void add(uint8_t value_)
Definition: murmur3.h:149
Definition: murmur3.h:57
is_same
Definition: type_traits_generator.h:981
Definition: ihash.h:69
Definition: absolute.h:37