Browse Source
maybe ECS framework can be used to gain more efficiency, but it's just fine for nowV2-origin
24 changed files with 517 additions and 245 deletions
@ -0,0 +1,67 @@ |
|||
#pragma once |
|||
|
|||
#include <functional> |
|||
#include <math/eigen_alias.hpp> |
|||
|
|||
#include <xxhash.h> |
|||
|
|||
namespace detail |
|||
{ |
|||
template <typename T> |
|||
struct float_to_int_type |
|||
{ |
|||
static_assert(std::is_floating_point_v<T>, "T must be a floating point type"); |
|||
using type = std::conditional_t<sizeof(T) == 4, uint32_t, uint64_t>; |
|||
}; |
|||
|
|||
static constexpr float float_hash_epsilon = 1e-6f; |
|||
} |
|||
|
|||
struct hash_funcs_fn |
|||
{ |
|||
template <typename T, int M, int N> |
|||
size_t operator()(const Eigen::Matrix<T, M, N> &mat) const |
|||
{ |
|||
static_assert(M != Eigen::Dynamic && N != Eigen::Dynamic, "only fixed size matrix is supported"); |
|||
|
|||
if constexpr (std::is_integral_v<T>) |
|||
return XXH3_64bits(mat.data(), sizeof(T) * M * N); |
|||
else if constexpr (std::is_floating_point_v<T>) |
|||
{ |
|||
using integral_type = typename detail::float_to_int_type<T>::type; |
|||
Eigen::Matrix<integral_type, M, N> int_mat = (mat.array() / static_cast<T>(detail::float_hash_epsilon)).template cast<integral_type>(); |
|||
return XXH3_64bits(int_mat.data(), sizeof(integral_type) * M * N); |
|||
} |
|||
else |
|||
static_assert([]() { return false; }(), "unsupported type in hash<Eigen::Matrix>"); |
|||
} |
|||
|
|||
template <typename T, int N> |
|||
size_t operator()(const Eigen::Transform<T, N, Eigen::AffineCompact> &trans) const |
|||
{ |
|||
if constexpr (std::is_integral_v<T>) |
|||
return XXH3_64bits(trans.data(), sizeof(T) * N * (N + 1)); |
|||
else if constexpr (std::is_floating_point_v<T>) |
|||
{ |
|||
using integral_type = typename detail::float_to_int_type<T>::type; |
|||
Eigen::Matrix<integral_type, N, N + 1> int_mat = (trans.array() / static_cast<T>(detail::float_hash_epsilon)).template cast<integral_type>(); |
|||
return XXH3_64bits(int_mat.data(), sizeof(integral_type) * N * (N + 1)); |
|||
} |
|||
else |
|||
static_assert([]() { return false; }(), "unsupported type in hash<Eigen::Matrix>"); |
|||
} |
|||
|
|||
template <typename T> |
|||
size_t operator()(std::reference_wrapper<T> ref) const |
|||
{ |
|||
return size_t(std::addressof(ref.get())); |
|||
} |
|||
|
|||
template <typename T> |
|||
size_t operator()(std::reference_wrapper<const T> ref) const |
|||
{ |
|||
return size_t(std::addressof(ref.get())); |
|||
} |
|||
}; |
|||
|
|||
static constexpr hash_funcs_fn hash_funcs{}; |
|||
@ -0,0 +1,40 @@ |
|||
#pragma once |
|||
|
|||
#include <type_traits> |
|||
|
|||
template <typename T> |
|||
struct pointer_wrapper{ |
|||
static_assert(std::is_object_v<T>, "T must be an object type"); |
|||
|
|||
pointer_wrapper() noexcept = default; |
|||
explicit pointer_wrapper(T* p) noexcept : ptr(p) {} |
|||
explicit pointer_wrapper(T&& x) noexcept |
|||
{ |
|||
T& ref = std::forward<T&&>(x); |
|||
ptr = std::addressof(ref); |
|||
} |
|||
|
|||
T& get() const noexcept { return *ptr; } |
|||
auto operator->() const noexcept { return ptr; } |
|||
operator T&() const noexcept { return *ptr; } |
|||
|
|||
T copy() const noexcept { return *ptr; } |
|||
|
|||
auto raw() const noexcept -> T* { return ptr; } |
|||
operator bool() const noexcept { return ptr != nullptr; } |
|||
|
|||
private: |
|||
T* ptr{nullptr}; |
|||
}; |
|||
|
|||
template <typename T> |
|||
auto make_pointer_wrapper(T* p) noexcept -> pointer_wrapper<T> |
|||
{ |
|||
return pointer_wrapper<T>(p); |
|||
} |
|||
|
|||
template <typename T> |
|||
auto make_pointer_wrapper(T& x) noexcept -> pointer_wrapper<T> |
|||
{ |
|||
return pointer_wrapper<T>(x); |
|||
} |
|||
Loading…
Reference in new issue