Mantid
Loading...
Searching...
No Matches
BitInterleaving.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#pragma once
8
9#include <cinttypes>
10#include <cstddef>
11
12#include "Types.h"
13
14namespace morton_index {
15
24template <size_t N, typename IntT, typename MortonT> MortonT pad(IntT) {
25 throw std::runtime_error("No pad() specialisation.");
26}
27
37template <size_t N, typename IntT, typename MortonT> IntT compact(MortonT) {
38 throw std::runtime_error("No compact() specialisation.");
39}
40
41/* Bit masks used for pad and compact operations are derived using
42 * docs/bit_padding_generator.py. */
43/* For more details see docs/bit_cppierleaving.md. */
44
45template <> inline uint32_t pad<1, uint16_t, uint32_t>(uint16_t v) {
46 uint32_t x(v);
47 x &= 0xffff;
48 x = (x | x << 8) & 0xff00ff;
49 x = (x | x << 4) & 0xf0f0f0f;
50 x = (x | x << 2) & 0x33333333;
51 x = (x | x << 1) & 0x55555555;
52 return x;
53}
54
55template <> inline uint16_t compact<1, uint16_t, uint32_t>(uint32_t x) {
56 x &= 0x55555555;
57 x = (x | x >> 1) & 0x33333333;
58 x = (x | x >> 2) & 0xf0f0f0f;
59 x = (x | x >> 4) & 0xff00ff;
60 x = (x | x >> 8) & 0xffff;
61 return (uint16_t)x;
62}
63
64template <> inline uint64_t pad<1, uint16_t, uint64_t>(uint16_t v) {
65 uint64_t x(v);
66 x &= 0xffff;
67 x = (x | x << 8) & 0xff00ff;
68 x = (x | x << 4) & 0xf0f0f0f;
69 x = (x | x << 2) & 0x33333333;
70 x = (x | x << 1) & 0x55555555;
71 return x;
72}
73
74template <> inline uint16_t compact<1, uint16_t, uint64_t>(uint64_t x) {
75 x &= 0x55555555;
76 x = (x | x >> 1) & 0x33333333;
77 x = (x | x >> 2) & 0xf0f0f0f;
78 x = (x | x >> 4) & 0xff00ff;
79 x = (x | x >> 8) & 0xffff;
80 return (uint16_t)x;
81}
82
83template <> inline uint32_t pad<2, uint8_t, uint32_t>(uint8_t v) {
84 uint32_t x(v);
85 x &= 0xff;
86 x = (x | x << 8) & 0xf00f;
87 x = (x | x << 4) & 0xc30c3;
88 x = (x | x << 2) & 0x249249;
89 return x;
90}
91
92template <> inline uint8_t compact<2, uint8_t, uint32_t>(uint32_t x) {
93 x &= 0x249249;
94 x = (x | x >> 2) & 0xc30c3;
95 x = (x | x >> 4) & 0xf00f;
96 x = (x | x >> 8) & 0xff;
97 return (uint8_t)x;
98}
99
100template <> inline uint64_t pad<2, uint16_t, uint64_t>(uint16_t v) {
101 uint64_t x(v);
102 x &= 0xffff;
103 x = (x | x << 16) & 0xff0000ff;
104 x = (x | x << 8) & 0xf00f00f00f;
105 x = (x | x << 4) & 0xc30c30c30c3;
106 x = (x | x << 2) & 0x249249249249;
107 return x;
108}
109
110template <> inline uint16_t compact<2, uint16_t, uint64_t>(uint64_t x) {
111 x &= 0x249249249249;
112 x = (x | x >> 2) & 0xc30c30c30c3;
113 x = (x | x >> 4) & 0xf00f00f00f;
114 x = (x | x >> 8) & 0xff0000ff;
115 x = (x | x >> 16) & 0xffff;
116 return (uint16_t)x;
117}
118
119template <> inline uint64_t pad<3, uint16_t, uint64_t>(uint16_t v) {
120 uint64_t x(v);
121 x &= 0xffff;
122 x = (x | x << 32) & 0xf800000007ff;
123 x = (x | x << 16) & 0xf80007c0003f;
124 x = (x | x << 8) & 0xc0380700c03807;
125 x = (x | x << 4) & 0x843084308430843;
126 x = (x | x << 2) & 0x909090909090909;
127 x = (x | x << 1) & 0x1111111111111111;
128 return x;
129}
130
131template <> inline uint16_t compact<3, uint16_t, uint64_t>(uint64_t x) {
132 x &= 0x1111111111111111;
133 x = (x | x >> 1) & 0x909090909090909;
134 x = (x | x >> 2) & 0x843084308430843;
135 x = (x | x >> 4) & 0xc0380700c03807;
136 x = (x | x >> 8) & 0xf80007c0003f;
137 x = (x | x >> 16) & 0xf800000007ff;
138 x = (x | x >> 32) & 0xffff;
139 return (uint16_t)x;
140}
141
142template <> inline uint128_t pad<1, uint32_t, uint128_t>(uint32_t v) {
143 uint128_t x(v);
144 x &= 0xffffffff_cppui128;
145 x = (x | x << 16) & 0xffff0000ffff_cppui128;
146 x = (x | x << 8) & 0xff00ff00ff00ff_cppui128;
147 x = (x | x << 4) & 0xf0f0f0f0f0f0f0f_cppui128;
148 x = (x | x << 2) & 0x3333333333333333_cppui128;
149 x = (x | x << 1) & 0x5555555555555555_cppui128;
150 return x;
151}
152
153template <> inline uint32_t compact<1, uint32_t, uint128_t>(uint128_t x) {
154
155 x &= 0x5555555555555555_cppui128;
156 x = (x | x >> 1) & 0x3333333333333333_cppui128;
157 x = (x | x >> 2) & 0xf0f0f0f0f0f0f0f_cppui128;
158 x = (x | x >> 4) & 0xff00ff00ff00ff_cppui128;
159 x = (x | x >> 8) & 0xffff0000ffff_cppui128;
160 x = (x | x >> 16) & 0xffffffff_cppui128;
161 return (uint32_t)x;
162}
163
164template <> inline uint128_t pad<2, uint32_t, uint128_t>(uint32_t v) {
165
166 uint128_t x(v);
167 x &= 0xffffffff_cppui128;
168 x = (x | x << 32) & 0xffff00000000ffff_cppui128;
169 x = (x | x << 16) & 0xff0000ff0000ff0000ff_cppui128;
170 x = (x | x << 8) & 0xf00f00f00f00f00f00f00f_cppui128;
171 x = (x | x << 4) & 0xc30c30c30c30c30c30c30c3_cppui128;
172 x = (x | x << 2) & 0x249249249249249249249249_cppui128;
173 return x;
174}
175
176template <> inline uint32_t compact<2, uint32_t, uint128_t>(uint128_t x) {
177
178 x &= 0x249249249249249249249249_cppui128;
179 x = (x | x >> 2) & 0xc30c30c30c30c30c30c30c3_cppui128;
180 x = (x | x >> 4) & 0xf00f00f00f00f00f00f00f_cppui128;
181 x = (x | x >> 8) & 0xff0000ff0000ff0000ff_cppui128;
182 x = (x | x >> 16) & 0xffff00000000ffff_cppui128;
183 x = (x | x >> 32) & 0xffffffff_cppui128;
184 return (uint32_t)x;
185}
186
187template <> inline uint128_t pad<3, uint32_t, uint128_t>(uint32_t v) {
188
189 uint128_t x(v);
190 x &= 0xffffffff_cppui128;
191 x = (x | x << 64) & 0xffc0000000000000003fffff_cppui128;
192 x = (x | x << 32) & 0xffc00000003ff800000007ff_cppui128;
193 x = (x | x << 16) & 0xf80007c0003f0000f80007c0003f_cppui128;
194 x = (x | x << 8) & 0xc0380700c0380700c0380700c03807_cppui128;
195 x = (x | x << 4) & 0x8430843084308430843084308430843_cppui128;
196 x = (x | x << 2) & 0x9090909090909090909090909090909_cppui128;
197 x = (x | x << 1) & 0x11111111111111111111111111111111_cppui128;
198 return x;
199}
200
201template <> inline uint32_t compact<3, uint32_t, uint128_t>(uint128_t x) {
202
203 x &= 0x11111111111111111111111111111111_cppui128;
204 x = (x | x >> 1) & 0x9090909090909090909090909090909_cppui128;
205 x = (x | x >> 2) & 0x8430843084308430843084308430843_cppui128;
206 x = (x | x >> 4) & 0xc0380700c0380700c0380700c03807_cppui128;
207 x = (x | x >> 8) & 0xf80007c0003f0000f80007c0003f_cppui128;
208 x = (x | x >> 16) & 0xffc00000003ff800000007ff_cppui128;
209 x = (x | x >> 32) & 0xffc0000000000000003fffff_cppui128;
210 x = (x | x >> 64) & 0xffffffff_cppui128;
211 return (uint32_t)x;
212}
213
214template <> inline uint256_t pad<2, uint64_t, uint256_t>(uint64_t v) {
215
216 uint256_t x(v);
217 x &= 0xffffffffffffffff_cppui256;
218 x = (x | x << 64) & 0xffffffff0000000000000000ffffffff_cppui256;
219 x = (x | x << 32) & 0xffff00000000ffff00000000ffff00000000ffff_cppui256;
220 x = (x | x << 16) & 0xff0000ff0000ff0000ff0000ff0000ff0000ff0000ff_cppui256;
221 x = (x | x << 8) & 0xf00f00f00f00f00f00f00f00f00f00f00f00f00f00f00f_cppui256;
222 x = (x | x << 4) & 0xc30c30c30c30c30c30c30c30c30c30c30c30c30c30c30c3_cppui256;
223 x = (x | x << 2) & 0x249249249249249249249249249249249249249249249249_cppui256;
224 return x;
225}
226
227template <> inline uint64_t compact<2, uint64_t, uint256_t>(uint256_t x) {
228
229 x &= 0x249249249249249249249249249249249249249249249249_cppui256;
230 x = (x | x >> 2) & 0xc30c30c30c30c30c30c30c30c30c30c30c30c30c30c30c3_cppui256;
231 x = (x | x >> 4) & 0xf00f00f00f00f00f00f00f00f00f00f00f00f00f00f00f_cppui256;
232 x = (x | x >> 8) & 0xff0000ff0000ff0000ff0000ff0000ff0000ff0000ff_cppui256;
233 x = (x | x >> 16) & 0xffff00000000ffff00000000ffff00000000ffff_cppui256;
234 x = (x | x >> 32) & 0xffffffff0000000000000000ffffffff_cppui256;
235 x = (x | x >> 64) & 0xffffffffffffffff_cppui256;
236 return (uint64_t)x;
237}
238
239template <> inline uint256_t pad<3, uint64_t, uint256_t>(uint64_t v) {
240
241 uint256_t x(v);
242 x &= 0xffffffffffffffff_cppui256;
243 x = (x | x << 128) & 0xfffff800000000000000000000000000000007ffffffffff_cppui256;
244 x = (x | x << 64) & 0xfffff80000000000000007ffffc0000000000000003fffff_cppui256;
245 x = (x | x << 32) & 0xffc00000003ff800000007ff00000000ffc00000003ff800000007ff_cppui256;
246 x = (x | x << 16) & 0xf80007c0003f0000f80007c0003f0000f80007c0003f0000f80007c0003f_cppui256;
247 x = (x | x << 8) & 0xc0380700c0380700c0380700c0380700c0380700c0380700c0380700c03807_cppui256;
248 x = (x | x << 4) & 0x843084308430843084308430843084308430843084308430843084308430843_cppui256;
249 x = (x | x << 2) & 0x909090909090909090909090909090909090909090909090909090909090909_cppui256;
250 x = (x | x << 1) & 0x1111111111111111111111111111111111111111111111111111111111111111_cppui256;
251 return x;
252}
253
254template <> inline uint64_t compact<3, uint64_t, uint256_t>(uint256_t x) {
255
256 x &= 0x1111111111111111111111111111111111111111111111111111111111111111_cppui256;
257 x = (x | x >> 1) & 0x909090909090909090909090909090909090909090909090909090909090909_cppui256;
258 x = (x | x >> 2) & 0x843084308430843084308430843084308430843084308430843084308430843_cppui256;
259 x = (x | x >> 4) & 0xc0380700c0380700c0380700c0380700c0380700c0380700c0380700c03807_cppui256;
260 x = (x | x >> 8) & 0xf80007c0003f0000f80007c0003f0000f80007c0003f0000f80007c0003f_cppui256;
261 x = (x | x >> 16) & 0xffc00000003ff800000007ff00000000ffc00000003ff800000007ff_cppui256;
262 x = (x | x >> 32) & 0xfffff80000000000000007ffffc0000000000000003fffff_cppui256;
263 x = (x | x >> 64) & 0xfffff800000000000000000000000000000007ffffffffff_cppui256;
264 x = (x | x >> 128) & 0xffffffffffffffff_cppui256;
265 return (uint64_t)x;
266}
267
277template <size_t ND, typename IntT, typename MortonT> MortonT interleave(const IntArray<ND, IntT> &coord) {
278 MortonT retVal(0);
279 for (size_t i = 0; i < ND; i++) {
280 retVal |= pad<ND - 1, IntT, MortonT>(coord[i]) << static_cast<int>(i);
281 }
282 return retVal;
283}
284
285template <size_t ND, typename IntT> Morton96 interleave(const IntArray<3, uint32_t> &coord) {
286 return Morton96(interleave<ND, IntT, uint128_t>(coord));
287}
288
298template <size_t ND, typename IntT, typename MortonT> IntArray<ND, IntT> deinterleave(const MortonT z) {
299 IntArray<ND, IntT> retVal;
300 for (size_t i = 0; i < ND; i++) {
301 retVal[i] = static_cast<IntT>(compact<ND - 1, IntT, MortonT>(z >> static_cast<int>(i)));
302 }
303 return retVal;
304}
305
306template <size_t ND, typename IntT> IntArray<ND, IntT> deinterleave(const Morton96 &z) {
307 return deinterleave<ND, IntT, uint128_t>(uint128_t(z));
308}
309
310template <size_t ND, typename IntT, typename MortonT> struct Interleaver {
311 static MortonT interleave(const IntArray<ND, IntT> &coord) {
312 return morton_index::interleave<ND, IntT, MortonT>(coord);
313 }
314
315 static IntArray<ND, IntT> deinterleave(const MortonT z) { return morton_index::deinterleave<ND, IntT, MortonT>(z); }
316};
317
318template <size_t ND, typename IntT> struct Interleaver<ND, IntT, Morton96> {
319 static Morton96 interleave(const IntArray<ND, IntT> &coord) { return morton_index::interleave<ND, IntT>(coord); }
320
321 static IntArray<ND, IntT> deinterleave(const Morton96 z) { return morton_index::deinterleave<ND, IntT>(z); }
322};
323
324} // namespace morton_index
uint16_t compact< 1, uint16_t, uint64_t >(uint64_t x)
uint128_t pad< 1, uint32_t, uint128_t >(uint32_t v)
uint64_t pad< 3, uint16_t, uint64_t >(uint16_t v)
uint16_t compact< 3, uint16_t, uint64_t >(uint64_t x)
MortonT pad(IntT)
Pad an integer with a given number of padding bits.
uint256_t pad< 3, uint64_t, uint256_t >(uint64_t v)
uint64_t compact< 3, uint64_t, uint256_t >(uint256_t x)
uint256_t pad< 2, uint64_t, uint256_t >(uint64_t v)
uint96_t Morton96
This class implements the structure of size 96bit, that can be used as Morton index.
Definition: Types.h:43
uint32_t compact< 2, uint32_t, uint128_t >(uint128_t x)
uint8_t compact< 2, uint8_t, uint32_t >(uint32_t x)
uint64_t pad< 2, uint16_t, uint64_t >(uint16_t v)
uint128_t pad< 2, uint32_t, uint128_t >(uint32_t v)
uint128_t pad< 3, uint32_t, uint128_t >(uint32_t v)
uint64_t pad< 1, uint16_t, uint64_t >(uint16_t v)
uint16_t compact< 1, uint16_t, uint32_t >(uint32_t x)
uint16_t compact< 2, uint16_t, uint64_t >(uint64_t x)
uint64_t compact< 2, uint64_t, uint256_t >(uint256_t x)
uint32_t pad< 2, uint8_t, uint32_t >(uint8_t v)
std::uint128_t uint128_t
Definition: Types.h:21
IntT compact(MortonT)
Compacts (removes padding from) an integer with a given number of padding bits.
uint32_t pad< 1, uint16_t, uint32_t >(uint16_t v)
uint32_t compact< 3, uint32_t, uint128_t >(uint128_t x)
Eigen::Array< IntT, static_cast< int >(ND), 1 > IntArray
Definition: Types.h:27
uint32_t compact< 1, uint32_t, uint128_t >(uint128_t x)
MortonT interleave(const IntArray< ND, IntT > &coord)
Interleaves an integer coordinate.
IntArray< ND, IntT > deinterleave(const MortonT z)
Deinterleaves a Morton number into an integer coordinate.
static Morton96 interleave(const IntArray< ND, IntT > &coord)
static IntArray< ND, IntT > deinterleave(const Morton96 z)
static MortonT interleave(const IntArray< ND, IntT > &coord)
static IntArray< ND, IntT > deinterleave(const MortonT z)