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__)
68#ifndef MORTON_MAX_BITS
69#define MORTON_MAX_BITS 256
87template <
unsigned NBits>
89#if defined(MORTON_HAS_INT128)
95 (NBits <= 8), std::uint8_t,
97 (NBits <= 16), std::uint16_t,
98 std::conditional_t<(NBits <= 32), std::uint32_t,
100 std::conditional_t<(NBits <= 64), std::uint64_t, uint128_t>
107template <
unsigned NBits>
113#if defined(__cpp_if_consteval)
119#elif defined(__GNUC__) || defined(__clang__)
120 return __builtin_is_constant_evaluated();
129 for (
unsigned i = 0; i < n; ++i)
136template <
unsigned Dim,
unsigned Bits,
typename Code>
139 for (
unsigned i = 0; i < Bits; ++i)
140 m |= (Code(1) << (i * Dim + d));
146template <
unsigned Dim,
unsigned Bits,
typename Code,
typename Coord>
149 for (
unsigned i = 0; i < Bits; ++i)
150 r |= Code(Code(x >> i) & Code(1)) << (i * Dim + d);
155template <
unsigned Dim,
unsigned Bits,
typename Code,
typename Coord>
158 for (
unsigned i = 0; i < Bits; ++i)
159 r |= Coord(Coord(c >> (i * Dim + d)) & Coord(1)) << i;
167inline bool cpu_has_bmi2() {
168 static const bool v = __builtin_cpu_supports(
"bmi2") != 0;
171inline bool cpu_has_avx2() {
172 static const bool v = __builtin_cpu_supports(
"avx2") != 0;
175inline bool cpu_has_avx512f() {
176 static const bool v = __builtin_cpu_supports(
"avx512f") != 0;
181#if MORTON_X86_RUNTIME_DISPATCH
185__attribute__((target(
"bmi2"))) inline std::uint64_t pdep_u64_hw(std::uint64_t v, std::uint64_t m) {
186 return _pdep_u64(v, m);
188__attribute__((target(
"bmi2"))) inline std::uint64_t pext_u64_hw(std::uint64_t v, std::uint64_t m) {
189 return _pext_u64(v, m);
198template <
unsigned Dim,
unsigned Bits>
200 static_assert(
Dim >= 1,
"Dim must be >= 1");
201 static_assert(
Bits >= 1,
"Bits must be >= 1");
203 "Dim * Bits exceeds MORTON_MAX_BITS (raise it if you need wider codes)");
242 template <
typename...
Cs,
typename = std::enable_if_t<
sizeof...(Cs) ==
Dim>>
246 for (
unsigned d = 0;
d <
Dim; ++
d)
254 for (
unsigned d = 0;
d <
Dim; ++
d)
268 std::array<coord_type, Dim>
out{};
269 for (
unsigned d = 0;
d <
Dim; ++
d)
289 code_ = (
s &
M) | (code_ & M_complement(
d));
296 code_ = (
s &
M) | (code_ & M_complement(
d));
303 code_ = (
s &
M) | (code_ & M_complement(
d));
310 code_ = (
s &
M) | (code_ & M_complement(
d));
362 std::array<Morton, 2 * Dim>
out{};
363 for (
unsigned d = 0;
d <
Dim; ++
d) {
379 for (
unsigned d = 0;
d <
Dim; ++
d) {
388 for (
unsigned d = 0;
d <
Dim; ++
d) {
451 return a.code_ ==
b.code_;
454 return a.code_ !=
b.code_;
457 return a.code_ <
b.code_;
460 return a.code_ <=
b.code_;
463 return a.code_ >
b.code_;
466 return a.code_ >=
b.code_;
475#if defined(__BMI2__) && !defined(__CUDA_ARCH__)
478#elif MORTON_X86_RUNTIME_DISPATCH
484 return detail::spread_sw<Dim, Bits, code_type, coord_type>(
x,
d);
489#if defined(__BMI2__) && !defined(__CUDA_ARCH__)
492#elif MORTON_X86_RUNTIME_DISPATCH
497 return detail::compact_sw<Dim, Bits, code_type, coord_type>(
c,
d);
502#if defined(__CUDA_ARCH__)
505 return detail::axis_mask<Dim, Bits, code_type>(
d);
507 return axis_masks_[
d];
518 MORTON_HD static constexpr std::array<code_type, Dim> make_masks() {
519 std::array<code_type, Dim>
a{};
520 for (
unsigned d = 0;
d <
Dim; ++
d)
521 a[
d] = detail::axis_mask<Dim, Bits, code_type>(
d);
524 static constexpr std::array<code_type, Dim> axis_masks_ = make_masks();
534#if defined(MORTON_HAS_INT128)
A Morton (Z-order) code interleaving Dim unsigned coordinates of Bits bits each.
Definition morton.hpp:199
friend MORTON_HD constexpr bool operator>=(Morton a, Morton b) noexcept
Definition morton.hpp:465
MORTON_HD constexpr Morton & operator++() noexcept
Definition morton.hpp:429
static MORTON_HD constexpr coord_type extract(code_type c, unsigned d)
Definition morton.hpp:487
friend MORTON_HD constexpr bool operator<=(Morton a, Morton b) noexcept
Definition morton.hpp:459
MORTON_HD constexpr Morton operator--(int) noexcept
Definition morton.hpp:442
MORTON_HD constexpr void inc(unsigned d)
Increment axis d by one. O(1).
Definition morton.hpp:300
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:333
static constexpr code_type field_mask
Mask of all valid code bits (handles code_bits == width without UB).
Definition morton.hpp:219
MORTON_HD constexpr void dec(unsigned d)
Decrement axis d by one. O(1).
Definition morton.hpp:307
detail::uint_for_t< Bits > coord_type
Definition morton.hpp:211
static constexpr unsigned bits_per_axis
Definition morton.hpp:207
static MORTON_HD constexpr Morton encode(Cs... coords)
Encode Dim coordinates into a Morton code.
Definition morton.hpp:243
friend MORTON_HD constexpr bool operator!=(Morton a, Morton b) noexcept
Definition morton.hpp:453
MORTON_HD constexpr code_type code() const noexcept
Definition morton.hpp:261
MORTON_HD constexpr std::array< coord_type, Dim > decode() const
Decode all coordinates.
Definition morton.hpp:267
MORTON_HD constexpr void set(unsigned d, coord_type value)
Replace one axis' coordinate (other axes untouched). Wraps mod 2^Bits.
Definition morton.hpp:275
MORTON_HD constexpr Morton & operator--() noexcept
Definition morton.hpp:438
MORTON_HD constexpr Morton() noexcept
Definition morton.hpp:232
MORTON_HD constexpr void sub(unsigned d, coord_type k)
Subtract k from axis d (wraps). O(1), branchless.
Definition morton.hpp:293
friend MORTON_HD constexpr bool operator==(Morton a, Morton b) noexcept
Definition morton.hpp:450
detail::uint_for_t< Dim *Bits > code_type
Definition morton.hpp:210
static MORTON_HD constexpr code_type axis_mask(unsigned d)
Mask of bits belonging to axis d.
Definition morton.hpp:501
MORTON_HD constexpr void add(unsigned d, coord_type k)
Add k to axis d (wraps). O(1), branchless.
Definition morton.hpp:286
static MORTON_HD constexpr Morton from_code(code_type raw) noexcept
Wrap a raw, already-interleaved code value.
Definition morton.hpp:235
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:361
MORTON_HD constexpr Morton operator++(int) noexcept
Definition morton.hpp:433
MORTON_HD constexpr coord_type get(unsigned d) const
Decode coordinate of a single axis.
Definition morton.hpp:264
MORTON_HD constexpr Morton neighbor(unsigned d, int dir) const
Morton code of the neighbour one step along ± axis d (wraps).
Definition morton.hpp:314
static MORTON_HD constexpr Morton encode(const std::array< coord_type, Dim > &c)
Encode from an array of coordinates.
Definition morton.hpp:252
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:326
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:340
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:349
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:372
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:421
static MORTON_HD constexpr code_type deposit(coord_type x, unsigned d)
Definition morton.hpp:471
friend MORTON_HD constexpr bool operator>(Morton a, Morton b) noexcept
Definition morton.hpp:462
MORTON_HD constexpr unsigned child_index(unsigned level) const
Index (0 .
Definition morton.hpp:415
static constexpr coord_type coord_max
Largest representable coordinate value per axis.
Definition morton.hpp:224
static constexpr unsigned octants
Definition morton.hpp:228
static constexpr unsigned code_bits
Definition morton.hpp:208
friend MORTON_HD constexpr bool operator<(Morton a, Morton b) noexcept
Definition morton.hpp:456
MORTON_HD constexpr Morton ancestor(unsigned level) const
Ancestor cell origin at the given level (clears the low level*Dim bits).
Definition morton.hpp:406
static constexpr unsigned dimensions
Definition morton.hpp:206
The MORTON_HD host/device function marker, shared by every core header.
#define MORTON_HD
Definition hd.hpp:27
#define MORTON_MAX_BITS
Definition morton.hpp:69
typename uint_for< NBits >::type uint_for_t
Definition morton.hpp:108
MORTON_HD constexpr Coord compact_sw(Code c, unsigned d)
Definition morton.hpp:156
MORTON_HD constexpr bool is_consteval() noexcept
Definition morton.hpp:112
MORTON_HD constexpr Code axis_mask(unsigned d)
Definition morton.hpp:137
MORTON_HD constexpr Code spread_sw(Coord x, unsigned d)
Definition morton.hpp:147
MORTON_HD constexpr unsigned pow3(unsigned n)
Definition morton.hpp:127
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:104
std::conditional_t<(NBits<=builtin_max), builtin, wide_uint<(NBits+63)/64 > > type
Definition morton.hpp:105
static constexpr unsigned builtin_max
Definition morton.hpp:90
Fixed-width unsigned integer of.
Definition wide_uint.hpp:46
Minimal fixed-width unsigned integer backing Morton codes wider than 128 bits.
#define MORTON_HAS_INT128
Definition wide_uint.hpp:25