#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; } struct hash_funcs_fn { template size_t operator()(const Eigen::Matrix &mat) 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(detail::float_hash_epsilon)).template cast(); return XXH3_64bits(int_mat.data(), sizeof(integral_type) * M * N); } else static_assert([]() { return false; }(), "unsupported type in hash"); } template size_t operator()(const Eigen::Transform &trans) 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.array() / static_cast(detail::float_hash_epsilon)).template cast(); return XXH3_64bits(int_mat.data(), sizeof(integral_type) * N * (N + 1)); } else static_assert([]() { return 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())); } }; static constexpr hash_funcs_fn hash_funcs{};