1use bitvec::prelude::*;
4
5pub fn add_be(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
6 let len = usize::max(a.len(), b.len());
7
8 let x: u128 = a.load_be();
11 let y: u128 = b.load_be();
12 let z = x.wrapping_add(y);
13 let mut c = BitVec::new();
14 c.resize(len, false);
15 c.store_be(z);
16 c
17}
18
19pub fn add_le(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
20 let len = usize::max(a.len(), b.len());
21
22 let x: u128 = a.load_le();
25 let y: u128 = b.load_le();
26 let z = x.wrapping_add(y);
27 let mut c = BitVec::new();
28 c.resize(len, false);
29 c.store_le(z);
30 c
31}
32
33pub fn sub_be(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
34 let len = usize::max(a.len(), b.len());
35 let x: u128 = a.load_be();
36 let y: u128 = b.load_be();
37 let z = x.wrapping_sub(y);
38 let mut c = BitVec::new();
39 c.resize(len, false);
40 c.store_be(z);
41 c
42}
43
44pub fn sub_le(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
45 let len = usize::max(a.len(), b.len());
46 let x: u128 = a.load_le();
47 let y: u128 = b.load_le();
48 let z = x.wrapping_sub(y);
49 let mut c = BitVec::new();
50 c.resize(len, false);
51 c.store_le(z);
52 c
53}
54
55#[allow(dead_code)]
57pub fn add_generic(
58 a: BitVec<u8, Msb0>,
59 b: BitVec<u8, Msb0>,
60) -> BitVec<u8, Msb0> {
61 if a.len() != b.len() {
62 panic!("bitvec add size mismatch");
63 }
64 let mut c = BitVec::new();
65 c.resize(a.len(), false);
66
67 for i in (1..a.len()).rev() {
68 let y = c[i];
69 let x = a[i] ^ b[i];
70 if !(a[i] | b[i]) {
71 continue;
72 }
73 c.set(i, x ^ y);
74 let mut z = (a[i] && b[i]) | y;
75 for j in (1..i).rev() {
76 if !z {
77 break;
78 }
79 z = c[j];
80 c.set(j, true);
81 }
82 }
83
84 c
85}
86
87pub fn mod_be(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
88 let len = usize::max(a.len(), b.len());
89
90 let x: u128 = a.load_be();
93 let y: u128 = b.load_be();
94 let z = x % y;
95 let mut c = BitVec::new();
96 c.resize(len, false);
97 c.store_be(z);
98 c
99}
100
101pub fn mod_le(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
102 let len = usize::max(a.len(), b.len());
103
104 let x: u128 = a.load_le();
107 let y: u128 = b.load_le();
108 let z = x % y;
109 let mut c = BitVec::new();
110 c.resize(len, false);
111 c.store_le(z);
112 c
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn bitmath_add_be() {
121 let mut a = bitvec![mut u8, Msb0; 0; 16];
122 a.store_be(47);
123 let mut b = bitvec![mut u8, Msb0; 0; 16];
124 b.store_be(74);
125
126 println!("{:?}", a);
127 println!("{:?}", b);
128 let c = add_be(a, b);
129 println!("{:?}", c);
130
131 let cc: u128 = c.load_be();
132 assert_eq!(cc, 47u128 + 74u128);
133 }
134
135 #[test]
136 fn bitmath_add_le() {
137 let mut a = bitvec![mut u8, Msb0; 0; 16];
138 a.store_le(47);
139 let mut b = bitvec![mut u8, Msb0; 0; 16];
140 b.store_le(74);
141
142 println!("{:?}", a);
143 println!("{:?}", b);
144 let c = add_le(a, b);
145 println!("{:?}", c);
146
147 let cc: u128 = c.load_le();
148 assert_eq!(cc, 47u128 + 74u128);
149 }
150
151 #[test]
152 fn bitmath_sub_be() {
153 use super::*;
154 let mut a = bitvec![mut u8, Msb0; 0; 16];
155 a.store_be(74);
156 let mut b = bitvec![mut u8, Msb0; 0; 16];
157 b.store_be(47);
158
159 println!("{:?}", a);
160 println!("{:?}", b);
161 let c = sub_be(a, b);
162 println!("{:?}", c);
163
164 let cc: u128 = c.load_be();
165 assert_eq!(cc, 74u128 - 47u128);
166 }
167
168 #[test]
169 fn bitmath_sub_le() {
170 use super::*;
171 let mut a = bitvec![mut u8, Msb0; 0; 16];
172 a.store_le(74);
173 let mut b = bitvec![mut u8, Msb0; 0; 16];
174 b.store_le(47);
175
176 println!("{:?}", a);
177 println!("{:?}", b);
178 let c = sub_le(a, b);
179 println!("{:?}", c);
180
181 let cc: u128 = c.load_le();
182 assert_eq!(cc, 74u128 - 47u128);
183 }
184
185 #[test]
186 fn bitmath_add_mixed_size() {
187 use super::*;
188 let mut a = bitvec![mut u8, Msb0; 0; 8];
189 a.store_be(0xAB);
190 let mut b = bitvec![mut u8, Msb0; 0; 16];
191 b.store_be(0xCDE);
192
193 println!("{:?}", a);
194 println!("{:?}", b);
195 let c = add_be(a, b);
196 println!("{:?}", c);
197
198 let cc: u128 = c.load_be();
199 assert_eq!(cc, 0xABu128 + 0xCDEu128);
200 }
201
202 #[test]
203 fn bitmath_add_cascade() {
204 use super::*;
205 let mut a = bitvec![mut u8, Msb0; 0; 16];
206 a.store_be(47);
207 let mut b = bitvec![mut u8, Msb0; 0; 16];
208 b.store_be(74);
209 let mut c = bitvec![mut u8, Msb0; 0; 16];
210 c.store_be(123);
211 let mut d = bitvec![mut u8, Msb0; 0; 16];
212 d.store_be(9876);
213
214 let e = add_be(a, add_be(b, add_be(c, d)));
215
216 let ee: u128 = e.load_be();
217 assert_eq!(ee, 47u128 + 74u128 + 123u128 + 9876u128);
218 }
219
220 #[test]
221 fn bitmath_add_nest() {
222 use super::*;
223 let mut orig_l3_len = bitvec![mut u8, Msb0; 0; 16usize];
224 orig_l3_len.store_le(0xe9u128);
225 let x = add_le(
226 {
227 let mut x = bitvec![mut u8, Msb0; 0; 16usize];
228 x.store_le(14u128);
229 x
230 },
231 add_le(
232 orig_l3_len.clone(),
233 add_le(
234 {
235 let mut x = bitvec![mut u8, Msb0; 0; 16usize];
236 x.store_le(8u128);
237 x
238 },
239 {
240 let mut x = bitvec![mut u8, Msb0; 0; 16usize];
241 x.store_le(8u128);
242 x
243 },
244 ),
245 ),
246 );
247
248 let y: u128 = x.load_le();
249 assert_eq!(y, 0xe9 + 14 + 8 + 8);
250 }
251
252 #[test]
253 fn bitmath_mod() {
254 use super::*;
255 let mut a = bitvec![mut u8, Msb0; 0; 16];
256 a.store_be(47);
257 let mut b = bitvec![mut u8, Msb0; 0; 16];
258 b.store_be(7);
259
260 println!("{:?}", a);
261 println!("{:?}", b);
262 let c = mod_be(a, b);
263 println!("{:?}", c);
264
265 let cc: u128 = c.load_be();
266 assert_eq!(cc, 47u128 % 7u128);
267 }
268}