fixed_bigint/heapless/
bit_deposit.rs1use super::HeaplessBigInt;
12use crate::MachineWord;
13use const_num_traits::{
14 DepositBits, ExtractBits, IsolateLowestOne, Nct, One, WrappingShl, WrappingSub, Zero,
15};
16
17impl<T, const CAP: usize> DepositBits for HeaplessBigInt<T, CAP, Nct>
18where
19 T: MachineWord,
20{
21 type Output = Self;
22 fn deposit_bits(self, mask: Self) -> Self {
23 let width = core::cmp::max(self.len(), mask.len());
26 let mut result = Self::new_zero_with_len(width);
27 if <Self as Zero>::is_zero(&mask) {
31 return result;
32 }
33 let one = <Self as One>::one();
34 let mut remaining = mask;
35 let mut bb = one.widened(width);
36 while !<Self as Zero>::is_zero(&remaining) {
37 let lowest = IsolateLowestOne::isolate_lowest_one(remaining);
38 if !<Self as Zero>::is_zero(&(self & bb)) {
39 result |= lowest;
40 }
41 remaining &= WrappingSub::wrapping_sub(remaining, one);
43 bb = WrappingShl::wrapping_shl(bb, 1);
44 }
45 result
46 }
47}
48
49impl<T, const CAP: usize> ExtractBits for HeaplessBigInt<T, CAP, Nct>
50where
51 T: MachineWord,
52{
53 type Output = Self;
54 fn extract_bits(self, mask: Self) -> Self {
55 let width = core::cmp::max(self.len(), mask.len());
58 let mut result = Self::new_zero_with_len(width);
59 if <Self as Zero>::is_zero(&mask) {
62 return result;
63 }
64 let one = <Self as One>::one();
65 let mut remaining = mask;
66 let mut bb = one.widened(width);
67 while !<Self as Zero>::is_zero(&remaining) {
68 let lowest = IsolateLowestOne::isolate_lowest_one(remaining);
69 if !<Self as Zero>::is_zero(&(self & lowest)) {
70 result |= bb;
71 }
72 remaining &= WrappingSub::wrapping_sub(remaining, one);
73 bb = WrappingShl::wrapping_shl(bb, 1);
74 }
75 result
76 }
77}
78
79impl<T, const CAP: usize> DepositBits for &HeaplessBigInt<T, CAP, Nct>
84where
85 T: MachineWord,
86{
87 type Output = HeaplessBigInt<T, CAP, Nct>;
88 fn deposit_bits(self, mask: Self) -> HeaplessBigInt<T, CAP, Nct> {
89 <HeaplessBigInt<T, CAP, Nct> as DepositBits>::deposit_bits(*self, *mask)
90 }
91}
92
93impl<T, const CAP: usize> ExtractBits for &HeaplessBigInt<T, CAP, Nct>
94where
95 T: MachineWord,
96{
97 type Output = HeaplessBigInt<T, CAP, Nct>;
98 fn extract_bits(self, mask: Self) -> HeaplessBigInt<T, CAP, Nct> {
99 <HeaplessBigInt<T, CAP, Nct> as ExtractBits>::extract_bits(*self, *mask)
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::HeaplessBigInt;
106 use const_num_traits::{DepositBits, ExtractBits};
107
108 type H = HeaplessBigInt<u8, 4>;
109
110 #[test]
111 fn deposit_extract_roundtrip() {
112 let mask = H::from(0b0101_0101u8).widened(4);
114 let src = H::from(0b1011u8).widened(4);
115 let dep = DepositBits::deposit_bits(src, mask);
116 assert_eq!(dep, H::from(0b0100_0101u8));
118 assert_eq!(dep.len(), 4);
119
120 let ext = ExtractBits::extract_bits(dep, mask);
122 assert_eq!(ext, H::from(0b1011u8));
123 assert_eq!(ext.len(), 4);
124 }
125
126 #[test]
127 fn deposit_full_mask_is_identity() {
128 let mask = H::from(0xFFFF_FFFFu32);
129 let v = H::from(0x1234_5678u32);
130 assert_eq!(DepositBits::deposit_bits(v, mask), v);
131 assert_eq!(ExtractBits::extract_bits(v, mask), v);
132 }
133
134 #[test]
137 fn zero_mask_returns_zero_without_panic() {
138 let src = H::from(0x1234_5678u32);
139 let zero_mask = H::new_zero_with_len(4);
140 assert_eq!(DepositBits::deposit_bits(src, zero_mask), H::from(0u8));
141 assert_eq!(ExtractBits::extract_bits(src, zero_mask), H::from(0u8));
142
143 let z0 = H::new_zero_with_len(0);
145 assert_eq!(DepositBits::deposit_bits(z0, z0).len(), 0);
146 assert_eq!(ExtractBits::extract_bits(z0, z0).len(), 0);
147 }
148
149 #[test]
151 fn by_ref_matches_value() {
152 let mask = H::from(0b0101_0101u8).widened(4);
153 let src = H::from(0b1011u8).widened(4);
154 assert_eq!(
155 DepositBits::deposit_bits(&src, &mask),
156 DepositBits::deposit_bits(src, mask)
157 );
158 assert_eq!(
159 ExtractBits::extract_bits(&src, &mask),
160 ExtractBits::extract_bits(src, mask)
161 );
162 }
163}