MCPcopy Create free account
hub / github.com/apache/arrow / unpack_width

Function unpack_width

cpp/src/arrow/util/bpacking_dispatch_internal.h:194–252  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

192template <int kPackedBitWidth, template <typename, int> typename Unpacker,
193 typename UnpackedUInt>
194void unpack_width(const uint8_t* in, UnpackedUInt* out, int batch_size, int bit_offset,
195 int max_read_bytes) {
196 if constexpr (kPackedBitWidth == 0) {
197 // Easy case to handle, simply setting memory to zero.
198 return unpack_null(in, out, batch_size);
199 } else {
200 // Number of bytes to read according to batch_size.
201 const int bytes_batch = static_cast<int>(
202 bit_util::BytesForBits(batch_size * kPackedBitWidth + bit_offset));
203 // If specified, max_read_bytes must be greater that the bytes needed to extract the
204 // number of desired values.
205 ARROW_DCHECK(max_read_bytes < 0 || bytes_batch <= max_read_bytes);
206 const uint8_t* in_end = in + (max_read_bytes >= 0 ? max_read_bytes : bytes_batch);
207
208 // In case of misalignment, we need to run the prolog until aligned.
209 int extracted =
210 unpack_exact<kPackedBitWidth, true>(in, in_end, out, batch_size, bit_offset);
211 // We either extracted everything or found a alignment
212 const int start_bit = extracted * kPackedBitWidth + bit_offset;
213 ARROW_DCHECK((extracted == batch_size) || ((start_bit) % 8 == 0));
214 batch_size -= extracted;
215 ARROW_DCHECK_GE(batch_size, 0);
216 in += start_bit / 8;
217 out += extracted;
218
219 if constexpr (kPackedBitWidth == 8 * sizeof(UnpackedUInt)) {
220 // Only memcpy / static_cast
221 return unpack_full(in, out, batch_size);
222 } else {
223 using UnpackerForWidth = Unpacker<UnpackedUInt, kPackedBitWidth>;
224 // Number of values extracted by one iteration of the kernel
225 constexpr auto kValuesUnpacked = UnpackerForWidth::kValuesUnpacked;
226 // Number of bytes read, but not necessarily unpacked, by one iteration of the
227 // kernel. This constant prevent reading past buffer end.
228 constexpr auto kBytesRead = UnpackerForWidth::kBytesRead;
229
230 if constexpr (kValuesUnpacked > 0) {
231 const uint8_t* in_last = in_end - kBytesRead;
232 // Running the optimized kernel for batch extraction
233 while ((batch_size >= kValuesUnpacked) && (in <= in_last)) {
234 in = UnpackerForWidth::unpack(in, out);
235 out += kValuesUnpacked;
236 batch_size -= kValuesUnpacked;
237 }
238
239 // Performance check making sure we ran the kernel loop as much as possible:
240 // Either we ran out because we could not pack enough values, or because we would
241 // overread.
242 ARROW_DCHECK((batch_size < kValuesUnpacked) || (in_end - in) < kBytesRead);
243 }
244
245 // Running the epilog for the remaining values that don't fit in a kernel
246 ARROW_DCHECK_GE(batch_size, 0);
247 ARROW_COMPILER_ASSUME(batch_size >= 0);
248 unpack_exact<kPackedBitWidth, false>(in, in_end, out, batch_size,
249 /* bit_offset= */ 0);
250 }
251 }

Callers

nothing calls this directly

Calls 4

unpack_nullFunction · 0.85
BytesForBitsFunction · 0.85
unpack_fullFunction · 0.85
unpackFunction · 0.70

Tested by

no test coverage detected