Browse Source

chore: cleanup

Sam Jaffe 1 year ago
parent
commit
886e14e046
2 changed files with 36 additions and 36 deletions
  1. 5 9
      graphics/src/helper.hpp
  2. 31 27
      util/include/game/util/hash.hpp

+ 5 - 9
graphics/src/helper.hpp

@@ -16,8 +16,7 @@
 
 #include "game/graphics/graphics_fwd.h"
 
-namespace graphics {
-namespace textures {
+namespace graphics::textures {
 enum class format : unsigned int { RGB, RGBA };
 struct external_data {
   external_data(std::string const & abs_path);
@@ -27,24 +26,21 @@ struct external_data {
   void * buffer;
 };
 }
-namespace shaders {
+namespace graphics::shaders {
 enum class type : unsigned int { FRAGMENT, VERTEX };
 }
-namespace materials {
+namespace graphics::materials {
 enum class uniform : unsigned int { NORMAL, DIFFUSE, SPECULAR };
 }
-}
 
-namespace std {
-template <> struct hash<graphics::shaders::type> {
+template <> struct std::hash<graphics::shaders::type> {
   std::size_t operator()(graphics::shaders::type tp) const {
     return std::hash<unsigned int>()(static_cast<unsigned int>(tp));
   }
 };
 
-template <> struct hash<graphics::materials::uniform> {
+template <> struct std::hash<graphics::materials::uniform> {
   std::size_t operator()(graphics::materials::uniform uf) const {
     return std::hash<unsigned int>()(static_cast<unsigned int>(uf));
   }
 };
-}

+ 31 - 27
util/include/game/util/hash.hpp

@@ -8,6 +8,7 @@
 
 #pragma once
 
+#include <cstdint>
 #include <tuple>
 #include <utility>
 
@@ -17,40 +18,43 @@ template <typename, typename> class identity;
   struct ::std::hash<T>                                                        \
       : public ::std::hash<identity<T, decltype(std::declval<T>().id)>> {}
 
-namespace std {
-template <typename T, typename I> struct hash<identity<T, I>> {
-  std::size_t operator()(identity<T, I> tp) const {
-    return std::hash<I>()(tp.id);
-  }
-};
-
-template <typename T, typename S> struct hash<std::pair<T, S>> {
-  std::size_t operator()(std::pair<T, S> const & pair) const {
-    return std::hash<T>()(pair.first) ^ std::hash<S>()(pair.second);
-  }
-};
+namespace detail {
+// Code from boost
+// Reciprocal of the golden ratio helps spread entropy
+//     and handles duplicates.
+// See Mike Seymour in magic-numbers-in-boosthash-combine:
+//     http://stackoverflow.com/questions/4948780
+template <typename T> void hash_combine(size_t & seed, T const & v) {
+  seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
 
-template <std::size_t I> struct tuple_hash;
+template <typename T, size_t... Is>
+void hash_combine(size_t & seed, T const & tuple, std::index_sequence<Is...>) {
+  // Expansion trick
+  [[maybe_unused]] int _[] = {(hash_combine(seed, std::get<Is>(tuple)), 0),
+                              ...};
+}
+}
 
-template <> struct tuple_hash<0> {
-  template <typename... As>
-  std::size_t operator()(std::tuple<As...> const &) const {
-    return 0;
+template <typename T, typename I> struct std::hash<identity<T, I>> {
+  std::size_t operator()(identity<T, I> tp) const {
+    return std::hash<I>()(tp.id);
   }
 };
 
-template <std::size_t I> struct tuple_hash {
-  template <typename... As>
-  std::size_t operator()(std::tuple<As...> const & tuple) const {
-    using elt = typename std::tuple_element<I - 1, std::tuple<As...>>::type;
-    return std::hash<elt>()(std::get<I - 1>(tuple)) ^
-           tuple_hash<I - 1>()(tuple);
+template <typename T, typename S> struct std::hash<std::pair<T, S>> {
+  size_t operator()(std::pair<T, S> const & pair) const {
+    size_t seed = 0;
+    detail::hash_combine(seed, pair, std::make_index_sequence<2>{});
+    return seed;
   }
 };
 
-template <typename... As> struct hash<std::tuple<As...>> {
-  std::size_t operator()(std::tuple<As...> const & tuple) const {
-    return tuple_hash<sizeof...(As)>()(tuple);
+template <typename... As> struct std::hash<std::tuple<As...>> {
+  size_t operator()(std::tuple<As...> const & tuple) const {
+    size_t seed = 0;
+    detail::hash_combine(seed, tuple,
+                         std::make_index_sequence<sizeof...(As)>{});
+    return seed;
   }
 };
-}