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 + 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 + y;
27 let mut c = BitVec::new();
28 c.resize(len, false);
29 c.store_le(z);
30 c
31}
32
33#[allow(dead_code)]
35pub fn add_generic(
36 a: BitVec<u8, Msb0>,
37 b: BitVec<u8, Msb0>,
38) -> BitVec<u8, Msb0> {
39 if a.len() != b.len() {
40 panic!("bitvec add size mismatch");
41 }
42 let mut c = BitVec::new();
43 c.resize(a.len(), false);
44
45 for i in (1..a.len()).rev() {
46 let y = c[i];
47 let x = a[i] ^ b[i];
48 if !(a[i] | b[i]) {
49 continue;
50 }
51 c.set(i, x ^ y);
52 let mut z = (a[i] && b[i]) | y;
53 for j in (1..i).rev() {
54 if !z {
55 break;
56 }
57 z = c[j];
58 c.set(j, true);
59 }
60 }
61
62 c
63}
64
65pub fn mod_be(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
66 let len = usize::max(a.len(), b.len());
67
68 let x: u128 = a.load_be();
71 let y: u128 = b.load_be();
72 let z = x % y;
73 let mut c = BitVec::new();
74 c.resize(len, false);
75 c.store_be(z);
76 c
77}
78
79pub fn mod_le(a: BitVec<u8, Msb0>, b: BitVec<u8, Msb0>) -> BitVec<u8, Msb0> {
80 let len = usize::max(a.len(), b.len());
81
82 let x: u128 = a.load_le();
85 let y: u128 = b.load_le();
86 let z = x % y;
87 let mut c = BitVec::new();
88 c.resize(len, false);
89 c.store_le(z);
90 c
91}
92
93#[cfg(test)]
94mod tests {
95
96 #[test]
97 fn bitmath_add() {
98 use super::*;
99 let mut a = bitvec![mut u8, Msb0; 0; 16];
100 a.store_be(47);
101 let mut b = bitvec![mut u8, Msb0; 0; 16];
102 b.store_be(74);
103
104 println!("{:?}", a);
105 println!("{:?}", b);
106 let c = add_be(a, b);
107 println!("{:?}", c);
108
109 let cc: u128 = c.load_be();
110 assert_eq!(cc, 47u128 + 74u128);
111 }
112
113 #[test]
114 fn bitmath_add_mixed_size() {
115 use super::*;
116 let mut a = bitvec![mut u8, Msb0; 0; 8];
117 a.store_be(0xAB);
118 let mut b = bitvec![mut u8, Msb0; 0; 16];
119 b.store_be(0xCDE);
120
121 println!("{:?}", a);
122 println!("{:?}", b);
123 let c = add_be(a, b);
124 println!("{:?}", c);
125
126 let cc: u128 = c.load_be();
127 assert_eq!(cc, 0xABu128 + 0xCDEu128);
128 }
129
130 #[test]
131 fn bitmath_add_cascade() {
132 use super::*;
133 let mut a = bitvec![mut u8, Msb0; 0; 16];
134 a.store_be(47);
135 let mut b = bitvec![mut u8, Msb0; 0; 16];
136 b.store_be(74);
137 let mut c = bitvec![mut u8, Msb0; 0; 16];
138 c.store_be(123);
139 let mut d = bitvec![mut u8, Msb0; 0; 16];
140 d.store_be(9876);
141
142 let e = add_be(a, add_be(b, add_be(c, d)));
143
144 let ee: u128 = e.load_be();
145 assert_eq!(ee, 47u128 + 74u128 + 123u128 + 9876u128);
146 }
147
148 #[test]
149 fn bitmath_add_nest() {
150 use super::*;
151 let mut orig_l3_len = bitvec![mut u8, Msb0; 0; 16usize];
152 orig_l3_len.store_le(0xe9u128);
153 let x = add_le(
154 {
155 let mut x = bitvec![mut u8, Msb0; 0; 16usize];
156 x.store_le(14u128);
157 x
158 },
159 add_le(
160 orig_l3_len.clone(),
161 add_le(
162 {
163 let mut x = bitvec![mut u8, Msb0; 0; 16usize];
164 x.store_le(8u128);
165 x
166 },
167 {
168 let mut x = bitvec![mut u8, Msb0; 0; 16usize];
169 x.store_le(8u128);
170 x
171 },
172 ),
173 ),
174 );
175
176 let y: u128 = x.load_le();
177 assert_eq!(y, 0xe9 + 14 + 8 + 8);
178 }
179
180 #[test]
181 fn bitmath_mod() {
182 use super::*;
183 let mut a = bitvec![mut u8, Msb0; 0; 16];
184 a.store_be(47);
185 let mut b = bitvec![mut u8, Msb0; 0; 16];
186 b.store_be(7);
187
188 println!("{:?}", a);
189 println!("{:?}", b);
190 let c = mod_be(a, b);
191 println!("{:?}", c);
192
193 let cc: u128 = c.load_be();
194 assert_eq!(cc, 47u128 % 7u128);
195 }
196}