205 const uint64_t* values,
size_t count,
207 if (bit_width == 0)
return;
210 size_t total_bits = count *
static_cast<size_t>(bit_width);
211 size_t total_bytes = (total_bits + 7) / 8;
213 size_t start = out.size();
214 out.resize(start + total_bytes, 0);
215 uint8_t* dst = out.data() + start;
217 size_t bit_offset = 0;
218 for (
size_t i = 0; i < count; ++i) {
219 uint64_t val = values[i];
220 int bits_remaining = bit_width;
221 size_t cur_bit = bit_offset;
222 while (bits_remaining > 0) {
223 size_t byte_idx = cur_bit / 8;
224 int bit_idx =
static_cast<int>(cur_bit % 8);
225 int bits_to_write = (std::min)(bits_remaining, 8 - bit_idx);
226 uint8_t mask =
static_cast<uint8_t
>(
227 (val & ((uint64_t{1} << bits_to_write) - 1)) << bit_idx);
228 dst[byte_idx] |= mask;
229 val >>= bits_to_write;
230 cur_bit +=
static_cast<size_t>(bits_to_write);
231 bits_remaining -= bits_to_write;
233 bit_offset +=
static_cast<size_t>(bit_width);
249 uint64_t* values,
size_t count,
251 if (bit_width == 0) {
252 for (
size_t i = 0; i < count; ++i) values[i] = 0;
256 uint64_t mask = (bit_width >= 64) ? ~uint64_t{0}
257 : (uint64_t{1} << bit_width) - 1;
259 size_t bit_offset = 0;
260 for (
size_t i = 0; i < count; ++i) {
262 int bits_remaining = bit_width;
263 size_t cur_bit = bit_offset;
265 while (bits_remaining > 0) {
266 size_t byte_idx = cur_bit / 8;
267 int bit_idx =
static_cast<int>(cur_bit % 8);
268 int bits_avail = 8 - bit_idx;
269 int bits_to_read = (std::min)(bits_remaining, bits_avail);
270 uint64_t chunk = (src[byte_idx] >> bit_idx)
271 & ((uint64_t{1} << bits_to_read) - 1);
272 val |= chunk << val_bit;
273 cur_bit +=
static_cast<size_t>(bits_to_read);
274 val_bit += bits_to_read;
275 bits_remaining -= bits_to_read;
277 values[i] = val & mask;
278 bit_offset +=
static_cast<size_t>(bit_width);
298[[nodiscard]]
inline std::vector<uint8_t>
encode_int64(
const int64_t* values,
300 std::vector<uint8_t> out;
312 out.reserve(32 + count);
325 size_t num_deltas = count - 1;
326 std::vector<int64_t> deltas(num_deltas);
327 for (
size_t i = 0; i < num_deltas; ++i) {
329 deltas[i] =
static_cast<int64_t
>(
static_cast<uint64_t
>(values[i + 1]) -
static_cast<uint64_t
>(values[i]));
333 size_t delta_idx = 0;
334 while (delta_idx < num_deltas) {
340 std::copy(deltas.begin() +
static_cast<ptrdiff_t
>(delta_idx),
341 deltas.begin() +
static_cast<ptrdiff_t
>(delta_idx + block_remaining),
342 block_deltas.begin());
345 int64_t min_delta = block_deltas[0];
346 for (
size_t i = 1; i < block_remaining; ++i) {
347 if (block_deltas[i] < min_delta) {
348 min_delta = block_deltas[i];
359 for (
size_t i = 0; i < block_remaining; ++i) {
361 adjusted[i] =
static_cast<uint64_t
>(block_deltas[i]) -
static_cast<uint64_t
>(min_delta);
372 uint64_t max_val = 0;
374 if (adjusted[mb_start + j] > max_val) {
375 max_val = adjusted[mb_start + j];
378 bit_widths[mb] =
static_cast<uint8_t
>(
bit_width_for(max_val));
383 out.push_back(bit_widths[mb]);
393 delta_idx += block_remaining;
438[[nodiscard]]
inline std::vector<int64_t>
decode_int64(
const uint8_t* data,
441 std::vector<int64_t> result;
442 if (num_values == 0 || size == 0)
return result;
443 if (num_values > 256 * 1024 * 1024)
return result;
444 result.reserve(num_values);
457 if (miniblock_count == 0 || block_size == 0)
return result;
460 static constexpr uint64_t MAX_DELTA_BLOCK_SIZE = 65536;
461 if (block_size > MAX_DELTA_BLOCK_SIZE)
return result;
462 static constexpr uint64_t MAX_MINIBLOCK_COUNT = 256;
463 if (miniblock_count > MAX_MINIBLOCK_COUNT)
return result;
464 if (block_size % miniblock_count != 0)
return result;
465 size_t values_per_miniblock =
static_cast<size_t>(block_size / miniblock_count);
466 if (values_per_miniblock == 0)
return result;
470 result.push_back(prev);
472 if (num_values == 1)
return result;
475 size_t values_remaining = num_values - 1;
477 while (values_remaining > 0 && pos < size) {
483 std::vector<uint8_t> bit_widths(
static_cast<size_t>(miniblock_count));
484 for (
size_t mb = 0; mb < static_cast<size_t>(miniblock_count); ++mb) {
486 bit_widths[mb] = data[pos++];
493 std::vector<uint64_t> unpacked(values_per_miniblock);
494 for (
size_t mb = 0; mb < static_cast<size_t>(miniblock_count); ++mb) {
495 if (values_remaining == 0)
break;
497 int bw = bit_widths[mb];
498 if (bw > 64)
return result;
502 for (
size_t j = 0; j < values_per_miniblock; ++j) {
507 size_t miniblock_bytes = (values_per_miniblock *
static_cast<size_t>(bw) + 7) / 8;
509 if (pos + miniblock_bytes > size) {
511 size_t avail = size - pos;
513 std::vector<uint8_t> padded(miniblock_bytes, 0);
514 std::memcpy(padded.data(), data + pos, avail);
516 values_per_miniblock, bw);
520 values_per_miniblock, bw);
521 pos += miniblock_bytes;
526 size_t to_emit = (std::min)(values_per_miniblock, values_remaining);
527 for (
size_t j = 0; j < to_emit; ++j) {
529 int64_t delta =
static_cast<int64_t
>(
530 unpacked[j] +
static_cast<uint64_t
>(min_delta));
531#if defined(__GNUC__) || defined(__clang__)
533 if (__builtin_add_overflow(prev, delta, &new_val)) {
539 if ((delta > 0 && prev > (std::numeric_limits<int64_t>::max)() - delta) ||
540 (delta < 0 && prev < (std::numeric_limits<int64_t>::min)() - delta)) {
545 result.push_back(prev);
547 values_remaining -= to_emit;
564[[nodiscard]]
inline std::vector<int32_t>
decode_int32(
const uint8_t* data,
568 std::vector<int32_t> result(wide.size());
569 for (
size_t i = 0; i < wide.size(); ++i) {
571 if (wide[i] < (std::numeric_limits<int32_t>::min)() || wide[i] > (std::numeric_limits<int32_t>::max)())
return {};
572 result[i] =
static_cast<int32_t
>(wide[i]);