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}