DAW JSON Link
daw_murmur3.h
Go to the documentation of this file.
1 // Copyright (c) Darrell Wright
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //
6 // Official repository: https://github.com/beached/daw_json_link
7 //
8 
9 #pragma once
10 
11 #include "version.h"
12 
13 #include <daw/daw_do_n.h>
14 #include <daw/daw_endian.h>
15 #include <daw/daw_string_view.h>
16 #include <daw/daw_uint_buffer.h>
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <iterator>
21 
22 namespace daw {
23  namespace murmur3_details {
24  [[nodiscard]] DAW_ATTRIB_FLATINLINE static inline constexpr UInt32
25  murmur3_32_scramble( UInt32 k ) {
26  using prime1 = daw::constant<0xcc9e'2d51_u32>;
27  using prime2 = daw::constant<0x1b87'3593_u32>;
28  k *= prime1::value;
29  k = rotate_left<15>( k );
30  k *= prime2::value;
31  return k;
32  }
33  } // namespace murmur3_details
34 
35  template<std::size_t N, typename CharT>
36  DAW_ATTRIB_NONNULL( )
37  [[nodiscard]] DAW_ATTRIB_INLINE static constexpr UInt32
38  fnv1a_32_N( CharT *first, UInt32 hash = 0x811c'9dc5_u32 ) {
39  daw::algorithm::do_n_arg<N>( [&]( std::size_t n ) {
40  hash ^= static_cast<UInt32>( static_cast<unsigned char>( first[n] ) );
41  hash *= 0x0100'0193_u32;
42  } );
43  return hash;
44  }
45 
46  template<bool expect_long_strings, typename StringView>
47  [[nodiscard]] static constexpr UInt32 fnv1a_32( StringView key ) {
48  static_assert( daw::traits::is_string_view_like_v<StringView>,
49  "Can only pass contiguous character ranges to fnv1a" );
50  std::size_t len = std::size( key );
51  auto *ptr = std::data( key );
52  auto hash = 0x811c'9dc5_u32;
53  if constexpr( expect_long_strings ) {
54  while( DAW_UNLIKELY( len >= 8 ) ) {
55  hash = fnv1a_32_N<8>( ptr, hash );
56  len -= 8;
57  ptr += 8;
58  }
59  if( len >= 4 ) {
60  hash = fnv1a_32_N<4>( ptr, hash );
61  len -= 4;
62  ptr += 4;
63  }
64  }
65  for( std::size_t n = 0; n < len; ++n ) {
66  hash ^= static_cast<unsigned char>( ptr[n] );
67  hash *= 0x0100'0193_u32;
68  }
69  return hash;
70  }
71 
72  template<bool expect_long_strings>
73  [[nodiscard]] DAW_ATTRIB_INLINE static constexpr UInt32
74  name_hash( daw::string_view key ) {
75  if( auto const Sz = std::size( key );
76  DAW_LIKELY( Sz <= sizeof( UInt32 ) ) ) {
77  auto result = 0_u32;
78  auto const *ptr = std::data( key );
79  for( std::size_t n = 0; n < Sz; ++n ) {
80  result <<= 8U;
81  result |= static_cast<unsigned char>( ptr[n] );
82  }
83  return result * 0xCC9E'2d51UL; // mix it up with an fnv1a prime
84  }
85  return fnv1a_32<expect_long_strings>( key );
86  }
87 
88  template<typename StringView>
89  [[nodiscard]] static constexpr UInt32 murmur3_32( StringView key,
90  std::uint32_t seed = 0 ) {
91  static_assert( daw::traits::is_string_view_like_v<StringView>,
92  "Can only pass contiguous character ranges to fnv1a" );
93  UInt32 h = to_uint32( seed );
94  UInt32 k = 0_u32;
95  char const *first = std::data( key );
96  char const *const last = daw::data_end( key );
97  while( ( last - first ) >= 4 ) {
98  // Here is a source of differing results across endianness.
99  // A swap here has no effects on hash properties though.
100  k = daw::to_uint32_buffer( first );
101  first += 4;
102  h ^= murmur3_details::murmur3_32_scramble( k );
103  h = rotate_left<13>( h );
104  h = h * 5 + 0xe654'6b64_u32;
105  }
106 
107  // Anything left over
108  k = 0_u32;
109  for( auto i = ( last - first ); i > 0; --i ) {
110  k <<= 8U;
111  k |= static_cast<unsigned char>( first[i - 1] );
112  }
113 
114  h ^= murmur3_details::murmur3_32_scramble( k );
115 
116  h ^= to_uint32( std::size( key ) );
117  h ^= h >> 16U;
118  h *= 0x85eb'ca6b_u32;
119  h ^= h >> 13U;
120  h *= 0xc2b2'ae35_u32;
121  h ^= h >> 16U;
122  return h;
123  }
124 } // namespace daw
static constexpr UInt32 murmur3_32(StringView key, std::uint32_t seed=0)
Definition: daw_murmur3.h:89
static constexpr UInt32 fnv1a_32(StringView key)
Definition: daw_murmur3.h:47
static constexpr DAW_ATTRIB_INLINE UInt32 fnv1a_32_N(CharT *first, UInt32 hash=0x811c '9dc5_u32)
Definition: daw_murmur3.h:38
static constexpr DAW_ATTRIB_INLINE UInt32 name_hash(daw::string_view key)
Definition: daw_murmur3.h:74