smallint/
logic.rs

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);