| 1139 | |
| 1140 | template <typename DType> |
| 1141 | void DeltaBitPackEncoder<DType>::FlushBlock() { |
| 1142 | if (values_current_block_ == 0) { |
| 1143 | return; |
| 1144 | } |
| 1145 | |
| 1146 | // Calculate the frame of reference for this miniblock. This value will be subtracted |
| 1147 | // from all deltas to guarantee all deltas are positive for encoding. |
| 1148 | const T min_delta = |
| 1149 | *std::min_element(deltas_.begin(), deltas_.begin() + values_current_block_); |
| 1150 | bit_writer_.PutZigZagVlqInt(min_delta); |
| 1151 | |
| 1152 | // Call to GetNextBytePtr reserves mini_blocks_per_block_ bytes of space to write |
| 1153 | // bit widths of miniblocks as they become known during the encoding. |
| 1154 | uint8_t* bit_width_data = bit_writer_.GetNextBytePtr(mini_blocks_per_block_); |
| 1155 | DCHECK(bit_width_data != nullptr); |
| 1156 | |
| 1157 | const uint32_t num_miniblocks = |
| 1158 | static_cast<uint32_t>(std::ceil(static_cast<double>(values_current_block_) / |
| 1159 | static_cast<double>(values_per_mini_block_))); |
| 1160 | for (uint32_t i = 0; i < num_miniblocks; i++) { |
| 1161 | const uint32_t values_current_mini_block = |
| 1162 | std::min(values_per_mini_block_, values_current_block_); |
| 1163 | |
| 1164 | const uint32_t start = i * values_per_mini_block_; |
| 1165 | const T max_delta = *std::max_element( |
| 1166 | deltas_.begin() + start, deltas_.begin() + start + values_current_mini_block); |
| 1167 | |
| 1168 | // The minimum number of bits required to write any of values in deltas_ vector. |
| 1169 | // See overflow comment above. |
| 1170 | // TODO: We can remove this condition once CRAN upgrades its macOS |
| 1171 | // SDK from 11.3. |
| 1172 | // __apple_build_version__ should be defined only on Apple clang |
| 1173 | #if defined(__apple_build_version__) && !defined(__cpp_lib_bitops) |
| 1174 | const auto bit_width = bit_width_data[i] = |
| 1175 | std::log2p1(static_cast<UT>(max_delta) - static_cast<UT>(min_delta)); |
| 1176 | #else |
| 1177 | const auto bit_width = bit_width_data[i] = |
| 1178 | std::bit_width(static_cast<UT>(max_delta) - static_cast<UT>(min_delta)); |
| 1179 | #endif |
| 1180 | |
| 1181 | for (uint32_t j = start; j < start + values_current_mini_block; j++) { |
| 1182 | // Convert delta to frame of reference. See overflow comment above. |
| 1183 | const UT value = static_cast<UT>(deltas_[j]) - static_cast<UT>(min_delta); |
| 1184 | bit_writer_.PutValue(value, bit_width); |
| 1185 | } |
| 1186 | // If there are not enough values to fill the last mini block, we pad the mini block |
| 1187 | // with zeroes so that its length is the number of values in a full mini block |
| 1188 | // multiplied by the bit width. |
| 1189 | for (uint32_t j = values_current_mini_block; j < values_per_mini_block_; j++) { |
| 1190 | bit_writer_.PutValue(0, bit_width); |
| 1191 | } |
| 1192 | values_current_block_ -= values_current_mini_block; |
| 1193 | } |
| 1194 | |
| 1195 | // If, in the last block, less than <number of miniblocks in a block> miniblocks are |
| 1196 | // needed to store the values, the bytes storing the bit widths of the unneeded |
| 1197 | // miniblocks are still present, their value should be zero, but readers must accept |
| 1198 | // arbitrary values as well. |
nothing calls this directly
no test coverage detected