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