morton_encoding/lib.rs
1//! `morton_encoding` is a crate that helps interleave the bits of numbers,
2//! (called “co-ordinates” in the source code)
3//! thereby creating a so-called “Morton encoding” (also known as a
4//! “Z-order encoding”) in whose final result (“Key”)
5//! all bits of the same significance are together.
6//! This is helpful for linearising the points
7//! of data structures whilst preserving
8//! some measure of locality. Z-order encoding isn't as good at preserving
9//! locality as Hilbert encoding, but it is much easier to compute.
10//! (For Hilbert encoding please refer to the
11//! ([`lindel`](https://crates.io/crates/lindel)
12//! crate instead.)
13//!
14//! # Usage
15//! The user is cordially advised to look for solutions in the following order:
16//! 1. By far the most ergonomic, performant, and panic-free usage
17//! is to use the [`morton_encode`](fn@morton_encode) and
18//! [`morton_decode`](fn@morton_decode) functions with arrays of
19//! primitive unsigned integers, as follows:
20//! ```
21//! # use morton_encoding::*;
22//! let input = [5u8, 4, 12, 129];
23//! let output = morton_encode(input);
24//! assert_eq!(output, 268447241);
25//! let reassembled_input = morton_decode(output);
26//! assert_eq!(input, reassembled_input);
27//! ```
28//!
29//! 2. If 128 bits are not enough, the user should use
30//! [`lindel`](https://crates.io/crates/lindel),
31//! which contains the `create_lineariseable_data_type` macro. This
32//! will unfortunately require manual implementation of any trait that
33//! the macro doesn't implement automatically, such as subtraction.
34//!
35//! 3. If the co-ordinates come at the end of a long iterator chain of length
36//! `<=8`, the user should use the `_generic` functions, taking care to not
37//! compare Keys resulting from unequal-length iterators.
38//!
39//! 4. Finally, if performance is of no concern at all, the user can make use
40//! of the `arbitrary_bit_size` module or of the `_generic` functions for
41//! arbitrary iterator length.
42//!
43//! # Contents
44//!
45//! The functions contained herein are broadly split into four categories:
46//! * “Bloating functions”, that interleave a number's bits with zeroes;
47//! * “Shrinking functions”, that perform the opposite operation;
48//! * “Morton encoding functions”, that interleave some numbers'
49//! bits with each other;
50//! * “Morton decoding functions”, that perform the opposite operation.
51//!
52//! For more detailed information,
53//! please refer to each individual function's documentation.
54//!
55//! # `std` vs `no_std`
56//!
57//! `std` is entirely optional for this crate, and is only useful if
58//! the user needs to use `BigUint`s. Currently, the crate
59//! (or its documentation, in any event) has currently been compiled with `std`
60#![cfg_attr(
61 feature = "std",
62 doc = " **on**, meaning that it can interleave arbitrary amounts of arbitrarily large integers, as long as the user only runs it within an operating system."
63)]
64#![cfg_attr(
65 not(feature = "std"),
66 doc = " **off**, meaning that it can be used even in embedded environments, but will demand home-made `uint` types if 128 bits are not enough for the user."
67)]
68//!
69//!
70//! # Similar crates
71//! A quick sift through crates.rs comes up with the following 3 similar crates:
72//! * [`morton`](https://crates.io/crates/morton): Just as fast as ours, but only works for `[u16; 2] <-> u32`.
73//! * [`bitwise`](https://crates.io/crates/bitwise):
74//! 1. On my machine it doesn't even compile.
75//! 2. It hasn't been implemented for more than 3 dimensions.
76//! 3. Its portable implementation, when copy-pasted, is 3.5x
77//! slower than ours.
78//! 4. Its non-portable implementation uses the
79//! `core::arch::x86_64::_pdep_u64` primitive, so we wrote some extra
80//! implementations that used it and benchmarked them. To our surprise,
81//! it was consistently slightly slower than our own code!
82//! * [`zdex`](https://crates.io/crates/zdex):
83//! Despite not built with performance in mind, its speed
84//! is within a few orders of magnitude from ours, its results are almost
85//! correct, and the API ought to be usable with enough dedication and
86//! experimentation. It does, however, need `std` whereas ours doesn't.
87//!
88//! # Operation
89//! This code works by splitting each coordinate's bits in half, and pushing
90//! them apart; then each half is split into quarters, and pushed apart again;
91//! and so on until each bit is `n-1` bits apart from its neighbours. From
92//! there, the complete key is computed by a mere shift-and-bitwise-or.
93//! A simplified version of this algorithm (and, in fact, the inspiration
94//! for this crate) can be found [here](https://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN).
95//!
96//! # Performance
97//! This crate's performace depends *crucially* on three things:
98//! 1. The CPU's ability to shift numbers by more than one bit at a time
99//! (which some microcontrollers can't do)
100//! 2. The compiler's ability to utilise compile-time information in order to
101//! [fold all the constants](https://en.wikipedia.org/wiki/Constant_folding)
102//! 3. The result of the operations fitting within a single register.
103//!
104//! Assuming, then, that the compiler *can* optimise to the best of its ability,
105//! the code is reasonably fast, at least for an operation whose hardware
106//! implementation only needs wires. For the transformation between
107//! `[u{N}; M] <-> u{N*M}`, the time needed is `O(M*log(N))`.
108//! The program *generally* needs about 20 machine instructions per coordinate,
109//! though this can certainly vary. <details>
110//! <summary>A full list of the machine instructions
111//! needed for each transformation can be found below; each column lists
112//! the operation first, then the total amount of machine instructions,
113//! then the amount of machine instructions per co-ordinate rounded up.</summary>
114//!
115//! ```should_not_compile
116//! u16 -> [u8; 2] : 23 12
117//! [u8; 2] -> u16 : 27 14
118//! u32 -> [u16; 2]: 28 14
119//! u64 -> [u32; 2]: 32 16
120//! [u16; 2] -> u32 : 34 17
121//! [u8; 3] -> u32 : 41 14
122//! u32 -> [u8; 3]: 48 16
123//! [u32; 2] -> u64 : 48 24
124//! [u8; 4] -> u32 : 55 14
125//! u32 -> [u8; 4]: 55 14
126//! [u16; 3] -> u64 : 56 19
127//! u64 -> [u16; 3]: 62 21
128//! [u8; 5] -> u64 : 64 13
129//! u64 -> [u16; 4]: 68 17
130//! [u16; 4] -> u64 : 71 18
131//! u64 -> [u8; 5]: 72 15
132//! [u8; 6] -> u64 : 79 14
133//! u64 -> [u8; 6]: 87 15
134//! [u64; 2] -> u128 : 93 47
135//! [u8; 7] -> u64 : 94 14
136//! u64 -> [u8; 7]: 102 15
137//! [u8; 8] -> u64 : 102 13
138//! u128 -> [u64; 2]: 110 55
139//! u128 -> [u16; 5]: 131 27
140//! u64 -> [u8; 8]: 132 17
141//! [u32; 3] -> u128 : 142 48
142//! u128 -> [u32; 3]: 142 48
143//! [u8; 9] -> u128 : 149 17
144//! [u32; 4] -> u128 : 152 38
145//! u128 -> [u32; 4]: 153 39
146//! [u16; 5] -> u128 : 159 32
147//! u128 -> [u16; 6]: 185 31
148//! [u8; 10] -> u128 : 190 19
149//! u128 -> [u8; 9]: 194 22
150//! [u16; 6] -> u128 : 213 36
151//! u128 -> [u8; 10]: 216 22
152//! u128 -> [u16; 7]: 217 31
153//! [u16; 7] -> u128 : 230 33
154//! [u8; 11] -> u128 : 244 23
155//! u128 -> [u8; 11]: 247 23
156//! [u16; 8] -> u128 : 253 32
157//! u128 -> [u16; 8]: 255 32
158//! u128 -> [u8; 12]: 266 23
159//! [u8; 12] -> u128 : 268 23
160//! [u8; 13] -> u128 : 285 22
161//! u128 -> [u8; 13]: 287 23
162//! u128 -> [u8; 14]: 308 22
163//! [u8; 14] -> u128 : 318 23
164//! u128 -> [u8; 15]: 332 23
165//! [u8; 15] -> u128 : 361 25
166//! u128 -> [u8; 16]: 382 24
167//! [u8; 16] -> u128 : 419 27
168//! ```
169//! As we can see, anything that doesn't involve `u128`s generally takes fewer
170//! than 20 machine code instructions per co-ordinate; the actual spread
171//! ranges between 12 and 24 instructions. For calculations that include
172//! `u128`s and above, the instructions needed increase linearly with the
173//! bit length.
174//! </details>
175
176#![cfg_attr(not(feature = "std"), no_std)]
177
178type SizeRatio = core::num::NonZeroUsize;
179
180use core::convert::From;
181use core::ops::BitAndAssign;
182use core::ops::BitOrAssign;
183use core::ops::ShlAssign;
184use num::traits::int::PrimInt;
185use num_traits::ToPrimitive;
186
187macro_rules! sizeof {
188 ($t: ty) => {
189 core::mem::size_of::<$t>()
190 };
191}
192
193/// A convenience function.
194///
195/// Persuades the compiler that a non-zero value is, in fact, non-zero.
196///
197/// Will (unsurprisingly) panic if called with a zero.
198pub fn nz(x: usize) -> SizeRatio {
199 SizeRatio::new(x).unwrap()
200}
201
202fn fits_n_times<A, B>(n: SizeRatio) -> bool {
203 sizeof!(A) >= n.get() * sizeof!(B)
204}
205
206/// An 8-bit co-ordinate requires 3 steps, regardless of the size ratio.
207/// For every doubling of its bits, another step is required.
208fn ceil_of_log2_of_coor_bits<Coor>() -> u32 {
209 (sizeof!(Coor) * 8).next_power_of_two().trailing_zeros()
210}
211
212/// Let `x = 1<<step_number`, and `y = x * (siz_rat - 1)`.
213/// Essentially, this function outputs a number that has `y` zeroes,
214/// then `x` ones, then `y` zeroes again, then `x` ones again,
215/// repeating that pattern for the whole number.
216/// In case the masking isn't really needed,
217/// all ones are returned instead so the compiler understands to
218/// not actually perform the masking.
219///
220/// The “bit twiddling hacks” web-site calls these “magic numbers”,
221/// but they're essentially just what I mentioned.
222/// https://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
223///
224/// Side-note: You really, really want this function to be
225/// optimised away.
226fn get_mask<Key>(step_number: usize, siz_rat: SizeRatio) -> Key
227where
228 Key: PrimInt + BitOrAssign + ShlAssign<usize>,
229{
230 let siz_rat = siz_rat.get();
231 let tentative_mask = {
232 let key_bits = sizeof!(Key) * 8;
233 let one_1 = Key::one();
234 let amount_of_1s_per_pattern = 1 << step_number;
235 let pattern_length = siz_rat * amount_of_1s_per_pattern;
236 let pattern = (one_1 << amount_of_1s_per_pattern) - one_1;
237 let mut insert_patterns_here: Key = pattern;
238 let amt_of_patterns_that_fit_in_key = key_bits / pattern_length;
239 let amt_of_patterns_we_still_need_to_insert = amt_of_patterns_that_fit_in_key - 1;
240 for _ in 0..amt_of_patterns_we_still_need_to_insert {
241 insert_patterns_here <<= pattern_length;
242 insert_patterns_here |= pattern;
243 }
244 insert_patterns_here
245 };
246
247 let masking_is_necessary = {
248 let usize_bits = 8 * (sizeof!(usize) as u32);
249 let floor_of_log2_of_siz_rat = usize_bits - siz_rat.leading_zeros() - 1;
250 ((step_number as u32) % floor_of_log2_of_siz_rat) == 0
251 };
252 if masking_is_necessary {
253 tentative_mask
254 } else {
255 Key::max_value()
256 }
257}
258
259/// Guarantees that a given data structure is suitable for a Morton Key.
260///
261/// Essentially, it guarantees that a) it behaves as if it's an integer
262/// and b) that it's larger than the relevant coordinate.
263///
264/// Ideally, we would also like a `const N: usize` here that would
265/// assert that a `Key` value is at least `N` times larger than a `Coor`
266/// value, but as of current (1.50) Rust this is not possible.
267pub trait ValidKey<Coor>:
268 PrimInt + From<Coor> + BitOrAssign + BitAndAssign + ShlAssign<usize>
269{
270}
271/// All primitive int types are suitable for Morton Keys.
272impl<Coor, Key: PrimInt + From<Coor> + BitOrAssign + BitAndAssign + ShlAssign<usize>> ValidKey<Coor>
273 for Key
274{
275}
276
277/// Given a data type and a number, it yields the smallest unsigned
278/// integer that's at least `N` times larger.
279///
280/// Implemented by brute force.
281pub trait IdealKey<const N: usize> {
282 type Key;
283}
284
285// UGLY WORK-AROUND, HOOOOOOOO!
286impl IdealKey<1> for u8 {
287 type Key = u8;
288}
289impl IdealKey<2> for u8 {
290 type Key = u16;
291}
292impl IdealKey<3> for u8 {
293 type Key = u32;
294}
295impl IdealKey<4> for u8 {
296 type Key = u32;
297}
298impl IdealKey<5> for u8 {
299 type Key = u64;
300}
301impl IdealKey<6> for u8 {
302 type Key = u64;
303}
304impl IdealKey<7> for u8 {
305 type Key = u64;
306}
307impl IdealKey<8> for u8 {
308 type Key = u64;
309}
310impl IdealKey<9> for u8 {
311 type Key = u128;
312}
313impl IdealKey<10> for u8 {
314 type Key = u128;
315}
316impl IdealKey<11> for u8 {
317 type Key = u128;
318}
319impl IdealKey<12> for u8 {
320 type Key = u128;
321}
322impl IdealKey<13> for u8 {
323 type Key = u128;
324}
325impl IdealKey<14> for u8 {
326 type Key = u128;
327}
328impl IdealKey<15> for u8 {
329 type Key = u128;
330}
331impl IdealKey<16> for u8 {
332 type Key = u128;
333}
334
335impl IdealKey<1> for u16 {
336 type Key = u16;
337}
338impl IdealKey<2> for u16 {
339 type Key = u32;
340}
341impl IdealKey<3> for u16 {
342 type Key = u64;
343}
344impl IdealKey<4> for u16 {
345 type Key = u64;
346}
347impl IdealKey<5> for u16 {
348 type Key = u128;
349}
350impl IdealKey<6> for u16 {
351 type Key = u128;
352}
353impl IdealKey<7> for u16 {
354 type Key = u128;
355}
356impl IdealKey<8> for u16 {
357 type Key = u128;
358}
359
360impl IdealKey<1> for u32 {
361 type Key = u32;
362}
363impl IdealKey<2> for u32 {
364 type Key = u64;
365}
366impl IdealKey<3> for u32 {
367 type Key = u128;
368}
369impl IdealKey<4> for u32 {
370 type Key = u128;
371}
372
373impl IdealKey<1> for u64 {
374 type Key = u64;
375}
376impl IdealKey<2> for u64 {
377 type Key = u128;
378}
379
380impl IdealKey<1> for u128 {
381 type Key = u128;
382}
383
384/// “Bloats” a given number by interleaving its bits with zeroes.
385///
386/// Each input bit is interleaved with `N - 1` zeroes.
387///
388/// # Examples
389/// ```
390/// # use morton_encoding::bloat_custom;
391/// assert_eq!(bloat_custom::<_, u32, 3>(0x55u8), 0x041041);
392/// ```
393/// # Panics
394///
395/// With the advent of `min_const_generics` in this crate, it was
396/// hoped that this function could recognise when a `Key` value
397/// is not large enough for `N` `Coor` values, and fail to compile
398/// in that case. Sadly, the compiler isn't quite clever enough for that yet.
399/// Thus, we have to make do with run-time panics instead, as seen in the
400/// following example:
401/// ```should_panic
402/// # use morton_encoding::bloat_custom;
403/// bloat_custom::<u8, u16, 3>(0x55u8); // Compiles, but panics.
404/// ```
405/// Therefore, the user is solely responsible for maintaining the invariants
406/// needed.
407pub fn bloat_custom<Coor, Key, const N: usize>(x: Coor) -> Key
408where
409 Coor: ToPrimitive,
410 Key: ValidKey<Coor>,
411{
412 //static_assertions::const_assert!(fitsntimes::<Key, Coor, {N}>());
413 assert!(N > 0, "N must not equal zero!");
414 assert!(
415 sizeof!(Key) >= N * sizeof!(Coor),
416 "Key value is not big enough for {} Coordinate values!",
417 N
418 );
419 bloat_custom_checked(x, nz(N)).unwrap()
420}
421
422/// Fallibly “bloats” a given number, interleaving its bits with zeroes.
423///
424/// Returns an `Option`.
425///
426/// Each input bit is interleaved with `siz_rat - 1` zeroes.
427/// Alternatively, if the provided `Key` type is too small to
428/// fit `siz_rat` `Coor` numbers inside it, a `None` is returned.
429///
430/// This function is usable when the size ratio is computed at run-time,
431/// but bear in mind that it might run much more slowly than its
432/// compile-time counterparts.
433///
434/// # Examples
435/// ```
436/// # use morton_encoding::bloat_custom_checked;
437/// # use morton_encoding::nz;
438/// assert_eq!(bloat_custom_checked(0xFFFFu16, nz(2)), Some(0x55555555u32));
439/// assert_eq!(bloat_custom_checked::<u16, u32>(0xFFFF, nz(3)), None);
440/// ```
441pub fn bloat_custom_checked<Coor, Key>(x: Coor, siz_rat: SizeRatio) -> Option<Key>
442where
443 Coor: ToPrimitive,
444 Key: ValidKey<Coor>,
445{
446 if !fits_n_times::<Key, Coor>(siz_rat) {
447 return None;
448 }
449
450 let mut result: Key = From::from(x);
451 if siz_rat.get() == 1 {
452 return Some(result);
453 }
454
455 let shift_bitor_mask = |x: &mut Key, y| {
456 let shift_amt = (siz_rat.get() - 1) << y;
457 *x |= *x << shift_amt;
458 (*x) &= get_mask(y, siz_rat)
459 };
460
461 let step_amount = ceil_of_log2_of_coor_bits::<Coor>();
462
463 (0..step_amount)
464 .rev()
465 .for_each(|q| shift_bitor_mask(&mut result, q as usize));
466
467 Some(result)
468}
469
470/// “Shrinks” a given number, only keeping a user-provided amount of its bits.
471///
472/// The 0th bit is always kept, and so is every `siz_rat`th bit thereafter. All
473/// other bits are lost.
474///
475/// This function sanitises its input, so the bits that are thrown away do not
476/// need to be cleared by the user.
477///
478/// # Examples
479/// ```
480/// # use morton_encoding::shrink_custom;
481/// assert_eq!(shrink_custom::<u8, u32, 3>(0x145145), 0x55);
482/// ```
483///
484/// # Panics
485///
486/// With the advent of min_const_generics in this crate, it was
487/// hoped that this function could recognise when a `Key` value
488/// is not large enough for `N` `Coor` values, and fail to compile
489/// in that case. Sadly, the compiler isn't quite clever enough for that yet.
490/// Thus, we have to make do with run-time panics instead, as seen in the
491/// following example:
492/// ```should_panic
493/// # use morton_encoding::shrink_custom;
494/// shrink_custom::<u8, u16, 3>(0x5555u16); // Compiles, but panics.
495/// ```
496/// Therefore, the user is solely responsible for maintaining the invariants
497/// needed.
498///
499pub fn shrink_custom<Coor, Key, const N: usize>(x: Key) -> Coor
500where
501 Coor: ToPrimitive + PrimInt,
502 Key: ValidKey<Coor>,
503{
504 if N == 0 || sizeof!(Key) < N * sizeof!(Coor) {
505 panic!();
506 }
507 shrink_custom_checked(x, nz(N)).unwrap()
508}
509
510/// Fallibly “shrinks” a given number, only keeping a certain amount of its bits.
511///
512/// The 0th bit is always kept, and so is every `siz_rat`th bit thereafter. All
513/// other bits are lost. Alternatively, if the provided `Key` type is too small
514/// to fit `siz_rat` `Coor` numbers inside it, a `None` is returned .
515///
516/// This function is usable when the size ratio is computed at run-time,
517/// but bear in mind that it might run much more slowly than its
518/// compile-time counterparts.
519///
520/// This function sanitises its input, so the bits that are thrown away do not
521/// need to be cleared by the user.
522///
523/// # Examples
524/// ```
525/// # use morton_encoding::shrink_custom_checked;
526/// # use morton_encoding::nz;
527/// assert_eq!(shrink_custom_checked::<u16, u32>(0xFFFF_FFFF, nz(2)), Some(0xFFFF));
528/// assert_eq!(shrink_custom_checked::<u16, u32>(0x185185, nz(3)), None);
529/// ```
530pub fn shrink_custom_checked<Coor, Key>(x: Key, siz_rat: SizeRatio) -> Option<Coor>
531where
532 Coor: ToPrimitive + PrimInt,
533 Key: ValidKey<Coor>,
534{
535 if !fits_n_times::<Key, Coor>(siz_rat) {
536 return None;
537 }
538
539 let mut result: Key = x;
540 if siz_rat.get() == 1 {
541 return Coor::from(result);
542 }
543
544 let shift_bitor_mask = |x: &mut Key, y| {
545 (*x) &= get_mask(y, siz_rat);
546 let shift_amt = (siz_rat.get() - 1) << y;
547 *x |= *x >> shift_amt;
548 };
549
550 let step_amount = ceil_of_log2_of_coor_bits::<Coor>();
551
552 (0..step_amount).for_each(|q| shift_bitor_mask(&mut result, q as usize));
553
554 Coor::from(result & (From::from(Coor::max_value())))
555}
556
557/// Receives an iterator of `Coor` values and encodes them all in a `Key` value.
558///
559/// Meant to be used with statically-known iterator lengths. If that is not
560/// the case, the checked version of this function (`morton_encode_checked`)
561/// should be used instead.
562///
563/// # Panics
564///
565/// This function will panic if the `Key` value provided does not have enough
566/// length for all the values in the iterator.
567///
568/// In the future, we would like to constrain it for iterators that have exactly
569/// `const N` elements, but that's still quite far away.
570///
571/// # Examples
572/// ```
573/// # use morton_encoding::morton_encode_generic;
574/// let input = vec!(0u8, 255);
575/// let result: u16 = morton_encode_generic(input);
576/// assert_eq!(result, 0x5555);
577/// ```
578/// In the event that one `Key` is strictly larger than all `Coor`s put together, all significant bits are gathered at the end, and extraneous bits at the beginning are cleared. The following example illustrates the difference:
579/// ```
580/// # use morton_encoding::morton_encode_generic;
581/// let input = vec!(255u8; 3);
582/// let result: u32 = morton_encode_generic(input);
583/// assert_eq!(result, 0b_0000_0000_111_111_111_111_111_111_111_111u32);
584/// let input = vec!(0u8, 255, 255, 255);
585/// let result: u32 = morton_encode_generic(input);
586/// assert_eq!(result, 0b_0111_0111_0111_0111_0111_0111_0111_0111u32);
587/// ```
588pub fn morton_encode_generic<Coor, Key, Coors>(coors: Coors) -> Key
589where
590 Coor: ToPrimitive,
591 Key: ValidKey<Coor>,
592 Coors: IntoIterator<Item = Coor>,
593 <Coors as core::iter::IntoIterator>::IntoIter: ExactSizeIterator,
594{
595 morton_encode_generic_checked(coors).unwrap()
596}
597
598/// Receives an iterator of `Coor` values and encodes them all in a `Option<Key>` value.
599///
600/// Returns a `None` if the iterator is empty, or if it is too large for all the `Coor` values contained within to fit inside a `Key` type.
601///
602/// # Examples
603/// ```
604/// # use morton_encoding::morton_encode_generic_checked;
605/// assert_eq!(morton_encode_generic_checked(vec!(1u8, 1)), Some(3u16));
606/// assert_eq!(morton_encode_generic_checked::<u16, u32, Vec<u16>>(vec!()), None);
607/// assert_eq!(morton_encode_generic_checked::<_, u16, _>(vec!(0u8, 255, 200)), None);
608/// ```
609pub fn morton_encode_generic_checked<Coor, Key, Coors>(coors: Coors) -> Option<Key>
610where
611 Coor: ToPrimitive,
612 Key: ValidKey<Coor>,
613 Coors: IntoIterator<Item = Coor>,
614 <Coors as core::iter::IntoIterator>::IntoIter: ExactSizeIterator,
615{
616 let iterator = coors.into_iter();
617 let siz_rat = SizeRatio::new(iterator.len())?;
618 if !fits_n_times::<Key, Coor>(siz_rat) {
619 None
620 } else {
621 Some({
622 let bloat_fn = |x| match siz_rat.get() {
623 1 => bloat_custom::<Coor, Key, 1>(x),
624 2 => bloat_custom::<Coor, Key, 2>(x),
625 3 => bloat_custom::<Coor, Key, 3>(x),
626 4 => bloat_custom::<Coor, Key, 4>(x),
627 5 => bloat_custom::<Coor, Key, 5>(x),
628 6 => bloat_custom::<Coor, Key, 6>(x),
629 7 => bloat_custom::<Coor, Key, 7>(x),
630 8 => bloat_custom::<Coor, Key, 8>(x),
631 _ => bloat_custom_checked::<Coor, Key>(x, siz_rat).unwrap(),
632 };
633 iterator
634 .map(bloat_fn)
635 .fold(Key::zero(), |acc, x| (acc << 1) | x)
636 })
637 }
638}
639
640/// Receives a `Key` value and returns an iterator of `Coor` values that were decoded from it.
641///
642/// Returns an empty iterator if the `Key` value is too small for so many `Coor` values.
643///
644/// # Examples
645/// ```
646/// # use morton_encoding::morton_decode_generic;
647/// # use morton_encoding::morton_encode_generic;
648/// # use morton_encoding::nz;
649/// assert_eq!(morton_decode_generic::<_, _, Vec<u8>>(3u16, nz(2)), vec!(1, 1));
650/// assert_eq!(morton_decode_generic::<u16, u32, Vec<u16>>(0, nz(4)), vec!());
651/// let input = vec!(1u8, 2);
652/// let encoded_input: u16 = morton_encode_generic(input.clone());
653/// let reassembled_input: Vec<u8> = morton_decode_generic(encoded_input, nz(2));
654/// assert_eq!(input, reassembled_input);
655/// ```
656pub fn morton_decode_generic<Coor, Key, Coors>(key: Key, siz_rat: SizeRatio) -> Coors
657where
658 Coor: ToPrimitive + PrimInt,
659 Key: ValidKey<Coor>,
660 Coors: core::iter::FromIterator<Coor>,
661{
662 if !fits_n_times::<Key, Coor>(siz_rat) {
663 core::iter::empty().collect::<Coors>()
664 } else {
665 let shrink_fn = |x| match siz_rat.get() {
666 1 => shrink_custom::<Coor, Key, 1>(x),
667 2 => shrink_custom::<Coor, Key, 2>(x),
668 3 => shrink_custom::<Coor, Key, 3>(x),
669 4 => shrink_custom::<Coor, Key, 4>(x),
670 5 => shrink_custom::<Coor, Key, 5>(x),
671 6 => shrink_custom::<Coor, Key, 6>(x),
672 7 => shrink_custom::<Coor, Key, 7>(x),
673 8 => shrink_custom::<Coor, Key, 8>(x),
674 _ => shrink_custom_checked::<Coor, Key>(x, siz_rat).unwrap(),
675 };
676 let siz_rat = siz_rat.get();
677 (0..siz_rat)
678 .map(|x| key >> (siz_rat - (x + 1)))
679 .map(shrink_fn)
680 .collect::<Coors>()
681 }
682}
683
684/// Encodes an array of `N` `Coordinates` into a `Key`.
685///
686/// Receives an array of `N` values of `Coordinate` type (`[Coordinate; N]`),
687/// and encodes them all in a `Key` value. In the event that one `Key` is
688/// strictly larger than `N` `Coordinate`s, all significant bits are gathered
689/// at the end, and extraneous bits at the beginning are cleared.
690///
691/// # Panics
692///
693/// This function will panic if the `Key` value provided does not have enough
694/// length for all the values in the iterator.
695///
696/// In the future, we would like for it to fail to compile for invalid
697/// parametres, but that's still quite far away.
698/// ```should_panic
699/// # use morton_encoding::morton_encode_array;
700/// let _: u32 = morton_encode_array([15u16, 256, 10000]); // Compiles, but panics.
701/// ```
702/// # Examples
703/// ```
704/// # use morton_encoding::morton_encode_array;
705/// let input = [255u8, 0];
706/// let result: u16 = morton_encode_array(input);
707/// assert_eq!(result, 0xAAAA);
708/// ```
709/// In the event that one `Key` is strictly larger than all `Coor`s put
710/// together, all significant bits are gathered at the end, and extraneous
711/// bits at the beginning are cleared. The following example illustrates
712/// the difference:
713/// ```
714/// # use morton_encoding::morton_encode_array;
715/// let input = [255u8; 3];
716/// let result: u32 = morton_encode_array(input);
717/// assert_eq!(result, 0b_0000_0000_111_111_111_111_111_111_111_111u32);
718/// let input = [0u8, 255, 255, 255];
719/// let result: u32 = morton_encode_array(input);
720/// assert_eq!(result, 0b_0111_0111_0111_0111_0111_0111_0111_0111u32);
721/// ```
722pub fn morton_encode_array<Coordinate, Key, const N: usize>(input: [Coordinate; N]) -> Key
723where
724 Coordinate: ToPrimitive + PrimInt,
725 Key: ValidKey<Coordinate>,
726{
727 input
728 .iter()
729 .map(|&m| bloat_custom::<Coordinate, Key, N>(m))
730 .fold(Key::zero(), |acc, x| (acc << 1) | x)
731}
732
733/// The most ergonomic way to perform the Morton encoding operation.
734///
735/// Works for all primitive unsigned integers, and never panics for them.
736/// Will work for others if the user implements the `IdealKey`
737/// trait for them, but will panic if the trait is misimplemented.
738///
739/// # Examples
740/// ```
741/// # use morton_encoding::morton_encode;
742/// # use morton_encoding::nz;
743/// assert_eq!(morton_encode([0u8; 2]), 0u16);
744/// assert_eq!(morton_encode([0u8; 3]), 0u32);
745/// assert_eq!(morton_encode([0u32; 3]), 0u128);
746/// ```
747pub fn morton_encode<Coordinate, const N: usize>(
748 input: [Coordinate; N],
749) -> <Coordinate as IdealKey<N>>::Key
750where
751 Coordinate: IdealKey<N> + ToPrimitive + PrimInt,
752 <Coordinate as IdealKey<N>>::Key: ValidKey<Coordinate>,
753{
754 morton_encode_array(input)
755}
756
757/// Receives a `Key` value and unscrambles it into an array.
758///
759/// Returns an array of `Coor` values that were decoded from the input.
760///
761/// Panics if the `Key` value is too small for so many `Coor` values.
762/// ```should_panic
763/// # use morton_encoding::morton_decode_array;
764/// let _: [u16; 5] = morton_decode_array(6000000u64);
765/// ```
766///
767/// # Examples
768/// ```
769/// # use morton_encoding::morton_decode_array;
770/// # use morton_encoding::morton_encode_array;
771/// # use morton_encoding::nz;
772/// assert_eq!(morton_decode_array::<u8, u16, 2>(3u16), [1u8, 1]);
773/// let input = [1u32, 2];
774/// let encoded_input: u64 = morton_encode_array(input);
775/// let reassembled_input: [u32; 2] = morton_decode_array(encoded_input);
776/// assert_eq!(input, reassembled_input);
777/// ```
778pub fn morton_decode_array<Coordinate, Key, const N: usize>(input: Key) -> [Coordinate; N]
779where
780 Coordinate: ToPrimitive + PrimInt,
781 Key: ValidKey<Coordinate>,
782{
783 let mut result = [Coordinate::zero(); N];
784 for (i, n) in result.iter_mut().rev().enumerate() {
785 *n = shrink_custom::<Coordinate, Key, N>(input >> i);
786 }
787 result
788}
789
790/// The most ergonomic way to perform the Morton decoding operation.
791///
792/// Works for all primitive unsigned integers, and never panics for them.
793/// Will work for others if the user implements the `IdealKey`
794/// trait for them, but will panic if the trait is misimplemented.
795///
796/// # Examples
797/// ```
798/// # use morton_encoding::morton_encode;
799/// # use morton_encoding::morton_decode;
800/// let input = 992;
801/// let output: [u8; 5] = morton_decode(input);
802/// assert_eq!(output, [2u8; 5]);
803/// let input = [543u32, 23765];
804/// let encoded_input: u64 = morton_encode(input);
805/// let reassembled_input: [u32; 2] = morton_decode(encoded_input);
806/// assert_eq!(input, reassembled_input);
807/// ```
808pub fn morton_decode<Coordinate, const N: usize>(
809 input: <Coordinate as IdealKey<N>>::Key,
810) -> [Coordinate; N]
811where
812 Coordinate: IdealKey<N> + ToPrimitive + PrimInt,
813 <Coordinate as IdealKey<N>>::Key: ValidKey<Coordinate>,
814{
815 morton_decode_array(input)
816}
817
818#[cfg(feature = "std")]
819#[cfg(test)]
820mod tests {
821 use super::*;
822
823 fn fmt_bin<T>(x: T) -> std::string::String
824 where
825 T: std::fmt::Binary,
826 {
827 let size = sizeof!(T);
828 if size == 16 {
829 format!("{:#0130b}", x)
830 } else if size == 8 {
831 format!("{:#066b}", x)
832 } else if size == 4 {
833 format!("{:#034b}", x)
834 } else if size == 2 {
835 format!("{:#018b}", x)
836 } else if size == 1 {
837 format!("{:#010b}", x)
838 } else {
839 format!("{:#b}", x)
840 }
841 }
842
843 fn bloat_slow_custom<Coor, Key>(x: Coor, siz_rat: SizeRatio) -> Key
844 where
845 Coor: ToPrimitive + PrimInt + std::fmt::Binary + core::ops::BitAnd,
846 Key: ValidKey<Coor>,
847 <Key as num_traits::Num>::FromStrRadixErr: std::fmt::Debug,
848 {
849 let coor_siz = sizeof!(Coor);
850 let coor_bits = coor_siz * 8;
851 let key_siz = sizeof!(Key);
852 let siz_rat = siz_rat.get();
853 if siz_rat == 1 {
854 return core::convert::From::from(x);
855 }
856 assert!(siz_rat >= 1 && coor_siz * siz_rat <= key_siz);
857 let key_zero = Key::zero();
858 let coor_zero = Coor::zero();
859 let mut result = key_zero;
860 let get_mask_key = |b| (Key::one()) << (b * siz_rat);
861 let get_mask_coor = |b| (Coor::one()) << b;
862 let tst_bit = |a: Coor, b| (a & get_mask_coor(b)) != coor_zero;
863 let set_bit = |a: &mut Key, b| (*a) |= get_mask_key(b);
864 for bit_examined in 0..coor_bits {
865 if tst_bit(x, bit_examined) {
866 set_bit(&mut result, bit_examined)
867 }
868 }
869 result
870 }
871
872 const MAX_BITS: u8 = 20;
873
874 fn size_ratio<A, B>() -> SizeRatio
875 where
876 A: From<B>,
877 {
878 nz(sizeof!(A) / sizeof!(B))
879 // The "From" trait ensures that the result is never zero; consequently, this function can never panic.
880 }
881
882 fn test_all_possible_values<Coor, Key>(siz_rat: Option<usize>)
883 where
884 Coor: num_traits::ToPrimitive
885 + std::fmt::Binary
886 + core::ops::BitAnd
887 + num::traits::PrimInt
888 + std::fmt::Display
889 + std::fmt::Debug,
890 rand::distributions::Standard: rand::distributions::Distribution<Coor>,
891 Key: num::traits::int::PrimInt
892 + core::convert::From<Coor>
893 + core::ops::BitOrAssign
894 + core::ops::BitAndAssign
895 + std::fmt::Binary
896 + core::ops::ShlAssign<usize>,
897 <Key as num_traits::Num>::FromStrRadixErr: std::fmt::Debug,
898 u128: core::convert::From<Coor>,
899 {
900 let siz_rat = siz_rat
901 .and_then(|x| SizeRatio::new(x))
902 .unwrap_or(size_ratio::<Key, Coor>());
903 let testing_function = |x| bloat_slow_custom::<Coor, Key>(x, siz_rat);
904 let function_under_test = |x| bloat_custom_checked::<Coor, Key>(x, siz_rat).unwrap();
905 let limit = core::cmp::min(u128::from(Coor::max_value()), 1u128 << MAX_BITS);
906 let limit = limit as usize;
907 for x in 0..=limit {
908 let x_ = Coor::from(x).expect("Coor and usize incompatible.");
909 if x % (1 << 26) == 0 && x != 0 {
910 dbg!(x >> 26);
911 }
912 let fn2 = function_under_test(x_);
913 let fn1 = testing_function(x_);
914 if fn1 != fn2 {
915 panic!(
916 "x = {} \ntesting_function = {}, \nfunction_under_test = {}",
917 x,
918 fmt_bin(fn1),
919 fmt_bin(fn2)
920 )
921 }
922 if x_ != shrink_custom_checked(fn2, siz_rat).unwrap() {
923 panic!(
924 "x = {} \nBloated = {}, \nShrunk = {}",
925 x,
926 fmt_bin(fn2),
927 shrink_custom_checked(fn2, siz_rat).unwrap()
928 )
929 }
930 if x % 16 == 0 {
931 let input = (0..siz_rat.get())
932 .map(|_| rand::random::<Coor>())
933 .collect::<Vec<Coor>>();
934 let encoded_input: Key = morton_encode_generic(input.clone());
935 let reinstated_input: Vec<Coor> = morton_decode_generic(encoded_input, siz_rat);
936 assert_eq!(input, reinstated_input);
937 }
938 }
939 }
940
941 #[test]
942 fn test_u8_u16() {
943 test_all_possible_values::<u8, u16>(None);
944 }
945 #[test]
946 fn test_u8_u24() {
947 test_all_possible_values::<u8, u32>(Some(3));
948 }
949 #[test]
950 fn test_u8_u32() {
951 test_all_possible_values::<u8, u32>(None);
952 }
953 #[test]
954 fn test_u8_u40() {
955 test_all_possible_values::<u8, u64>(Some(5));
956 }
957 #[test]
958 fn test_u8_u48() {
959 test_all_possible_values::<u8, u64>(Some(6));
960 }
961 #[test]
962 fn test_u8_u56() {
963 test_all_possible_values::<u8, u64>(Some(7));
964 }
965 #[test]
966 fn test_u8_u64() {
967 test_all_possible_values::<u8, u64>(None);
968 }
969 #[test]
970 fn test_u8_u72() {
971 test_all_possible_values::<u8, u128>(Some(9));
972 }
973 #[test]
974 fn test_u8_u80() {
975 test_all_possible_values::<u8, u128>(Some(10));
976 }
977 #[test]
978 fn test_u8_u88() {
979 test_all_possible_values::<u8, u128>(Some(11));
980 }
981 #[test]
982 fn test_u8_u96() {
983 test_all_possible_values::<u8, u128>(Some(12));
984 }
985 #[test]
986 fn test_u8_u104() {
987 test_all_possible_values::<u8, u128>(Some(13));
988 }
989 #[test]
990 fn test_u8_u112() {
991 test_all_possible_values::<u8, u128>(Some(14));
992 }
993 #[test]
994 fn test_u8_u120() {
995 test_all_possible_values::<u8, u128>(Some(15));
996 }
997 #[test]
998 fn test_u8_u128() {
999 test_all_possible_values::<u8, u128>(None);
1000 }
1001 #[test]
1002 fn test_u16_u32() {
1003 test_all_possible_values::<u16, u32>(None);
1004 }
1005 #[test]
1006 fn test_u16_u48() {
1007 test_all_possible_values::<u16, u64>(Some(3));
1008 }
1009 #[test]
1010 fn test_u16_u64() {
1011 test_all_possible_values::<u16, u64>(None);
1012 }
1013 #[test]
1014 fn test_u16_u80() {
1015 test_all_possible_values::<u16, u128>(Some(5));
1016 }
1017 #[test]
1018 fn test_u16_u96() {
1019 test_all_possible_values::<u16, u128>(Some(6));
1020 }
1021 #[test]
1022 fn test_u16_u112() {
1023 test_all_possible_values::<u16, u128>(Some(7));
1024 }
1025 #[test]
1026 fn test_u16_u128() {
1027 test_all_possible_values::<u16, u128>(None);
1028 }
1029 #[test]
1030 fn test_u32_u64() {
1031 test_all_possible_values::<u32, u64>(None);
1032 }
1033 #[test]
1034 fn test_u32_u96() {
1035 test_all_possible_values::<u32, u128>(Some(3));
1036 }
1037 #[test]
1038 fn test_u32_u128() {
1039 test_all_possible_values::<u32, u128>(None);
1040 }
1041 #[test]
1042 fn test_u64_u128() {
1043 test_all_possible_values::<u64, u128>(None);
1044 }
1045
1046 macro_rules! test_functions {
1047 ($encod: ident, $decod: ident, $t1: ty, $t2: ty, $siz_rat: expr) => {
1048 let max_bits_for_this = (MAX_BITS - 3) as usize;
1049 let tmp_bit_limit = $siz_rat * sizeof!($t1) * 8;
1050 if tmp_bit_limit > max_bits_for_this {
1051 for _ in 0..(1 << max_bits_for_this) {
1052 let mut input: [$t1; $siz_rat] = [0; $siz_rat];
1053 for m in 0..$siz_rat {
1054 input[m] = rand::random::<$t1>();
1055 }
1056 let tmp = morton_encode(input);
1057 assert_eq!(input, morton_decode(tmp));
1058 }
1059 } else {
1060 let limit = ((1 as u128) << tmp_bit_limit).wrapping_sub(1);
1061 let limit = limit as $t2;
1062 for input in 0..=limit {
1063 let tmp: [$t1; $siz_rat] = morton_decode(input);
1064 assert_eq!(input, morton_encode(tmp));
1065 }
1066 }
1067 };
1068 }
1069 #[test]
1070 fn test_all_spec_funcs() {
1071 test_functions!(morton_encode_u8_2d, morton_decode_u8_2d, u8, u16, 2);
1072 test_functions!(morton_encode_u8_3d, morton_decode_u8_3d, u8, u32, 3);
1073 test_functions!(morton_encode_u8_4d, morton_decode_u8_4d, u8, u32, 4);
1074 test_functions!(morton_encode_u8_5d, morton_decode_u8_5d, u8, u64, 5);
1075 test_functions!(morton_encode_u8_6d, morton_decode_u8_6d, u8, u64, 6);
1076 test_functions!(morton_encode_u8_7d, morton_decode_u8_7d, u8, u64, 7);
1077 test_functions!(morton_encode_u8_8d, morton_decode_u8_8d, u8, u64, 8);
1078 test_functions!(morton_encode_u8_9d, morton_decode_u8_9d, u8, u128, 9);
1079 test_functions!(morton_encode_u8_10d, morton_decode_u8_10d, u8, u128, 10);
1080 test_functions!(morton_encode_u8_11d, morton_decode_u8_11d, u8, u128, 11);
1081 test_functions!(morton_encode_u8_12d, morton_decode_u8_12d, u8, u128, 12);
1082 test_functions!(morton_encode_u8_13d, morton_decode_u8_13d, u8, u128, 13);
1083 test_functions!(morton_encode_u8_14d, morton_decode_u8_14d, u8, u128, 14);
1084 test_functions!(morton_encode_u8_15d, morton_decode_u8_15d, u8, u128, 15);
1085 test_functions!(morton_encode_u8_16d, morton_decode_u8_16d, u8, u128, 16);
1086 test_functions!(morton_encode_u16_2d, morton_decode_u16_2d, u16, u32, 2);
1087 test_functions!(morton_encode_u16_3d, morton_decode_u16_3d, u16, u64, 3);
1088 test_functions!(morton_encode_u16_4d, morton_decode_u16_4d, u16, u64, 4);
1089 test_functions!(morton_encode_u16_5d, morton_decode_u16_5d, u16, u128, 5);
1090 test_functions!(morton_encode_u16_6d, morton_decode_u16_6d, u16, u128, 6);
1091 test_functions!(morton_encode_u16_7d, morton_decode_u16_7d, u16, u128, 7);
1092 test_functions!(morton_encode_u16_8d, morton_decode_u16_8d, u16, u128, 8);
1093 test_functions!(morton_encode_u32_2d, morton_decode_u32_2d, u32, u64, 2);
1094 test_functions!(morton_encode_u32_3d, morton_decode_u32_3d, u32, u128, 3);
1095 test_functions!(morton_encode_u32_4d, morton_decode_u32_4d, u32, u128, 4);
1096 test_functions!(morton_encode_u64_2d, morton_decode_u64_2d, u64, u128, 2);
1097 }
1098}
1099
1100#[cfg(feature = "std")]
1101/// The most general, but least performant, ways to perform
1102/// Morton encoding and decoding. The functions contained herein work
1103/// correctly, but the author makes absolutely no guarantees about
1104/// how performant they are.
1105pub mod arbitrary_bit_size {
1106 use super::*;
1107 use num::BigUint;
1108 /// A convenience function for converting primitive values to BigUints.
1109 /// Will fail to compile if called with a literal that's not explicitly
1110 /// declared as unsigned.
1111 ///
1112 /// Unavailable if compiled with `no_std`.
1113 pub fn tobuint<Coor>(x: Coor) -> BigUint
1114 where
1115 Coor: num::Unsigned,
1116 num::BigUint: core::convert::From<Coor>,
1117 {
1118 BigUint::from(x)
1119 }
1120
1121 fn get_mask_biguint(
1122 step_number: usize,
1123 siz_rat: SizeRatio,
1124 key_bits: usize,
1125 ) -> Option<num::BigUint> {
1126 use num_traits::identities::One;
1127
1128 let siz_rat = siz_rat.get();
1129 let tentative_mask = {
1130 let one_1 = BigUint::one();
1131 let amount_of_1s_per_pattern = 1 << step_number;
1132 let pattern = (one_1 << amount_of_1s_per_pattern) - BigUint::one();
1133 let mut insert_patterns_here = pattern.clone();
1134 let pattern_length = siz_rat * amount_of_1s_per_pattern;
1135 let amt_of_patterns_that_fit_in_key = key_bits / pattern_length;
1136 let amt_of_patterns_we_still_need_to_insert = amt_of_patterns_that_fit_in_key - 1;
1137 for _ in 0..amt_of_patterns_we_still_need_to_insert {
1138 insert_patterns_here <<= pattern_length;
1139 insert_patterns_here |= pattern.clone();
1140 }
1141 insert_patterns_here
1142 };
1143
1144 let masking_is_necessary = {
1145 let floor_of_log2_of_siz_rat =
1146 8 * (sizeof!(usize) as u32) - siz_rat.leading_zeros() - 1;
1147 (step_number as u32) % floor_of_log2_of_siz_rat == 0
1148 };
1149 if masking_is_necessary {
1150 Some(tentative_mask)
1151 } else {
1152 None
1153 }
1154 }
1155
1156 /// “Bloats” a given number to an arbitrarily large BigUint.
1157 ///
1158 /// Each bit of the input is interleaved with `siz_rat - 1` zeroes.
1159 ///
1160 /// This function assumes that the user will not need to use numbers larger than
1161 ///`usize::max_value()` bytes in size.
1162 ///
1163 /// Unavailable if compiled with `no_std`.
1164 ///
1165 /// # Examples
1166 /// ```
1167 /// # use morton_encoding::arbitrary_bit_size::bloat_custom_biguint;
1168 /// # use morton_encoding::nz;
1169 /// # use morton_encoding::arbitrary_bit_size::tobuint;
1170 /// # use num::BigUint;
1171 /// assert_eq!(bloat_custom_biguint(1u32, nz(2)), tobuint(1u8));
1172 /// assert_eq!(bloat_custom_biguint(u128::max_value(), nz(32)), BigUint::new(vec!(1u32; 128)));
1173 /// ```
1174 pub fn bloat_custom_biguint<Coor>(x: Coor, siz_rat: SizeRatio) -> num::BigUint
1175 where
1176 Coor: num_traits::ToPrimitive,
1177 num::BigUint: core::convert::From<Coor>,
1178 {
1179 let coor_siz = sizeof!(Coor);
1180 let key_siz = coor_siz * siz_rat.get();
1181
1182 let mut result = num::BigUint::from(x);
1183 if siz_rat.get() == 1 {
1184 return result;
1185 }
1186
1187 let shift_bitor_mask = |x: &mut num::BigUint, y| {
1188 let shift_amt = (siz_rat.get() - 1) << y;
1189 *x |= ((*x).clone()) << shift_amt;
1190 if let Some(mask) = get_mask_biguint(y, siz_rat, key_siz * 8) {
1191 (*x) &= mask;
1192 }
1193 };
1194
1195 let op_amt = coor_siz.next_power_of_two().trailing_zeros() + 3;
1196 (0..op_amt)
1197 .rev()
1198 .for_each(|q| shift_bitor_mask(&mut result, q as usize));
1199 result
1200 }
1201
1202 /// “Shrinks” a given number from an arbitrarily large BigUint.
1203 ///
1204 /// The 0th bit is always kept, as is every `siz_rat`th bit thereafter.
1205 ///
1206 /// This function sanitises its input, such that the bits that are thrown away do not need to be cleared by the user. It is also assumed that the user will not need to use numbers larger than `usize::max_value()` bytes in size.
1207 ///
1208 /// Unavailable if compiled with `no_std`.
1209 ///
1210 /// # Examples
1211 /// ```
1212 /// # use morton_encoding::arbitrary_bit_size::shrink_custom_biguint;
1213 /// # use morton_encoding::nz;
1214 /// # use morton_encoding::arbitrary_bit_size::tobuint;
1215 /// assert_eq!(shrink_custom_biguint(tobuint(1u8), nz(2)), tobuint(1u8));
1216 /// assert_eq!(shrink_custom_biguint(num::BigUint::new(vec!(3u32; 128)), nz(32)), num::BigUint::new(vec!(u32::max_value(); 4)));
1217 /// ```
1218 pub fn shrink_custom_biguint(x: BigUint, siz_rat: SizeRatio) -> num::BigUint {
1219 use num_traits::identities::One;
1220
1221 let key_bits = x.bits() + siz_rat.get() - 1;
1222 let coor_bits = key_bits / siz_rat.get();
1223 let key_bits = coor_bits * siz_rat.get();
1224
1225 let mut result = x;
1226 if siz_rat.get() == 1 {
1227 return result;
1228 }
1229
1230 let shift_bitor_mask = |x: &mut BigUint, y| {
1231 if let Some(mask) = get_mask_biguint(y, siz_rat, key_bits) {
1232 (*x) &= mask;
1233 }
1234 //dbg!(x);
1235 let shift_amt = (siz_rat.get() - 1) << y;
1236 *x |= ((*x).clone()) >> shift_amt;
1237 };
1238
1239 let step_amount = coor_bits.next_power_of_two().trailing_zeros();
1240 (0..step_amount).for_each(|q| shift_bitor_mask(&mut result, q as usize));
1241
1242 let final_mask = {
1243 let mut tmpmask = BigUint::one();
1244 tmpmask <<= coor_bits;
1245 tmpmask - BigUint::one()
1246 };
1247
1248 result & final_mask
1249 }
1250
1251 /// Receives an iterator of `Coor` values and encodes them all in a `BigUint`.
1252 ///
1253 /// Unavailable if compiled with `no_std`.
1254 ///
1255 /// # Examples
1256 /// ```
1257 /// # use morton_encoding::arbitrary_bit_size::morton_encode_biguint;
1258 /// # use morton_encoding::nz;
1259 /// # use morton_encoding::arbitrary_bit_size::tobuint;
1260 /// let input = vec!(0u8, 255u8);
1261 /// let result = morton_encode_biguint(input);
1262 /// assert_eq!(result, tobuint(0x5555u16));
1263 /// ```
1264 pub fn morton_encode_biguint<Coor, Coors>(coors: Coors) -> BigUint
1265 where
1266 Coor: ToPrimitive,
1267 num::BigUint: core::convert::From<Coor>,
1268 Coors: IntoIterator<Item = Coor>,
1269 <Coors as core::iter::IntoIterator>::IntoIter: ExactSizeIterator,
1270 {
1271 let zero = BigUint::new(vec![0u32]);
1272 let iterator = coors.into_iter();
1273 if let Some(siz_rat) = SizeRatio::new(iterator.len()) {
1274 let bloat_fn = |x: Coor| bloat_custom_biguint::<Coor>(x, siz_rat);
1275 iterator.map(bloat_fn).fold(zero, |acc, x| (acc << 1) | x)
1276 } else {
1277 zero
1278 }
1279 }
1280
1281 /// Receives a `BigUint` value and returns an iterator of `BigUint` values that were decoded from it.
1282 ///
1283 /// Unavailable if compiled with `no_std`.
1284 ///
1285 /// # Examples
1286 /// ```
1287 /// # use morton_encoding::arbitrary_bit_size::morton_decode_biguint;
1288 /// # use morton_encoding::arbitrary_bit_size::morton_encode_biguint;
1289 /// # use morton_encoding::nz;
1290 /// # use morton_encoding::arbitrary_bit_size::tobuint;
1291 /// assert_eq!(morton_decode_biguint::<Vec<_>>(tobuint(3u8), nz(2)), vec!(tobuint(1u8); 2));
1292 /// let input = vec!(tobuint(1u8), tobuint(2u8));
1293 /// let encoded_input = morton_encode_biguint(input.clone());
1294 /// let reassembled_input: Vec<_> = morton_decode_biguint(encoded_input, nz(2));
1295 /// assert_eq!(input, reassembled_input);
1296 /// ```
1297 pub fn morton_decode_biguint<Coors>(key: BigUint, siz_rat: SizeRatio) -> Coors
1298 where
1299 Coors: core::iter::FromIterator<BigUint> + IntoIterator<Item = BigUint>,
1300 <Coors as core::iter::IntoIterator>::IntoIter: ExactSizeIterator,
1301 {
1302 let shrink_fn = |x: BigUint| shrink_custom_biguint(x, siz_rat);
1303 let siz_rat = siz_rat.get();
1304 (0..siz_rat)
1305 .map(|x| key.clone() >> (siz_rat - (x + 1)))
1306 .map(shrink_fn)
1307 .collect::<Coors>()
1308 }
1309}