19#ifndef MORTON_MORTON_HPP
20#define MORTON_MORTON_HPP
35#if (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(__clang__)) && \
36 !defined(__CUDACC__) && !defined(__HIPCC__)
48#ifndef MORTON_ENABLE_RUNTIME_DISPATCH
49#define MORTON_ENABLE_RUNTIME_DISPATCH 0
51#if MORTON_X86 && MORTON_ENABLE_RUNTIME_DISPATCH && !defined(__BMI2__)
52#define MORTON_X86_RUNTIME_DISPATCH 1
54#define MORTON_X86_RUNTIME_DISPATCH 0
57#if MORTON_X86 || defined(__BMI2__)
61#if defined(__SIZEOF_INT128__)
62#define MORTON_HAS_INT128 1
68#ifndef MORTON_MAX_BITS
69#define MORTON_MAX_BITS 256
85#if defined(MORTON_HAS_INT128)
91template <
unsigned NBits>
93#if defined(MORTON_HAS_INT128)
99 (NBits <= 8), std::uint8_t,
101 (NBits <= 16), std::uint16_t,
102 std::conditional_t<(NBits <= 32), std::uint32_t,
104 std::conditional_t<(NBits <= 64), std::uint64_t, uint128_t>
111template <
unsigned NBits>
117#if defined(__cpp_if_consteval)
123#elif defined(__GNUC__) || defined(__clang__)
124 return __builtin_is_constant_evaluated();
133 for (
unsigned i = 0; i < n; ++i)
140template <
unsigned Dim,
unsigned Bits,
typename Code>
143 for (
unsigned i = 0; i < Bits; ++i)
144 m |= (Code(1) << (i * Dim + d));
150template <
unsigned Dim,
unsigned Bits,
typename Code,
typename Coord>
153 for (
unsigned i = 0; i < Bits; ++i)
154 r |= Code(Code(x >> i) & Code(1)) << (i * Dim + d);
159template <
unsigned Dim,
unsigned Bits,
typename Code,
typename Coord>
162 for (
unsigned i = 0; i < Bits; ++i)
163 r |= Coord(Coord(c >> (i * Dim + d)) & Coord(1)) << i;
171inline bool cpu_has_bmi2() {
172 static const bool v = __builtin_cpu_supports(
"bmi2") != 0;
175inline bool cpu_has_avx2() {
176 static const bool v = __builtin_cpu_supports(
"avx2") != 0;
179inline bool cpu_has_avx512f() {
180 static const bool v = __builtin_cpu_supports(
"avx512f") != 0;
185#if MORTON_X86_RUNTIME_DISPATCH
189__attribute__((target(
"bmi2"))) inline std::uint64_t pdep_u64_hw(std::uint64_t v, std::uint64_t m) {
190 return _pdep_u64(v, m);
192__attribute__((target(
"bmi2"))) inline std::uint64_t pext_u64_hw(std::uint64_t v, std::uint64_t m) {
193 return _pext_u64(v, m);
202template <
unsigned Dim,
unsigned Bits>
204 static_assert(
Dim >= 1,
"Dim must be >= 1");
205 static_assert(
Bits >= 1,
"Bits must be >= 1");
207 "Dim * Bits exceeds MORTON_MAX_BITS (raise it if you need wider codes)");
246 template <
typename...
Cs,
typename = std::enable_if_t<
sizeof...(Cs) ==
Dim>>
250 for (
unsigned d = 0;
d <
Dim; ++
d)
258 for (
unsigned d = 0;
d <
Dim; ++
d)
272 std::array<coord_type, Dim>
out{};
273 for (
unsigned d = 0;
d <
Dim; ++
d)
293 code_ = (
s &
M) | (code_ & M_complement(
d));
300 code_ = (
s &
M) | (code_ & M_complement(
d));
307 code_ = (
s &
M) | (code_ & M_complement(
d));
314 code_ = (
s &
M) | (code_ & M_complement(
d));
366 std::array<Morton, 2 * Dim>
out{};
367 for (
unsigned d = 0;
d <
Dim; ++
d) {
383 for (
unsigned d = 0;
d <
Dim; ++
d) {
392 for (
unsigned d = 0;
d <
Dim; ++
d) {
455 return a.code_ ==
b.code_;
458 return a.code_ !=
b.code_;
461 return a.code_ <
b.code_;
464 return a.code_ <=
b.code_;
467 return a.code_ >
b.code_;
470 return a.code_ >=
b.code_;
479#if defined(__BMI2__) && !defined(__CUDA_ARCH__)
482#elif MORTON_X86_RUNTIME_DISPATCH
488 return detail::spread_sw<Dim, Bits, code_type, coord_type>(
x,
d);
493#if defined(__BMI2__) && !defined(__CUDA_ARCH__)
496#elif MORTON_X86_RUNTIME_DISPATCH
501 return detail::compact_sw<Dim, Bits, code_type, coord_type>(
c,
d);
506#if defined(__CUDA_ARCH__)
509 return detail::axis_mask<Dim, Bits, code_type>(
d);
511 return axis_masks_[
d];
522 MORTON_HD static constexpr std::array<code_type, Dim> make_masks() {
523 std::array<code_type, Dim>
a{};
524 for (
unsigned d = 0;
d <
Dim; ++
d)
525 a[
d] = detail::axis_mask<Dim, Bits, code_type>(
d);
528 static constexpr std::array<code_type, Dim> axis_masks_ = make_masks();
538#if defined(MORTON_HAS_INT128)
A Morton (Z-order) code interleaving Dim unsigned coordinates of Bits bits each.
Definition morton.hpp:203
friend MORTON_HD constexpr bool operator>=(Morton a, Morton b) noexcept
Definition morton.hpp:469
MORTON_HD constexpr Morton & operator++() noexcept
Definition morton.hpp:433
static MORTON_HD constexpr coord_type extract(code_type c, unsigned d)
Definition morton.hpp:491
friend MORTON_HD constexpr bool operator<=(Morton a, Morton b) noexcept
Definition morton.hpp:463
MORTON_HD constexpr Morton operator--(int) noexcept
Definition morton.hpp:446
MORTON_HD constexpr void inc(unsigned d)
Increment axis d by one. O(1).
Definition morton.hpp:304
MORTON_HD constexpr void sub_sat(unsigned d, coord_type k)
Subtract k from axis d, clamping at 0 instead of wrapping.
Definition morton.hpp:337
static constexpr code_type field_mask
Mask of all valid code bits (handles code_bits == width without UB).
Definition morton.hpp:223
MORTON_HD constexpr void dec(unsigned d)
Decrement axis d by one. O(1).
Definition morton.hpp:311
detail::uint_for_t< Bits > coord_type
Definition morton.hpp:215
static constexpr unsigned bits_per_axis
Definition morton.hpp:211
static MORTON_HD constexpr Morton encode(Cs... coords)
Encode Dim coordinates into a Morton code.
Definition morton.hpp:247
friend MORTON_HD constexpr bool operator!=(Morton a, Morton b) noexcept
Definition morton.hpp:457
MORTON_HD constexpr code_type code() const noexcept
Definition morton.hpp:265
MORTON_HD constexpr std::array< coord_type, Dim > decode() const
Decode all coordinates.
Definition morton.hpp:271
MORTON_HD constexpr void set(unsigned d, coord_type value)
Replace one axis' coordinate (other axes untouched). Wraps mod 2^Bits.
Definition morton.hpp:279
MORTON_HD constexpr Morton & operator--() noexcept
Definition morton.hpp:442
MORTON_HD constexpr Morton() noexcept
Definition morton.hpp:236
MORTON_HD constexpr void sub(unsigned d, coord_type k)
Subtract k from axis d (wraps). O(1), branchless.
Definition morton.hpp:297
friend MORTON_HD constexpr bool operator==(Morton a, Morton b) noexcept
Definition morton.hpp:454
detail::uint_for_t< Dim *Bits > code_type
Definition morton.hpp:214
static MORTON_HD constexpr code_type axis_mask(unsigned d)
Mask of bits belonging to axis d.
Definition morton.hpp:505
MORTON_HD constexpr void add(unsigned d, coord_type k)
Add k to axis d (wraps). O(1), branchless.
Definition morton.hpp:290
static MORTON_HD constexpr Morton from_code(code_type raw) noexcept
Wrap a raw, already-interleaved code value.
Definition morton.hpp:239
MORTON_HD constexpr std::array< Morton, 2 *Dim > face_neighbors() const
The 2*Dim von Neumann (face) neighbours, ordered {axis0-, axis0+, axis1-, axis1+, ....
Definition morton.hpp:365
MORTON_HD constexpr Morton operator++(int) noexcept
Definition morton.hpp:437
MORTON_HD constexpr coord_type get(unsigned d) const
Decode coordinate of a single axis.
Definition morton.hpp:268
MORTON_HD constexpr Morton neighbor(unsigned d, int dir) const
Morton code of the neighbour one step along ± axis d (wraps).
Definition morton.hpp:318
static MORTON_HD constexpr Morton encode(const std::array< coord_type, Dim > &c)
Encode from an array of coordinates.
Definition morton.hpp:256
MORTON_HD constexpr void add_sat(unsigned d, coord_type k)
Add k to axis d, clamping at coord_max instead of wrapping.
Definition morton.hpp:330
MORTON_HD constexpr bool try_add(unsigned d, coord_type k)
Add k to axis d only if it does not overflow past coord_max.
Definition morton.hpp:344
MORTON_HD constexpr bool try_sub(unsigned d, coord_type k)
Subtract k from axis d only if it does not underflow past 0.
Definition morton.hpp:353
MORTON_HD constexpr std::array< Morton, detail::pow3(Dim) - 1 > all_neighbors() const
The 3^Dim - 1 Moore neighbours (all cells differing by -1/0/+1 on each axis, excluding self),...
Definition morton.hpp:376
MORTON_HD constexpr Morton child(unsigned level, unsigned octant) const
The octant-th child origin of a cell that is an ancestor at level (i.e.
Definition morton.hpp:425
static MORTON_HD constexpr code_type deposit(coord_type x, unsigned d)
Definition morton.hpp:475
friend MORTON_HD constexpr bool operator>(Morton a, Morton b) noexcept
Definition morton.hpp:466
MORTON_HD constexpr unsigned child_index(unsigned level) const
Index (0 .
Definition morton.hpp:419
static constexpr coord_type coord_max
Largest representable coordinate value per axis.
Definition morton.hpp:228
static constexpr unsigned octants
Definition morton.hpp:232
static constexpr unsigned code_bits
Definition morton.hpp:212
friend MORTON_HD constexpr bool operator<(Morton a, Morton b) noexcept
Definition morton.hpp:460
MORTON_HD constexpr Morton ancestor(unsigned level) const
Ancestor cell origin at the given level (clears the low level*Dim bits).
Definition morton.hpp:410
static constexpr unsigned dimensions
Definition morton.hpp:210
The MORTON_HD host/device function marker, shared by every core header.
#define MORTON_HD
Definition hd.hpp:27
#define MORTON_HAS_INT128
Definition morton.hpp:62
#define MORTON_MAX_BITS
Definition morton.hpp:69
typename uint_for< NBits >::type uint_for_t
Definition morton.hpp:112
unsigned __int128 uint128_t
Definition morton.hpp:86
MORTON_HD constexpr Coord compact_sw(Code c, unsigned d)
Definition morton.hpp:160
MORTON_HD constexpr bool is_consteval() noexcept
Definition morton.hpp:116
MORTON_HD constexpr Code axis_mask(unsigned d)
Definition morton.hpp:141
MORTON_HD constexpr Code spread_sw(Coord x, unsigned d)
Definition morton.hpp:151
MORTON_HD constexpr unsigned pow3(unsigned n)
Definition morton.hpp:131
std::conditional_t<(NBits<=8), std::uint8_t, std::conditional_t<(NBits<=16), std::uint16_t, std::conditional_t<(NBits<=32), std::uint32_t, std::conditional_t<(NBits<=64), std::uint64_t, uint128_t > > > > builtin
Definition morton.hpp:108
std::conditional_t<(NBits<=builtin_max), builtin, wide_uint<(NBits+63)/64 > > type
Definition morton.hpp:109
static constexpr unsigned builtin_max
Definition morton.hpp:94
Fixed-width unsigned integer of.
Definition wide_uint.hpp:29
Minimal fixed-width unsigned integer backing Morton codes wider than 128 bits.