1use super::{Buffer, MutableBuffer};
19use crate::util::bit_util::ceil;
20
21pub fn bitwise_quaternary_op_helper<F>(
24 buffers: [&Buffer; 4],
25 offsets: [usize; 4],
26 len_in_bits: usize,
27 op: F,
28) -> Buffer
29where
30 F: Fn(u64, u64, u64, u64) -> u64,
31{
32 let first_chunks = buffers[0].bit_chunks(offsets[0], len_in_bits);
33 let second_chunks = buffers[1].bit_chunks(offsets[1], len_in_bits);
34 let third_chunks = buffers[2].bit_chunks(offsets[2], len_in_bits);
35 let fourth_chunks = buffers[3].bit_chunks(offsets[3], len_in_bits);
36
37 let chunks = first_chunks
38 .iter()
39 .zip(second_chunks.iter())
40 .zip(third_chunks.iter())
41 .zip(fourth_chunks.iter())
42 .map(|(((first, second), third), fourth)| op(first, second, third, fourth));
43 let mut buffer = unsafe { MutableBuffer::from_trusted_len_iter(chunks) };
46
47 let remainder_bytes = ceil(first_chunks.remainder_len(), 8);
48 let rem = op(
49 first_chunks.remainder_bits(),
50 second_chunks.remainder_bits(),
51 third_chunks.remainder_bits(),
52 fourth_chunks.remainder_bits(),
53 );
54 let rem = &rem.to_le_bytes()[0..remainder_bytes];
56 buffer.extend_from_slice(rem);
57
58 buffer.into()
59}
60
61pub fn bitwise_bin_op_helper<F>(
64 left: &Buffer,
65 left_offset_in_bits: usize,
66 right: &Buffer,
67 right_offset_in_bits: usize,
68 len_in_bits: usize,
69 mut op: F,
70) -> Buffer
71where
72 F: FnMut(u64, u64) -> u64,
73{
74 let left_chunks = left.bit_chunks(left_offset_in_bits, len_in_bits);
75 let right_chunks = right.bit_chunks(right_offset_in_bits, len_in_bits);
76
77 let chunks = left_chunks
78 .iter()
79 .zip(right_chunks.iter())
80 .map(|(left, right)| op(left, right));
81 let mut buffer = unsafe { MutableBuffer::from_trusted_len_iter(chunks) };
84
85 let remainder_bytes = ceil(left_chunks.remainder_len(), 8);
86 let rem = op(left_chunks.remainder_bits(), right_chunks.remainder_bits());
87 let rem = &rem.to_le_bytes()[0..remainder_bytes];
89 buffer.extend_from_slice(rem);
90
91 buffer.into()
92}
93
94pub fn bitwise_unary_op_helper<F>(
97 left: &Buffer,
98 offset_in_bits: usize,
99 len_in_bits: usize,
100 mut op: F,
101) -> Buffer
102where
103 F: FnMut(u64) -> u64,
104{
105 let mut result =
107 MutableBuffer::new(ceil(len_in_bits, 8)).with_bitset(len_in_bits / 64 * 8, false);
108
109 let left_chunks = left.bit_chunks(offset_in_bits, len_in_bits);
110
111 let result_chunks = result.typed_data_mut::<u64>().iter_mut();
112
113 result_chunks
114 .zip(left_chunks.iter())
115 .for_each(|(res, left)| {
116 *res = op(left);
117 });
118
119 let remainder_bytes = ceil(left_chunks.remainder_len(), 8);
120 let rem = op(left_chunks.remainder_bits());
121 let rem = &rem.to_le_bytes()[0..remainder_bytes];
123 result.extend_from_slice(rem);
124
125 result.into()
126}
127
128pub fn buffer_bin_and(
131 left: &Buffer,
132 left_offset_in_bits: usize,
133 right: &Buffer,
134 right_offset_in_bits: usize,
135 len_in_bits: usize,
136) -> Buffer {
137 bitwise_bin_op_helper(
138 left,
139 left_offset_in_bits,
140 right,
141 right_offset_in_bits,
142 len_in_bits,
143 |a, b| a & b,
144 )
145}
146
147pub fn buffer_bin_or(
150 left: &Buffer,
151 left_offset_in_bits: usize,
152 right: &Buffer,
153 right_offset_in_bits: usize,
154 len_in_bits: usize,
155) -> Buffer {
156 bitwise_bin_op_helper(
157 left,
158 left_offset_in_bits,
159 right,
160 right_offset_in_bits,
161 len_in_bits,
162 |a, b| a | b,
163 )
164}
165
166pub fn buffer_bin_xor(
169 left: &Buffer,
170 left_offset_in_bits: usize,
171 right: &Buffer,
172 right_offset_in_bits: usize,
173 len_in_bits: usize,
174) -> Buffer {
175 bitwise_bin_op_helper(
176 left,
177 left_offset_in_bits,
178 right,
179 right_offset_in_bits,
180 len_in_bits,
181 |a, b| a ^ b,
182 )
183}
184
185pub fn buffer_bin_and_not(
188 left: &Buffer,
189 left_offset_in_bits: usize,
190 right: &Buffer,
191 right_offset_in_bits: usize,
192 len_in_bits: usize,
193) -> Buffer {
194 bitwise_bin_op_helper(
195 left,
196 left_offset_in_bits,
197 right,
198 right_offset_in_bits,
199 len_in_bits,
200 |a, b| a & !b,
201 )
202}
203
204pub fn buffer_unary_not(left: &Buffer, offset_in_bits: usize, len_in_bits: usize) -> Buffer {
207 bitwise_unary_op_helper(left, offset_in_bits, len_in_bits, |a| !a)
208}