From e3d5da3e6646dc99f510bdfca216cd03df39e91b Mon Sep 17 00:00:00 2001 From: q66 Date: Sun, 10 May 2015 21:57:52 +0100 Subject: [PATCH] octa::Hash in functional.h (+ specializations for all primitive types) --- octa/functional.h | 146 ++++++++++++++++++++++++++++++++++++++++++++++ octa/memory.h | 1 + octa/new.h | 2 + 3 files changed, 149 insertions(+) diff --git a/octa/functional.h b/octa/functional.h index d58a9e8..44df855 100644 --- a/octa/functional.h +++ b/octa/functional.h @@ -100,6 +100,152 @@ namespace octa { return BinaryNegate(fn); } + /* hash */ + + template struct Hash; + + template struct __OctaHashBase { + typedef T ArgType; + typedef size_t ResultType; + + size_t operator()(T v) const noexcept { + return (size_t)v; + } + }; + +#define __OCTA_HASH_BASIC(T) template<> struct Hash: __OctaHashBase {}; + + __OCTA_HASH_BASIC(bool) + __OCTA_HASH_BASIC(char) + __OCTA_HASH_BASIC(schar) + __OCTA_HASH_BASIC(uchar) + __OCTA_HASH_BASIC(char16_t) + __OCTA_HASH_BASIC(char32_t) + __OCTA_HASH_BASIC(wchar_t) + __OCTA_HASH_BASIC(short) + __OCTA_HASH_BASIC(ushort) + __OCTA_HASH_BASIC(int) + __OCTA_HASH_BASIC(uint) + __OCTA_HASH_BASIC(long) + __OCTA_HASH_BASIC(ulong) + +#undef __OCTA_HASH_BASIC + + static inline size_t __octa_mem_hash(const void *p, size_t l) { + const uchar *d = (const uchar *)p; + size_t h = 5381; + for (size_t i = 0; i < l; ++i) h = ((h << 5) + h) ^ d[i]; + return h; + } + + template + struct __OctaScalarHash; + + template struct __OctaScalarHash { + typedef T ArgType; + typedef size_t ResultType; + + size_t operator()(T v) const noexcept { + union { T v; size_t h; } u; + u.h = 0; + u.v = v; + return u.h; + } + }; + + template struct __OctaScalarHash { + typedef T ArgType; + typedef size_t ResultType; + + size_t operator()(T v) const noexcept { + union { T v; size_t h; } u; + u.v = v; + return u.h; + } + }; + + template struct __OctaScalarHash { + typedef T ArgType; + typedef size_t ResultType; + + size_t operator()(T v) const noexcept { + union { T v; struct { size_t h1, h2; }; } u; + u.v = v; + return __octa_mem_hash((const void *)&u, sizeof(u)); + } + }; + + template struct __OctaScalarHash { + typedef T ArgType; + typedef size_t ResultType; + + size_t operator()(T v) const noexcept { + union { T v; struct { size_t h1, h2, h3; }; } u; + u.v = v; + return __octa_mem_hash((const void *)&u, sizeof(u)); + } + }; + + template struct __OctaScalarHash { + typedef T ArgType; + typedef size_t ResultType; + + size_t operator()(T v) const noexcept { + union { T v; struct { size_t h1, h2, h3, h4; }; } u; + u.v = v; + return __octa_mem_hash((const void *)&u, sizeof(u)); + } + }; + + template<> struct Hash: __OctaScalarHash {}; + template<> struct Hash: __OctaScalarHash {}; + + template<> struct Hash: __OctaScalarHash { + size_t operator()(float v) const noexcept { + if (v == 0) return 0; + return __OctaScalarHash::operator()(v); + } + }; + + template<> struct Hash: __OctaScalarHash { + size_t operator()(double v) const noexcept { + if (v == 0) return 0; + return __OctaScalarHash::operator()(v); + } + }; + + template<> struct Hash: __OctaScalarHash { + size_t operator()(ldouble v) const noexcept { + if (v == 0) return 0; +#ifdef __i386__ + union { ldouble v; struct { size_t h1, h2, h3, h4; }; } u; + u.h1 = u.h2 = u.h3 = u.h4 = 0; + u.v = v; + return (u.h1 ^ u.h2 ^ u.h3 ^ u.h4); +#else +#ifdef __x86_64__ + union { ldouble v; struct { size_t h1, h2; }; } u; + u.h1 = u.h2 = 0; + u.v = v; + return (u.h1 ^ u.h2); +#else + return __OctaScalarHash::operator()(v); +#endif +#endif + } + }; + + template struct Hash { + typedef T *ArgType; + typedef size_t ResultType; + + size_t operator()(T *v) const noexcept { + union { T *v; size_t h; } u; + u.v = v; + return __octa_mem_hash((const void *)&u, sizeof(u)); + } + }; + /* reference wrapper */ template diff --git a/octa/memory.h b/octa/memory.h index b305263..80a7db1 100644 --- a/octa/memory.h +++ b/octa/memory.h @@ -7,6 +7,7 @@ #define OCTA_MEMORY_H #include "octa/new.h" +#include "octa/utility.h" #include "octa/type_traits.h" namespace octa { diff --git a/octa/new.h b/octa/new.h index 8c1bef8..a2b6401 100644 --- a/octa/new.h +++ b/octa/new.h @@ -6,6 +6,8 @@ #ifndef OCTA_NEW_H #define OCTA_NEW_H +#include + inline void *operator new (size_t, void *p) { return p; } inline void *operator new [](size_t, void *p) { return p; } inline void operator delete (void *, void *) {}