1use crate::smallint::SmallUintType;
2use crate::SmallUint;
3use core::mem::ManuallyDrop;
4use core::ops::{BitAnd, BitOr, BitXor};
5
6macro_rules! basic_op {
7 ($imp:ident, $typ:ty, $fun:ident) => {
8 impl<'a, 'b> $imp<&'a $typ> for &'b $typ {
9 type Output = $typ;
10
11 fn $fun(self, rhs: &$typ) -> Self::Output {
12 $fun(self, rhs)
13 }
14 }
15
16 impl<'a> $imp<$typ> for &'a $typ {
17 type Output = $typ;
18
19 fn $fun(self, rhs: $typ) -> Self::Output {
20 self.$fun(&rhs)
21 }
22 }
23
24 impl<'a> $imp<&'a $typ> for $typ {
25 type Output = $typ;
26
27 fn $fun(self, rhs: &$typ) -> Self::Output {
28 (&self).$fun(rhs)
29 }
30 }
31
32 impl $imp<$typ> for $typ {
33 type Output = $typ;
34
35 fn $fun(self, rhs: $typ) -> Self::Output {
36 (&self).$fun(&rhs)
37 }
38 }
39 };
40}
41
42fn bitand(a: &SmallUint, b: &SmallUint) -> SmallUint {
43 match (&a.0, &b.0) {
44 (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => {
45 SmallUint(SmallUintType::Inline(i & j))
46 }
47
48 (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s)))
49 | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => {
50 let slice = unsafe { core::slice::from_raw_parts(r, s) };
51 let mut j = 0u128;
52 for i in 0..4 {
53 j <<= 32;
54
55 j |= slice[3 - i] as u128;
56 }
57 SmallUint(SmallUintType::Inline(i & j))
58 }
59
60 (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
61 let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
62 let slice2 = unsafe { core::slice::from_raw_parts(i, j) };
63
64 let min = std::cmp::min(slice1.len(), slice2.len());
65
66 let mut res = Vec::with_capacity(min);
67
68 for l in 0..min {
69 res.push(slice1[l] & slice2[l]);
70 }
71
72 while res.len() != 1 && res[res.len() - 1] == 0 {
73 res.pop();
74 }
75
76 if res.len() <= 4 {
77 let mut r = 0u128;
78 for t in 0..res.len() {
79 r <<= 32;
80 r |= res[res.len() - 1 - t] as u128;
81 }
82 SmallUint(SmallUintType::Inline(r))
83 } else {
84 let mut slice = ManuallyDrop::new(res.into_boxed_slice());
85 SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
86 }
87 }
88 }
89}
90
91basic_op!(BitAnd, SmallUint, bitand);
92
93fn bitor(a: &SmallUint, b: &SmallUint) -> SmallUint {
94 match (&a.0, &b.0) {
95 (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => {
96 SmallUint(SmallUintType::Inline(i | j))
97 }
98 (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s)))
99 | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => {
100 let slice = unsafe { core::slice::from_raw_parts(r, s) };
101
102 let mut retvec = slice.to_vec();
103
104 let mut v = i;
105 #[allow(clippy::needless_range_loop)]
106 for r in 0..4 {
107 retvec[r] |= v as u32;
108
109 v >>= 32;
110 }
111
112 let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
113
114 SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len())))
115 }
116
117 (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
118 let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
119 let slice2 = unsafe { core::slice::from_raw_parts(i, j) };
120
121 let m = std::cmp::min(slice1.len(), slice2.len());
122
123 let mut retvec;
124 if slice1.len() > slice2.len() {
125 retvec = slice1.to_vec();
126 } else {
127 retvec = slice2.to_vec();
128 }
129
130 for t in 0..m {
131 retvec[t] = slice1[t] | slice2[t];
132 }
133
134 let mut slice = ManuallyDrop::new(retvec.into_boxed_slice());
135
136 SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
137 }
138 }
139}
140
141basic_op!(BitOr, SmallUint, bitor);
142
143fn bitxor(a: &SmallUint, b: &SmallUint) -> SmallUint {
144 match (&a.0, &b.0) {
145 (&SmallUintType::Inline(i), &SmallUintType::Inline(j)) => {
146 SmallUint(SmallUintType::Inline(i ^ j))
147 }
148 (&SmallUintType::Inline(i), &SmallUintType::Heap((r, s)))
149 | (&SmallUintType::Heap((r, s)), &SmallUintType::Inline(i)) => {
150 let slice = unsafe { core::slice::from_raw_parts(r, s) };
151
152 let mut retvec = slice.to_vec();
153
154 let mut v = i;
155 #[allow(clippy::needless_range_loop)]
156 for r in 0..4 {
157 retvec[r] ^= v as u32;
158
159 v >>= 32;
160 }
161
162 let mut retslice = ManuallyDrop::new(retvec.into_boxed_slice());
163
164 SmallUint(SmallUintType::Heap((retslice.as_mut_ptr(), retslice.len())))
165 }
166
167 (&SmallUintType::Heap((r, s)), &SmallUintType::Heap((i, j))) => {
168 let slice1 = unsafe { core::slice::from_raw_parts(r, s) };
169 let slice2 = unsafe { core::slice::from_raw_parts(i, j) };
170
171 let m = std::cmp::min(slice1.len(), slice2.len());
172
173 let mut res;
174 if slice1.len() > slice2.len() {
175 res = slice1.to_vec();
176 } else {
177 res = slice2.to_vec();
178 }
179
180 for t in 0..m {
181 res[t] = slice1[t] ^ slice2[t];
182 }
183
184 while res.len() != 1 && res[res.len() - 1] == 0 {
185 res.pop();
186 }
187
188 if res.len() <= 4 {
189 let mut r = 0u128;
190 for t in 0..res.len() {
191 r <<= 32;
192 r |= res[res.len() - 1 - t] as u128;
193 }
194 SmallUint(SmallUintType::Inline(r))
195 } else {
196 let mut slice = ManuallyDrop::new(res.into_boxed_slice());
197 SmallUint(SmallUintType::Heap((slice.as_mut_ptr(), slice.len())))
198 }
199 }
200 }
201}
202
203basic_op!(BitXor, SmallUint, bitxor);