4 #include "util/coding/double_compressor.h" 12 #include "base/bits.h" 13 #include "base/endian.h" 14 #include "base/logging.h" 15 #include "base/integral_types.h" 16 #include "util/math/float2decimal.h" 23 static inline unsigned DecimalCost(
unsigned dec_len) {
27 return (dec_len + 1) / 2;
30 constexpr uint8_t kRawBit = 1 << 7;
31 constexpr uint8_t kHasExceptionsBit = 1 << 6;
33 double FromPositive(int64_t significand,
int exponent) {
34 while (significand % 10 == 0) {
38 DCHECK_LE(Bits::FindMSBSet64NonZero(significand), 52);
39 double res(significand);
40 return res * exp10(exponent);
44 double FromDecimal(int64_t significand,
int exponent) {
49 return -FromPositive(-significand, exponent);
51 return FromPositive(significand, exponent);
54 constexpr
size_t kShuffleStep = 1024;
56 inline void bitshuffle2(
const int64_t* src,
size_t count, uint8_t* dest, uint8_t* tmp) {
57 const uint8_t* src_b = reinterpret_cast<const uint8_t*>(src);
58 const uint8_t* src_e = src_b + count *
sizeof(uint64_t);
60 for (; src_b + kShuffleStep <= src_e; src_b += kShuffleStep) {
61 bitshuffle(
sizeof(uint64_t), kShuffleStep, src_b, ptr, tmp);
65 bitshuffle(
sizeof(uint64_t), src_e - src_b, src_b, ptr, tmp);
69 inline void bitunshuffle2(
const uint8_t* src,
size_t sz, uint8_t* dest) {
70 uint8_t tmp[kShuffleStep];
74 for (; i + kShuffleStep <= sz; i += kShuffleStep) {
75 bitunshuffle(
sizeof(uint64_t), kShuffleStep, src + i, ptr, tmp);
79 bitunshuffle(
sizeof(uint64_t), sz - i, src + i, ptr, tmp);
87 ExpInfo() { std::fill(cnt, cnt + 17, 0); }
89 uint32_t count()
const {
return std::accumulate(cnt, cnt + 17, uint32_t(0)); }
90 uint32_t Cost(
int edelta)
const {
94 for (
unsigned i = 0; i < 17; ++i) {
95 res += cnt[i] * DecimalCost(edelta + i + 1);
101 void DoubleCompressor::DecimalHeader::Serialize(uint8_t flags, uint8_t* dest) {
102 LittleEndian::Store64(dest, min_val);
103 dest +=
sizeof(uint64_t);
104 LittleEndian::Store16(dest, exponent);
105 dest +=
sizeof(uint16_t);
107 LittleEndian::Store16(dest, lz4_size);
108 dest +=
sizeof(uint16_t);
110 if (flags & kHasExceptionsBit)
111 LittleEndian::Store16(dest, first_exception_index);
114 uint32_t DoubleCompressor::DecimalHeader::Parse(uint8_t flags,
const uint8_t* src) {
115 min_val = LittleEndian::Load64(src);
116 src +=
sizeof(uint64_t);
117 exponent = LittleEndian::Load16(src);
118 src +=
sizeof(uint16_t);
120 lz4_size = LittleEndian::Load16(src);
121 src +=
sizeof(uint16_t);
124 if (flags & kHasExceptionsBit) {
125 first_exception_index = LittleEndian::Load16(src);
131 unsigned DoubleCompressor::NormalizeDecimals(
unsigned count,
const double* dbl_src) {
132 aux_->header.min_val = kuint64max;
133 aux_->header.first_exception_index = count;
135 unsigned normal_cnt = 0;
136 unsigned prev_exception_index = 0;
137 unsigned exception_index = 0;
139 for (
unsigned i = 0; i < count; ++i) {
140 const Decimal& dec = aux_->dec[i];
142 if (dec.CanNormalize(aux_->header.exponent)) {
143 int64_t normal_val = dec.val * base::Power10(dec.exp - aux_->header.exponent);
144 aux_->normalized[i] = normal_val;
145 if (normal_val < aux_->header.min_val)
146 aux_->header.min_val = normal_val;
149 aux_->exceptions[exception_index++] = dbl_src[i];
151 if (aux_->header.first_exception_index != count) {
152 aux_->normalized[prev_exception_index] = i - prev_exception_index;
154 aux_->header.first_exception_index = i;
156 prev_exception_index = i;
160 if (exception_index) {
161 aux_->normalized[prev_exception_index] = 0;
164 exception_index = aux_->header.first_exception_index;
167 for (
unsigned i = 0; i < count; ++i) {
168 if (i == exception_index) {
169 exception_index += aux_->normalized[i];
171 aux_->normalized[i] -= aux_->header.min_val;
178 uint32_t DoubleCompressor::Commit(
const double* src, uint32_t count, uint8_t* dest) {
180 return WriteRawDoubles(src, count, dest);
183 CHECK_LE(count, BLOCK_MAX_LEN);
189 for (
unsigned i = 0; i < count; ++i) {
190 Decimal& dec = aux_->dec[i];
191 CHECK(util::dtoa::ToDecimal(src[i], &dec.val, &dec.exp, &dec.dec_len));
193 DCHECK_GT(dec.dec_len, 0);
194 DCHECK_LE(dec.dec_len, 17);
197 if (dec.val != 0 && dec.dec_len < 17) {
198 ++exp_map[dec.exp].cnt[dec.dec_len - 1];
201 uint32_t cost = Optimize(exp_map);
203 unsigned normal_cnt = NormalizeDecimals(count, src);
204 if (normal_cnt < count / 2) {
205 return WriteRawDoubles(src, count, dest);
207 VLOG(1) <<
"Cost: " << cost <<
" normalized count: " << normal_cnt;
210 uint8_t* shuffle_buf = reinterpret_cast<uint8_t*>(aux_->dec);
211 bitshuffle2(aux_->normalized, count, shuffle_buf, dest);
213 char*
const cdest = reinterpret_cast<char*>(dest);
214 char* next = cdest + 3 + DECIMAL_HEADER_MAX_SIZE - 2;
215 char* end = cdest + CommitMaxSize(count);
216 unsigned exc_count = count - normal_cnt;
220 flags = kHasExceptionsBit;
222 const unsigned kByteSize =
sizeof(uint64_t) * count;
223 int res = LZ4_compress_fast(reinterpret_cast<const char*>(shuffle_buf), next,
224 kByteSize, LZ4_COMPRESSBOUND(kByteSize), 3 );
226 if ((res + 8 * exc_count) * 1.1 > kByteSize) {
227 return WriteRawDoubles(src, count, dest);
230 aux_->header.lz4_size = res;
231 aux_->header.Serialize(flags, dest + 3);
235 shuffle(
sizeof(uint64_t), exc_count *
sizeof(uint64_t),
236 reinterpret_cast<const uint8_t*>(aux_->exceptions), shuffle_buf);
238 res = LZ4_compress_fast(reinterpret_cast<const char*>(shuffle_buf), next,
239 exc_count * 8, end - next, 5);
243 uint32_t written = next - cdest;
245 CHECK_LE(written, COMPRESS_BLOCK_BOUND);
246 LittleEndian::Store16(dest + 1, written - 3);
251 uint32_t DoubleCompressor::Optimize(
const ExponentMap& em) {
252 uint32_t best = kuint32max;
254 uint32_t prefix_cnt = 0;
258 for (
auto it = em.begin(); it != em.end(); ++it) {
259 int16_t e_base = it->first;
260 uint32_t current = it->second.Cost(0);
263 for (++next; next != em.end(); ++next) {
264 current += next->second.Cost(next->first - e_base);
266 current += prefix_cnt * 9;
267 if (current < best) {
269 aux_->header.exponent = e_base;
271 prefix_cnt += it->second.count();
276 uint32_t DoubleCompressor::WriteRawDoubles(
const double* src, uint32_t count, uint8_t* dest) {
278 uint16_t sz = count *
sizeof(double);
279 LittleEndian::Store16(dest + 1, sz);
280 memcpy(dest + 3, src, sz);
285 int32_t DoubleDecompressor::Decompress(
const uint8_t* src, uint32_t src_len,
double* dest) {
286 if (src_len < 3 || LittleEndian::Load16(src + 1) != src_len - 3)
291 uint8_t flags = *src;
294 if ((flags & kRawBit) != 0) {
295 CHECK_EQ(0, src_len %
sizeof(
double));
296 memcpy(dest, src, src_len);
297 return src_len /
sizeof(double);
299 CHECK_GT(src_len, DoubleCompressor::DECIMAL_HEADER_MAX_SIZE);
304 DoubleCompressor::DecimalHeader dh;
305 uint32 read = dh.Parse(flags, src);
308 CHECK_LE(dh.lz4_size, src_len);
309 constexpr
size_t kMaxSize = DoubleCompressor::BLOCK_MAX_BYTES;
312 src_len -= dh.lz4_size;
314 int res = LZ4_decompress_safe(reinterpret_cast<const char*>(src),
315 reinterpret_cast<char*>(aux_->z4buf), dh.lz4_size, kMaxSize);
317 CHECK_EQ(0, res % 8);
320 bitunshuffle2(aux_->z4buf, res, reinterpret_cast<uint8_t*>(dest));
321 unsigned count = res / 8;
323 unsigned exception_index = count;
324 unsigned exception_id = 0;
325 if (flags & kHasExceptionsBit) {
326 res = LZ4_decompress_safe(reinterpret_cast<const char*>(src),
327 reinterpret_cast<char*>(aux_->z4buf), src_len,
330 CHECK_EQ(0, res % 8);
331 unshuffle(
sizeof(
double), res, aux_->z4buf, reinterpret_cast<uint8*>(aux_->exceptions));
332 exception_index = dh.first_exception_index;
335 int64_t* i64 = reinterpret_cast<int64_t*>(dest);
336 for (
unsigned i = 0; i < count; ++i) {
337 if (i == exception_index) {
338 unsigned delta = i64[i];
339 dest[i] = aux_->exceptions[exception_id++];
340 exception_index += delta;
341 CHECK_LT(exception_index, count);
343 int64_t f = i64[i] + dh.min_val;
344 dest[i] = FromDecimal(f, dh.exponent);