//===----------------------------------------------------------------------===// // DuckDB // // duckdb/storage/compression/chimp/packed_data.hpp // // //===----------------------------------------------------------------------===// #pragma once #include "duckdb/storage/compression/chimp/algorithm/chimp_utils.hpp" #include "duckdb.h" namespace duckdb { struct UnpackedData { uint8_t leading_zero; uint8_t significant_bits; uint8_t index; }; template struct PackedDataUtils { private: static constexpr uint8_t INDEX_BITS_SIZE = 7; static constexpr uint8_t LEADING_BITS_SIZE = 3; static constexpr uint8_t INDEX_MASK = ((uint8_t)1 << INDEX_BITS_SIZE) - 1; static constexpr uint8_t LEADING_MASK = ((uint8_t)1 << LEADING_BITS_SIZE) - 1; static constexpr uint8_t INDEX_SHIFT_AMOUNT = (sizeof(uint16_t) * 8) - INDEX_BITS_SIZE; static constexpr uint8_t LEADING_SHIFT_AMOUNT = INDEX_SHIFT_AMOUNT - LEADING_BITS_SIZE; public: //|----------------| //! packed_data(16) bits // IIIIIII //! Index (7 bits, shifted by 9) // LLL //! LeadingZeros (3 bits, shifted by 6) // SSSSSS //! SignificantBits (6 bits) static inline void Unpack(uint16_t packed_data, UnpackedData &dest) { dest.index = packed_data >> INDEX_SHIFT_AMOUNT & INDEX_MASK; dest.leading_zero = packed_data >> LEADING_SHIFT_AMOUNT & LEADING_MASK; dest.significant_bits = packed_data & SignificantBits::mask; // Verify that combined, this is not bigger than the full size of the type D_ASSERT(dest.significant_bits + dest.leading_zero <= (sizeof(CHIMP_TYPE) * 8)); } static inline uint16_t Pack(uint8_t index, uint8_t leading_zero, uint8_t significant_bits) { static constexpr uint8_t BIT_SIZE = (sizeof(CHIMP_TYPE) * 8); uint16_t result = 0; result += ((uint32_t)BIT_SIZE << 3) * (ChimpConstants::BUFFER_SIZE + index); result += BIT_SIZE * (leading_zero & 7); if (BIT_SIZE == 32) { // Shift the result by 1 to occupy the 16th bit result <<= 1; } result += (significant_bits & 63); return result; } }; template struct PackedDataBuffer { public: PackedDataBuffer() : index(0), buffer(nullptr) { } public: void SetBuffer(uint16_t *buffer) { this->buffer = buffer; this->index = 0; } void Reset() { this->index = 0; } inline void Insert(uint16_t packed_data) { if (!EMPTY) { buffer[index] = packed_data; } index++; } idx_t index; uint16_t *buffer; }; } // namespace duckdb