1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Morton/Z-order deinterleaving of a [`U512`] into two [`U256`] coordinates.
use super::U512;
use crate::u256::U256;
impl U512 {
/// Deinterleaves a [`U512`] Morton code into two [`U256`] coordinates.
///
/// Returns `(x, y)` where `x` contains the bits from even positions
/// (0, 2, 4, ..., 510) and `y` contains the bits from odd positions
/// (1, 3, 5, ..., 511). This is the inverse of
/// [`interleave`](U512::interleave):
/// `U512::interleave(&x, &y).deinterleave() == (x, y)`.
///
/// # Examples
///
/// ```
/// use cnfy_uint::u256::U256;
/// use cnfy_uint::u512::U512;
///
/// let x = U256::from_be_limbs([0, 0, 0, 42]);
/// let y = U256::from_be_limbs([0, 0, 0, 99]);
/// let (rx, ry) = U512::interleave(&x, &y).deinterleave();
/// assert_eq!(rx, x);
/// assert_eq!(ry, y);
/// ```
#[inline]
pub const fn deinterleave(&self) -> (U256, U256) {
(self.undilate_even(), self.undilate_odd())
}
}
#[cfg(test)]
mod ai_tests {
use super::*;
/// Deinterleaving zero produces (ZERO, ZERO).
#[test]
fn zero() {
assert_eq!(U512::ZERO.deinterleave(), (U256::ZERO, U256::ZERO));
}
/// Round-trip: interleave then deinterleave recovers both coordinates.
#[test]
fn round_trip() {
let x = U256::from_be_limbs([
0xDEAD_BEEF_CAFE_BABE,
0x1234_5678_9ABC_DEF0,
0x0123_4567_89AB_CDEF,
0xFEDC_BA98_7654_3210,
]);
let y = U256::from_be_limbs([
0x0011_2233_4455_6677,
0x8899_AABB_CCDD_EEFF,
0xFFEE_DDCC_BBAA_9988,
0x7766_5544_3322_1100,
]);
let (rx, ry) = U512::interleave(&x, &y).deinterleave();
assert_eq!(rx, x);
assert_eq!(ry, y);
}
/// Deinterleaving an even-only value returns (x, ZERO).
#[test]
fn even_only() {
let x = U256::from_be_limbs([0, 0, 0, 0xCAFE_BABE]);
let v = x.dilate_even();
assert_eq!(v.deinterleave(), (x, U256::ZERO));
}
/// Deinterleaving an odd-only value returns (ZERO, y).
#[test]
fn odd_only() {
let y = U256::from_be_limbs([0, 0, 0, 0xDEAD_BEEF]);
let v = y.dilate_odd();
assert_eq!(v.deinterleave(), (U256::ZERO, y));
}
/// Deinterleaving MAX gives (MAX, MAX).
#[test]
fn max() {
assert_eq!(U512::MAX.deinterleave(), (U256::MAX, U256::MAX));
}
/// Round-trip with both coordinates at maximum.
#[test]
fn round_trip_max() {
let (rx, ry) = U512::interleave(&U256::MAX, &U256::MAX).deinterleave();
assert_eq!(rx, U256::MAX);
assert_eq!(ry, U256::MAX);
}
}