Branimir Karadžić 9 years ago
parent
commit
393a86a849
2 changed files with 180 additions and 134 deletions
  1. 26 134
      include/bx/hash.h
  2. 154 0
      include/bx/hash.inl

+ 26 - 134
include/bx/hash.h

@@ -10,135 +10,37 @@
 
 
 namespace bx
 namespace bx
 {
 {
-// MurmurHash2 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-
-#define MURMUR_M 0x5bd1e995
-#define MURMUR_R 24
-#define mmix(_h, _k) { _k *= MURMUR_M; _k ^= _k >> MURMUR_R; _k *= MURMUR_M; _h *= MURMUR_M; _h ^= _k; }
-
+	/// MurmurHash2 was written by Austin Appleby, and is placed in the public
+	/// domain. The author hereby disclaims copyright to this source code.
+	///
 	class HashMurmur2A
 	class HashMurmur2A
 	{
 	{
 	public:
 	public:
-		void begin(uint32_t _seed = 0)
-		{
-			m_hash = _seed;
-			m_tail = 0;
-			m_count = 0;
-			m_size = 0;
-		}
-
-		void add(const void* _data, int _len)
-		{
-			if (BX_UNLIKELY(!isAligned(_data, 4) ) )
-			{
-				addUnaligned(_data, _len);
-				return;
-			}
-
-			addAligned(_data, _len);
-		}
-
-		void addAligned(const void* _data, int _len)
-		{
-			const uint8_t* data = (const uint8_t*)_data;
-			m_size += _len;
-
-			mixTail(data, _len);
-
-			while(_len >= 4)
-			{
-				uint32_t kk = *(uint32_t*)data;
-
-				mmix(m_hash, kk);
-
-				data += 4;
-				_len -= 4;
-			}
-
-			mixTail(data, _len);
-		}
+		///
+		void begin(uint32_t _seed = 0);
 
 
-		void addUnaligned(const void* _data, int _len)
-		{
-			const uint8_t* data = (const uint8_t*)_data;
-			m_size += _len;
+		///
+		void add(const void* _data, int _len);
 
 
-			mixTail(data, _len);
+		///
+		void addAligned(const void* _data, int _len);
 
 
-			while(_len >= 4)
-			{
-				uint32_t kk;
-				readUnaligned(data, kk);
-
-				mmix(m_hash, kk);
-
-				data += 4;
-				_len -= 4;
-			}
-
-			mixTail(data, _len);
-		}
+		///
+		void addUnaligned(const void* _data, int _len);
 
 
+		///
 		template<typename Ty>
 		template<typename Ty>
-		void add(Ty _value)
-		{
-			add(&_value, sizeof(Ty) );
-		}
-
-		uint32_t end()
-		{
-			mmix(m_hash, m_tail);
-			mmix(m_hash, m_size);
-
-			m_hash ^= m_hash >> 13;
-			m_hash *= MURMUR_M;
-			m_hash ^= m_hash >> 15;
+		void add(Ty _value);
 
 
-			return m_hash;
-		}
+		///
+		uint32_t end();
 
 
 	private:
 	private:
-		static void readUnaligned(const void* _data, uint32_t& _out)
-		{
-			const uint8_t* data = (const uint8_t*)_data;
-			if (BX_ENABLED(BX_CPU_ENDIAN_BIG) )
-			{
-				_out = 0
-					| data[0]<<24
-					| data[1]<<16
-					| data[2]<<8
-					| data[3]
-					;
-			}
-			else
-			{
-				_out = 0
-					| data[0]
-					| data[1]<<8
-					| data[2]<<16
-					| data[3]<<24
-					;
-			}
-		}
-
-		void mixTail(const uint8_t*& _data, int& _len)
-		{
-			while( _len && ((_len<4) || m_count) )
-			{
-				m_tail |= (*_data++) << (m_count * 8);
-
-				m_count++;
-				_len--;
-
-				if(m_count == 4)
-				{
-					mmix(m_hash, m_tail);
-					m_tail = 0;
-					m_count = 0;
-				}
-			}
-		}
+		///
+		static void readUnaligned(const void* _data, uint32_t& _out);
+
+		///
+		void mixTail(const uint8_t*& _data, int& _len);
 
 
 		uint32_t m_hash;
 		uint32_t m_hash;
 		uint32_t m_tail;
 		uint32_t m_tail;
@@ -146,25 +48,15 @@ namespace bx
 		uint32_t m_size;
 		uint32_t m_size;
 	};
 	};
 
 
-#undef MURMUR_M
-#undef MURMUR_R
-#undef mmix
-
-	inline uint32_t hashMurmur2A(const void* _data, uint32_t _size)
-	{
-		HashMurmur2A murmur;
-		murmur.begin();
-		murmur.add(_data, (int)_size);
-		return murmur.end();
-	}
+	///
+	uint32_t hashMurmur2A(const void* _data, uint32_t _size);
 
 
+	///
 	template <typename Ty>
 	template <typename Ty>
-	inline uint32_t hashMurmur2A(const Ty& _data)
-	{
-		BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
-		return hashMurmur2A(&_data, sizeof(Ty) );
-	}
+	uint32_t hashMurmur2A(const Ty& _data);
 
 
 } // namespace bx
 } // namespace bx
 
 
+#include "hash.inl"
+
 #endif // BX_HASH_H_HEADER_GUARD
 #endif // BX_HASH_H_HEADER_GUARD

+ 154 - 0
include/bx/hash.inl

@@ -0,0 +1,154 @@
+/*
+ * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
+ */
+
+#ifndef BX_HASH_H_HEADER_GUARD
+#	error "Must be included from bx/hash.h!"
+#endif // BX_HASH_H_HEADER_GUARD
+
+namespace bx
+{
+#define MURMUR_M 0x5bd1e995
+#define MURMUR_R 24
+#define mmix(_h, _k) { _k *= MURMUR_M; _k ^= _k >> MURMUR_R; _k *= MURMUR_M; _h *= MURMUR_M; _h ^= _k; }
+
+	inline void HashMurmur2A::begin(uint32_t _seed)
+	{
+		m_hash = _seed;
+		m_tail = 0;
+		m_count = 0;
+		m_size = 0;
+	}
+
+	inline void HashMurmur2A::add(const void* _data, int _len)
+	{
+		if (BX_UNLIKELY(!isAligned(_data, 4) ) )
+		{
+			addUnaligned(_data, _len);
+			return;
+		}
+
+		addAligned(_data, _len);
+	}
+
+	inline void HashMurmur2A::addAligned(const void* _data, int _len)
+	{
+		const uint8_t* data = (const uint8_t*)_data;
+		m_size += _len;
+
+		mixTail(data, _len);
+
+		while(_len >= 4)
+		{
+			uint32_t kk = *(uint32_t*)data;
+
+			mmix(m_hash, kk);
+
+			data += 4;
+			_len -= 4;
+		}
+
+		mixTail(data, _len);
+	}
+
+	inline void HashMurmur2A::addUnaligned(const void* _data, int _len)
+	{
+		const uint8_t* data = (const uint8_t*)_data;
+		m_size += _len;
+
+		mixTail(data, _len);
+
+		while(_len >= 4)
+		{
+			uint32_t kk;
+			readUnaligned(data, kk);
+
+			mmix(m_hash, kk);
+
+			data += 4;
+			_len -= 4;
+		}
+
+		mixTail(data, _len);
+	}
+
+	template<typename Ty>
+	inline void HashMurmur2A::add(Ty _value)
+	{
+		add(&_value, sizeof(Ty) );
+	}
+
+	inline uint32_t HashMurmur2A::end()
+	{
+		mmix(m_hash, m_tail);
+		mmix(m_hash, m_size);
+
+		m_hash ^= m_hash >> 13;
+		m_hash *= MURMUR_M;
+		m_hash ^= m_hash >> 15;
+
+		return m_hash;
+	}
+
+	inline void HashMurmur2A::readUnaligned(const void* _data, uint32_t& _out)
+	{
+		const uint8_t* data = (const uint8_t*)_data;
+		if (BX_ENABLED(BX_CPU_ENDIAN_BIG) )
+		{
+			_out = 0
+				| data[0]<<24
+				| data[1]<<16
+				| data[2]<<8
+				| data[3]
+				;
+		}
+		else
+		{
+			_out = 0
+				| data[0]
+				| data[1]<<8
+				| data[2]<<16
+				| data[3]<<24
+				;
+		}
+	}
+
+	inline void HashMurmur2A::mixTail(const uint8_t*& _data, int& _len)
+	{
+		while( _len && ((_len<4) || m_count) )
+		{
+			m_tail |= (*_data++) << (m_count * 8);
+
+			m_count++;
+			_len--;
+
+			if(m_count == 4)
+			{
+				mmix(m_hash, m_tail);
+				m_tail = 0;
+				m_count = 0;
+			}
+		}
+	}
+
+#undef MURMUR_M
+#undef MURMUR_R
+#undef mmix
+
+	inline uint32_t hashMurmur2A(const void* _data, uint32_t _size)
+	{
+		HashMurmur2A murmur;
+		murmur.begin();
+		murmur.add(_data, (int)_size);
+		return murmur.end();
+	}
+
+	template <typename Ty>
+	inline uint32_t hashMurmur2A(const Ty& _data)
+	{
+		BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
+		return hashMurmur2A(&_data, sizeof(Ty) );
+	}
+
+} // namespace bx