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

Function unpack_width

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

Source from the content-addressed store, hash-verified

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

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