text: // Copyright 2014 the V8 project authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  //
  // This also contains public domain code from MurmurHash. From the
  // MurmurHash header:
  //
  // MurmurHash3 was written by Austin Appleby, and is placed in the public
  // domain. The author hereby disclaims copyright to this source code.
  
  #include "src/base/functional.h"
  
  #include <limits>
  
  #include "src/base/bits.h"
  
  namespace v8 {
  namespace base {
  
  namespace {
  
  // Thomas Wang, Integer Hash Functions.
  // https://gist.github.com/badboy/6267743
  template <typename T>
  V8_INLINE size_t hash_value_unsigned(T v) {
    switch (sizeof(T)) {
      case 4: {
        // "32 bit Mix Functions"
        v = ~v + (v << 15);  // v = (v << 15) - v - 1;
        v = v ^ (v >> 12);
        v = v + (v << 2);
        v = v ^ (v >> 4);
        v = v * 2057;  // v = (v + (v << 3)) + (v << 11);
        v = v ^ (v >> 16);
        return static_cast<size_t>(v);
      }
      case 8: {
        switch (sizeof(size_t)) {
          case 4: {
            // "64 bit to 32 bit Hash Functions"
            v = ~v + (v << 18);  // v = (v << 18) - v - 1;
            v = v ^ (v >> 31);
            v = v * 21;  // v = (v + (v << 2)) + (v << 4);
            v = v ^ (v >> 11);
            v = v + (v << 6);
            v = v ^ (v >> 22);
            return static_cast<size_t>(v);
          }
          case 8: {
            // "64 bit Mix Functions"
            v = ~v + (v << 21);  // v = (v << 21) - v - 1;
            v = v ^ (v >> 24);
            v = (v + (v << 3)) + (v << 8);  // v * 265
            v = v ^ (v >> 14);
            v = (v + (v << 2)) + (v << 4);  // v * 21
            v = v ^ (v >> 28);
            v = v + (v << 31);
            return static_cast<size_t>(v);
          }
        }
      }
    }
    UNREACHABLE();
    return static_cast<size_t>(v);
  }
  
  }  // namespace
  
  
  // This code was taken from MurmurHash.
  size_t hash_combine(size_t seed, size_t value) {
  #if V8_HOST_ARCH_32_BIT
    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;
  
    value *= c1;
    value = bits::RotateRight32(value, 15);
    value *= c2;
  
    seed ^= value;
    seed = bits::RotateRight32(seed, 13);
    seed = seed * 5 + 0xe6546b64;
  #else
    const uint64_t m = V8_UINT64_C(0xc6a4a7935bd1e995);
    const uint32_t r = 47;
  
    value *= m;
    value ^= value >> r;
    value *= m;
  
    seed ^= value;
    seed *= m;
  #endif  // V8_HOST_ARCH_32_BIT
    return seed;
  }
  
  
  size_t hash_value(unsigned int v) { return hash_value_unsigned(v); }
  
  
  size_t hash_value(unsigned long v) {  // NOLINT(runtime/int)
    return hash_value_unsigned(v);
  }
  
  
  size_t hash_value(unsigned long long v) {  // NOLINT(runtime/int)
    return hash_value_unsigned(v);
  }
  
  }  // namespace base
  }  // namespace v8
  