You mentioned in TODO that a better naming system is required. I solved the issue by using a combination of tag dispatch, function overloading, and partial specialization of template classes. Please see the implementation in shohirose/morton for details.
A brief overview of my idea is the following:
namespace tag {
// Tags representing each implementation
struct bmi {};
struct preshifted_lookup_table {};
struct lookup_table {};
} // namespace tag
namespace detail {
template <typename MortonCode, typename Coordinate, typename Tag>
class morton2d {};
// Partial specialization of morton2d for tag::bmi
template <typename MortonCode, typename Coordinate>
class morton2d<MortonCode, Coordinate, tag::bmi> {
public:
static MortonCode encode(const Coordinate x, const Coordinate y) noexcept {
// ...
}
static void decode(const MortonCode m, Coordinate& x, Coordinate& y) noexcept {
// ...
}
};
// Partial specialization of morton2d for tag::preshifted_lookup_table
template <typename MortonCode, typename Coordinate>
class morton2d<MortonCode, Coordinate, tag::preshifted_lookup_table> {
// ...
};
// Partial specialization of morton2d for tag::lookup_table
template <typename MortonCode, typename Coordinate>
class morton2d<MortonCode, Coordinate, tag::lookup_table> {
// ...
};
} // namespace detail
// Switch implementation by using a tag dispatch technique.
template <typename Tag>
inline uint_fast32_t encode(const uint_fast16_t x, const uint_fast16_t y, Tag) noexcept {
return detail::morton2d<uint_fast32_t, uint_fast16_t, Tag>::encode(x, y);
}
template <typename Tag>
inline void decode(const uint_fast32_t m, uint_fast16_t& x, uint_fast16_t& y, Tag) noexcept {
detail::morton2d<uint_fast32_t, uint_fast16_t, Tag>::decode(x, y);
}
Then, we can specify an implementation through a uniform API:
uint_fast16_t x = // ...
uint_fast16_t y = // ...
// Encode using BMI instruction set (if available)
const auto m1 = encode(x, y, tag::bmi{});
// Encode using preshifted lookup table
const auto m2 = encode(x, y, tag::preshifted_lookup_table{});
// Encode using lookup table
const auto m3 = encode(x, y, tag::lookup_table{});
Hi,
You mentioned in TODO that a better naming system is required. I solved the issue by using a combination of tag dispatch, function overloading, and partial specialization of template classes. Please see the implementation in shohirose/morton for details.
A brief overview of my idea is the following:
Then, we can specify an implementation through a uniform API:
I hope this might help you.