#pragma once #include #include #include namespace detail { template struct float_to_int_type { static_assert(std::is_floating_point_v, "T must be a floating point type"); using type = std::conditional_t; }; static constexpr float float_hash_epsilon = 1e-6f; } // namespace detail static inline void hash_combine(size_t &seed, uint32_t value) { seed = seed ^ (std::hash()(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); } static inline void hash_combine(uint64_t &seed, uint64_t value) { seed = seed ^ (std::hash()(value) + 0x9e3779b97f4a7c15ULL + (seed << 12) + (seed >> 4)); } template static inline size_t hash_combine(size_t seed, InputTypes... values) { (hash_combine(seed, values), ...); return seed; } struct hash_funcs_fn { template size_t operator()(const Eigen::Matrix &mat, double epsilon = detail::float_hash_epsilon) const { static_assert(M != Eigen::Dynamic && N != Eigen::Dynamic, "only fixed size matrix is supported"); if constexpr (std::is_integral_v) return XXH3_64bits(mat.data(), sizeof(T) * M * N); else if constexpr (std::is_floating_point_v) { using integral_type = typename detail::float_to_int_type::type; Eigen::Matrix int_mat = (mat.array() / static_cast(epsilon)).template cast(); return XXH3_64bits(int_mat.data(), sizeof(integral_type) * M * N); } else static_assert(false, "unsupported type in hash"); } template size_t operator()(const Eigen::Transform &trans, double epsilon = detail::float_hash_epsilon) const { if constexpr (std::is_integral_v) return XXH3_64bits(trans.data(), sizeof(T) * N * (N + 1)); else if constexpr (std::is_floating_point_v) { using integral_type = typename detail::float_to_int_type::type; Eigen::Matrix int_mat = (trans.affine().array() / static_cast(epsilon)).template cast(); return XXH3_64bits(int_mat.data(), sizeof(integral_type) * N * (N + 1)); } else static_assert(false, "unsupported type in hash"); } template size_t operator()(std::reference_wrapper ref) const { return size_t(std::addressof(ref.get())); } template size_t operator()(std::reference_wrapper ref) const { return size_t(std::addressof(ref.get())); } template size_t operator()(InputIt first, InputIt last) const { using T = std::decay; return XXH3_64bits(&*first, std::distance(first, last) * sizeof(T)); } }; static constexpr hash_funcs_fn hash_funcs{};