1use std::ops::Shl;
4
5use super::onescomplement::unsigned::{Unsigned9Bit, Unsigned18Bit, Unsigned36Bit};
6
7#[must_use]
9pub fn split_halves(w: Unsigned36Bit) -> (Unsigned18Bit, Unsigned18Bit) {
10 (left_half(w), right_half(w))
11}
12
13#[must_use]
15pub fn join_halves(left: Unsigned18Bit, right: Unsigned18Bit) -> Unsigned36Bit {
16 Unsigned36Bit::from(left).shl(18) | Unsigned36Bit::from(right)
17}
18
19#[must_use]
21pub fn join_quarters(left: Unsigned9Bit, right: Unsigned9Bit) -> Unsigned18Bit {
22 Unsigned18Bit::from(left).shl(9) | Unsigned18Bit::from(right)
23}
24
25#[must_use]
27pub fn right_half(word: Unsigned36Bit) -> Unsigned18Bit {
28 let bits: u64 = u64::from(word);
29 Unsigned18Bit::try_from(bits & 0o777_777).unwrap()
30}
31
32#[must_use]
34pub fn left_half(word: Unsigned36Bit) -> Unsigned18Bit {
35 let bits: u64 = u64::from(word) >> 18;
36 Unsigned18Bit::try_from(bits & 0o777_777).unwrap()
37}
38
39#[must_use]
43pub fn split_halfword(halfword: Unsigned18Bit) -> (Unsigned9Bit, Unsigned9Bit) {
44 let bits: u32 = u32::from(halfword);
45 (
46 Unsigned9Bit::try_from((bits >> 9) & 0o777).unwrap(),
47 Unsigned9Bit::try_from((bits) & 0o777).unwrap(),
48 )
49}
50
51#[must_use]
55pub fn quarters(word: Unsigned36Bit) -> [Unsigned9Bit; 4] {
56 let (left, right) = split_halves(word);
57 let (q4, q3) = split_halfword(left);
58 let (q2, q1) = split_halfword(right);
59 [q4, q3, q2, q1]
60}
61
62#[cfg(test)]
63mod tests {
64 use test_strategy::proptest;
65
66 use super::super::onescomplement::unsigned::{Unsigned9Bit, Unsigned18Bit, Unsigned36Bit};
67 use super::*;
68
69 macro_rules! assert_octal_eq {
70 ($left:expr_2021, $right:expr_2021 $(,)?) => {{
71 match (&$left, &$right) {
72 (left_val, right_val) => {
73 if !(*left_val == *right_val) {
74 panic!(
75 "Assertion failed: {:>#012o} != {:>#012o}",
76 left_val, right_val
77 );
78 }
79 }
80 }
81 }};
82 }
83
84 #[test]
85 fn test_join_halves() {
86 assert_octal_eq!(
87 join_halves(
88 Unsigned18Bit::try_from(0o123_456_u32).unwrap(),
89 Unsigned18Bit::try_from(0o525_252_u32).unwrap()
90 ),
91 Unsigned36Bit::try_from(0o123_456_525_252_u64).unwrap()
92 );
93 }
94
95 #[test]
96 fn test_join_quarters() {
97 assert_octal_eq!(
98 join_quarters(
99 Unsigned9Bit::try_from(0o123_u16).unwrap(),
100 Unsigned9Bit::try_from(0o456_u16).unwrap()
101 ),
102 Unsigned18Bit::try_from(0o123_456_u32).unwrap()
103 );
104 }
105
106 #[test]
107 fn test_split_halfword() {
108 let h = Unsigned18Bit::try_from(0o123_456_u32).expect("valid test data");
109 assert_eq!(
110 split_halfword(h),
111 (
112 Unsigned9Bit::try_from(0o123).unwrap(),
113 Unsigned9Bit::try_from(0o456).unwrap()
114 )
115 );
116 }
117
118 #[test]
119 fn test_quarters() {
120 fn q(n: u16) -> Unsigned9Bit {
121 Unsigned9Bit::try_from(n).expect("valid test data")
122 }
123 assert_eq!(
124 quarters(Unsigned36Bit::try_from(0o123_456_525_252_u64).unwrap()),
125 [q(0o123), q(0o456), q(0o525), q(0o252)]
126 );
127 }
128
129 #[proptest]
130 fn test_word_split_and_join_are_inverses(value: Unsigned36Bit) {
131 let left = left_half(value);
132 let right = right_half(value);
133 let joined = join_halves(left, right);
134 assert_eq!(value, joined);
135 }
136
137 #[proptest]
138 fn test_halfword_split_and_join_are_inverses(value: Unsigned18Bit) {
139 let (left, right) = split_halfword(value);
140 let joined = join_quarters(left, right);
141 assert_eq!(joined, value);
142 }
143
144 #[proptest]
145 fn test_word_quartering_and_joining_are_inverses(value: Unsigned36Bit) {
146 let quarters: [Unsigned9Bit; 4] = quarters(value);
147 let left = join_quarters(quarters[0], quarters[1]);
148 let right = join_quarters(quarters[2], quarters[3]);
149 let joined = join_halves(left, right);
150 assert_eq!(joined, value);
151 }
152}