54#include <ufo/numeric/vec.hpp>
73template <std::
size_t Dim, std::
unsigned_
integral T, std::
size_t Offset>
74constexpr inline T MortonMask = [] {
76 std::size_t bits = std::numeric_limits<T>::digits;
77 for (std::size_t i = 0; i < bits / Dim; ++i) {
78 mask |= T(1) << (i * Dim + Offset);
83template <std::
size_t Dim, std::
unsigned_
integral T, std::
size_t Offset = 0>
84 requires(Dim >= 1 && Offset < Dim)
85[[nodiscard]]
constexpr T spread(T x)
87 if constexpr (1 == Dim) {
92 if constexpr (
sizeof(T) == 4) {
93 return _pdep_u32(
static_cast<std::uint32_t
>(x),
94 MortonMask<Dim, std::uint32_t, Offset>);
95 }
else if constexpr (
sizeof(T) == 8) {
96 return _pdep_u64(
static_cast<std::uint64_t
>(x),
97 MortonMask<Dim, std::uint64_t, Offset>);
101 if constexpr (0 != Offset) {
102 return spread<Dim, T, 0>(x) << Offset;
103 }
else if constexpr (2 == Dim) {
105 if constexpr (
sizeof(T) == 8) {
106 m &= 0x00000000FFFFFFFF;
107 m = (m | (m << 16)) & 0x0000FFFF0000FFFF;
108 m = (m | (m << 8)) & 0x00FF00FF00FF00FF;
109 m = (m | (m << 4)) & 0x0F0F0F0F0F0F0F0F;
110 m = (m | (m << 2)) & 0x3333333333333333;
111 m = (m | (m << 1)) & 0x5555555555555555;
114 m = (m | (m << 8)) & 0x00FF00FF;
115 m = (m | (m << 4)) & 0x0F0F0F0F;
116 m = (m | (m << 2)) & 0x33333333;
117 m = (m | (m << 1)) & 0x55555555;
120 }
else if constexpr (3 == Dim) {
122 if constexpr (
sizeof(T) == 8) {
124 m = (m | m << 32) & 0x1F00000000FFFF;
125 m = (m | m << 16) & 0x1F0000FF0000FF;
126 m = (m | m << 8) & 0x100F00F00F00F00F;
127 m = (m | m << 4) & 0x10C30C30C30C30C3;
128 m = (m | m << 2) & 0x1249249249249249;
131 m = (m | m << 16) & 0x30000FF;
132 m = (m | m << 8) & 0x300F00F;
133 m = (m | m << 4) & 0x30C30C3;
134 m = (m | m << 2) & 0x9249249;
139 std::size_t bits = std::numeric_limits<T>::digits / Dim;
140 for (std::size_t i = 0; i < bits; ++i) {
141 res |= (x & (T(1) << i)) << (i * (Dim - 1));
148template <std::
size_t Dim, std::
unsigned_
integral T, std::
size_t Offset = 0>
149 requires(Dim >= 1 && Offset < Dim)
150[[nodiscard]]
constexpr T compact(T m)
152 if constexpr (1 == Dim) {
157 if constexpr (
sizeof(T) == 4) {
158 return _pext_u32(
static_cast<std::uint32_t
>(m),
159 MortonMask<Dim, std::uint32_t, Offset>);
160 }
else if constexpr (
sizeof(T) == 8) {
161 return _pext_u64(
static_cast<std::uint64_t
>(m),
162 MortonMask<Dim, std::uint64_t, Offset>);
166 if constexpr (0 != Offset) {
167 return compact<Dim, T, 0>(m >> Offset);
168 }
else if constexpr (2 == Dim) {
169 T x(m & MortonMask<Dim, T, 0>);
170 if constexpr (
sizeof(T) == 8) {
171 x = (x ^ (x >> 1)) & 0x3333333333333333;
172 x = (x ^ (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
173 x = (x ^ (x >> 4)) & 0x00FF00FF00FF00FF;
174 x = (x ^ (x >> 8)) & 0x0000FFFF0000FFFF;
175 x = (x ^ (x >> 16)) & 0x00000000FFFFFFFF;
177 x = (x ^ (x >> 1)) & 0x33333333;
178 x = (x ^ (x >> 2)) & 0x0F0F0F0F;
179 x = (x ^ (x >> 4)) & 0x00FF00FF;
180 x = (x ^ (x >> 8)) & 0x0000FFFF;
183 }
else if constexpr (3 == Dim) {
184 T x(m & MortonMask<Dim, T, 0>);
185 if constexpr (
sizeof(T) == 8) {
186 x = (x ^ (x >> 2)) & 0x10C30C30C30C30C3;
187 x = (x ^ (x >> 4)) & 0x100F00F00F00F00F;
188 x = (x ^ (x >> 8)) & 0x1F0000FF0000FF;
189 x = (x ^ (x >> 16)) & 0x1F00000000FFFF;
190 x = (x ^ (x >> 32)) & 0x1FFFFF;
192 x = (x ^ (x >> 2)) & 0x30C30C3;
193 x = (x ^ (x >> 4)) & 0x300F00F;
194 x = (x ^ (x >> 8)) & 0x30000FF;
195 x = (x ^ (x >> 16)) & 0x3FF;
200 std::size_t bits = std::numeric_limits<T>::digits / Dim;
201 for (std::size_t i = 0; i < bits; ++i) {
202 res |= (m & (T(1) << (i * Dim))) >> (i * (Dim - 1));
211template <std::
size_t Dim>
213 static constexpr std::uint32_t X_M_32 = detail::MortonMask<Dim, std::uint32_t, 0>;
214 static constexpr std::uint64_t X_M_64 = detail::MortonMask<Dim, std::uint64_t, 0>;
216 static constexpr std::size_t LEVELS_32 = 32 / Dim;
217 static constexpr std::size_t LEVELS_64 = 64 / Dim;
219 template <std::convertible_to<std::u
int32_t>... Args>
220 requires(
sizeof...(Args) == Dim)
221 [[nodiscard]]
static constexpr std::uint32_t encode32(Args... args)
223 return encode_impl<std::uint32_t>(std::make_index_sequence<Dim>{},
224 static_cast<std::uint32_t
>(args)...);
229 return std::apply([](
auto... args) {
return encode32(args...); }, v.fields);
232 template <std::convertible_to<std::u
int32_t>... Args>
233 requires(
sizeof...(Args) == Dim)
234 [[nodiscard]]
static constexpr std::uint64_t encode64(Args... args)
236 return encode_impl<std::uint64_t>(std::make_index_sequence<Dim>{},
237 static_cast<std::uint32_t
>(args)...);
242 return std::apply([](
auto... args) {
return encode64(args...); }, v.fields);
247 return decode_impl<std::uint32_t>(m, std::make_index_sequence<Dim>{});
250 [[nodiscard]]
static constexpr std::uint32_t decode32(std::uint32_t m, std::size_t pos)
253 return decode_pos_impl<std::uint32_t>(m, pos, std::make_index_sequence<Dim>{});
258 return decode_impl<std::uint64_t>(m, std::make_index_sequence<Dim>{});
261 [[nodiscard]]
static constexpr std::uint32_t decode64(std::uint64_t m, std::size_t pos)
264 return decode_pos_impl<std::uint64_t>(m, pos, std::make_index_sequence<Dim>{});
267 [[nodiscard]]
static constexpr std::uint32_t spread32(std::uint32_t x)
269 return detail::spread<Dim, std::uint32_t, 0>(x);
272 [[nodiscard]]
static constexpr std::uint64_t spread64(std::uint32_t x)
274 return detail::spread<Dim, std::uint64_t, 0>(
static_cast<std::uint64_t
>(x));
277 [[nodiscard]]
static constexpr std::uint32_t compact32(std::uint32_t m)
279 return detail::compact<Dim, std::uint32_t, 0>(m);
282 [[nodiscard]]
static constexpr std::uint32_t compact64(std::uint64_t m)
284 return static_cast<std::uint32_t
>(detail::compact<Dim, std::uint64_t, 0>(m));
288 template <std::unsigned_integral T, std::size_t... Is, std::convertible_to<T>... Args>
289 [[nodiscard]]
static constexpr T encode_impl(std::index_sequence<Is...>, Args... args)
291 return (detail::spread<Dim, T, Is>(
static_cast<T
>(args)) | ...);
294 template <std::unsigned_integral T, std::size_t... Is>
296 T m, std::index_sequence<Is...>)
299 static_cast<std::uint32_t
>(detail::compact<Dim, T, Is>(m))...);
302 template <std::unsigned_integral T, std::size_t... Is>
303 [[nodiscard]]
static constexpr std::uint32_t decode_pos_impl(T m, std::size_t pos,
304 std::index_sequence<Is...>)
307 ((Is == pos ? res =
static_cast<std::uint32_t
>(detail::compact<Dim, T, Is>(m)) : 0),
All vision-related classes and functions.
A fixed-size arithmetic vector of up to 4 dimensions.