ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
acalgos.inl
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_bitbuffer of the \aliblong.
4 *
5 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_BITBUFFER_AC_V1_ALGOS
9#define HPP_ALIB_BITBUFFER_AC_V1_ALGOS 1
10
11#if !defined(HPP_ALIB_MONOMEM_DETAIL_ARRAY_COMPRESSION_ALLOW)
12# error "ALib sources with ending '.inl' must not be included from outside."
13#endif
14
15#if !defined(HPP_ALIB_BITBUFFER_AC_V1_HUFFMAN)
17#endif
18
19namespace alib { namespace bitbuffer { namespace ac_v1 {
20
21
22/**
23 * Writes data compressed using class \alib{bitbuffer::ac_v1;HuffmanEncoder}.
24 * @tparam TI The integral type of the array to write.
25 * @param bw The bit writer to use.
26 * @param data The array to read the data from.
27 */
28template<typename TI>
30{
31 using TUI= typename std::make_unsigned<TI>::type;
32 if( !data.length() )
33 return;
34
35 HuffmanEncoder he( bw );
36
37 // count all occurrences of bytes
38 for(size_t i= 0; i < data.length(); ++i)
39 {
40 TUI val= data.get( i );
41 int bytes= sizeof(TUI);
42
43 // using a loop here (instead of "if constexpr..." because hd.read() is inlined
44 // (two times something similar below)
45 COUNTNEXT:
46 he.CountSymbol(uint8_t (val) );
47 if( --bytes )
48 {
50 val>>= 8;
52 goto COUNTNEXT;
53 }
54 }
55 // build huffman code
56 he.Generate();
57
58 // write out
59 for(size_t i= 0; i < data.length(); ++i)
60 {
61 TUI val= data.get( i );
62 ShiftOpRHS bits= bitsof(TUI) - 8;
63 while( bits >= 0 )
64 {
66 he.Write(uint8_t (val >> bits ) );
68
69 bits-= 8;
70 }
71 }
72}
73
74/**
75 * Reads data compressed using class \alib{bitbuffer::ac_v1;HuffmanDecoder}.
76 * @tparam TI The integral type of the array to read back.
77 * @param br The bit reader to use.
78 * @param data The array to read the data to.
79 */
80template<typename TI>
82{
83 using TUI= typename std::make_unsigned<TI>::type;
84 if( !data.length() )
85 return;
86 HuffmanDecoder hd( br );
87 hd.ReadTree();
88 for(size_t i= 0; i < data.length(); ++i)
89 {
90 TUI val= 0;
91 int bytes= sizeof(TUI);
92 READNEXT:
93 val|= hd.Read();
94 if( --bytes )
95 {
97 val<<= 8;
99 goto READNEXT;
100 }
101 data.set(i, val);
102 }
103}
104
105
106/**
107 * Writes array data by simply using the mechanics provided with class \alib{bitbuffer;BitWriter},
108 * which tries to shorten integrals on writing.
109 * @tparam TI The integral type of the array to write.
110 * @param bw The bit writer to use.
111 * @param data The array to read the data from.
112 */
113template<typename TI>
115{
116 for(size_t i= 0; i < data.length(); ++i)
117 {
118 bw.Write( data.get( i ) );
119 }
120}
121
122/**
123 * Reads data compressed using simply the mechanics provided with class \alib{bitbuffer;BitWriter}
124 * which tries to shorten integrals on writing.
125 * @tparam TI The integral type of the array to read back.
126 * @param br The bit reader to use.
127 * @param data The array to read the data to.
128 */
129template<typename TI>
131{
132 using TUI= typename std::make_unsigned<TI>::type;
133 for(size_t i= 0; i < data.length(); ++i)
134 data.set(i, br.Read<TUI>() );
135}
136
137/**
138 * Writes array data by writing only the difference to the minimum found value.
139 * @tparam TI The integral type of the array to write.
140 * @param bw The bit writer to use.
141 * @param data The array to read the data from.
142 */
143template<typename TI>
145{
146 using TUI= typename std::make_unsigned<TI>::type;
147
148 // calc min/max
149 data.calcMinMax();
150
151 // get bits needed
152 int bitCnt= lang::MSB0(TUI(data.max - data.min));
153
154 // write data
155 bw.Write<lang::Log2OfSize<TUI>() + 1>( bitCnt );
156 bw.Write( data.min );
157 if( !bitCnt )
158 return;
159
160 for(size_t i= 0; i < data.length(); ++i )
161 bw.Write( bitCnt, TUI( data.get(i) - data.min ) );
162}
163
164/**
165 * Reads data compressed with method \alib{bitbuffer::ac_v1;writeMinMax}.
166 * @tparam TI The integral type of the array to read back.
167 * @param br The bit reader to use.
168 * @param data The array to read the data to.
169 */
170template<typename TI>
172{
173 using TUI= typename std::make_unsigned<TI>::type;
174 auto bitCnt= br.Read<lang::Log2OfSize<TUI>() + 1>();
175 TUI min = br.Read<TUI>();
176
177 if( !bitCnt )
178 {
179 for(size_t i= 0; i < data.length(); ++i)
180 data.set(i, min );
181 return;
182 }
183 for(size_t i= 0; i < data.length(); ++i)
184 data.set(i, br.Read<TUI>( bitCnt ) + min );
185}
186
187/**
188 * Writes array data assuming it is sparsely set.
189 * @tparam TI The integral type of the array to write.
190 * @param bw The bit writer to use.
191 * @param data The array to read the data from.
192 */
193template<typename TI>
195{
196 if( !data.length() )
197 return;
198 using TUI= typename std::make_unsigned<TI>::type;
199 TUI first= data.get(0);
200 bw.Write(first);
201 for(size_t i= 1; i < data.length(); ++i)
202 {
203 TUI second= data.get(i);
204 if( second==first)
205 bw.Write<1>( 1) ;
206 else
207 {
208 bw.Write<1>( 0 );
209 bw.Write(second);
210 }
211 first= second;
212 }
213}
214
215/**
216 * Reads data compressed with method \alib{bitbuffer::ac_v1;writeSparse}.
217 * @tparam TI The integral type of the array to read back.
218 * @param br The bit reader to use.
219 * @param data The array to read the data to.
220 */
221template<typename TI>
223{
224 if( !data.length() )
225 return;
226 using TUI= typename std::make_unsigned<TI>::type;
227 auto prevVal= br.Read<TUI>();
228 data.set(0, prevVal);
229 for(size_t i= 1; i < data.length(); ++i)
230 data.set(i, prevVal= br.Read<1>() ? prevVal
231 : br.Read<TUI>() );
232}
233
234/**
235 * Writes array data assuming it is very sparsely set.
236 * @tparam TI The integral type of the array to write.
237 * @param bw The bit writer to use.
238 * @param data The array to read the data from.
239 */
240template<typename TI>
242{
243 using TUI= typename std::make_unsigned<TI>::type;
244 if( !data.length() )
245 return;
246
247 // calc min/max
248 data.calcMinMax();
249
250 // loop twice:
251 // 1st pass: calc longest repetition
252 // 2nd pass: write data
253 auto maxSegLen = (std::numeric_limits<size_t>::min)();
254 auto bitCntVal = 0;
255 auto bitCntRep = 0;
256 for( int pass= 0 ; pass < 2 ; ++ pass )
257 {
258 size_t segStart= 0;
259 TUI val = data.get(0);
260 TUI prevVal;
261 do
262 {
263 // find next segment [segStart - segEnd[
264 bool sparse;
265 size_t segEnd= segStart + 1;
266 prevVal= val;
267
268 // only one value left?
269 if( segEnd == data.length() )
270 {
271 sparse= false; // could also be set to true
272 }
273 else
274 {
275 val= data.get(segEnd);
276
277 sparse= (prevVal == val);
278
279 // find end
280 while( ( (prevVal == val) == sparse )
281 && ++segEnd < data.length())
282 {
283 prevVal= val;
284 val = data.get(segEnd);
285 }
286 if( !sparse ) // in diff mode, we have to go one back!
287 segEnd--;
288 }
289
290 // Pass 0: just note maximum segment length
291 if( pass== 0)
292 maxSegLen= (std::max)( maxSegLen, segEnd - segStart );
293 // Pass 1: write segment
294 else
295 {
296 // write
297 if( sparse )
298 { // write an extra 0 to indicate sparse mode
299 bw.Write( bitCntRep +1, (segEnd - segStart) << 1 );
300 bw.Write( bitCntVal , TUI(prevVal - data.min ) );
301 }
302 else
303 { // write an extra 1 to indicate non-sparse mode
304 bw.Write( bitCntRep +1, ((segEnd - segStart) << 1) | 1 );
305 for( size_t j= segStart; j < segEnd; ++j)
306 bw.Write( bitCntVal, TUI(data.get(j) - data.min ) );
307 }
308 }
309
310 // next segment
311 segStart= segEnd;
312 }
313 while( segStart < data.length() );
314
315 // pass 0 done: calc and write bits needed for value and repetition
316 if( pass == 0)
317 {
318 bitCntVal= lang::MSB0( TUI(data.max - data.min) );
319 bitCntRep= lang::MSB (maxSegLen);
320
321 bw.Write<lang::Log2OfSize<uint32_t>()+1 + lang::Log2OfSize<TUI>()+1>(
322 bitCntRep
323 | bitCntVal << (lang::Log2OfSize<uint32_t>()+1) );
324 bw.Write( data.min );
325 }
326 } // 2 pass loop
327}
328
329/**
330 * Reads data compressed with method \alib{bitbuffer::ac_v1;writeVerySparse}.
331 * @tparam TI The integral type of the array to read back.
332 * @param br The bit reader to use.
333 * @param data The array to read the data to.
334 */
335template<typename TI>
337{
338 using TUI= typename std::make_unsigned<TI>::type;
339 if( !data.length() ) return;
340
341 auto bitCntRep = br.Read<lang::Log2OfSize<uint32_t>()+1 + lang::Log2OfSize<TUI>()+1>();
342 auto bitCntVal = bitCntRep >> (lang::Log2OfSize<uint32_t>() + 1);
343 bitCntRep&= lang::LowerMask<lang::Log2OfSize<uint32_t>() + 1, int>();
344
345 TUI minVal = br.Read<TUI>();
346
347 size_t segStart= 0;
348 while( segStart < data.length() )
349 {
350 size_t cntRep= br.Read<size_t>( bitCntRep + 1 );
351 size_t segEnd= segStart + (cntRep >> 1);
352 if( (cntRep & 1) == 0 ) // sparse
353 {
354 TUI val = br.Read<TUI>( bitCntVal ) + minVal;
355 for( size_t i= segStart ; i < segEnd ; ++i )
356 data.set(i, val);
357 }
358 else // different values
359 {
360 for( size_t i= segStart ; i < segEnd ; ++i )
361 data.set(i, br.Read<TUI>( bitCntVal ) + minVal);
362 }
363 segStart= segEnd;
364 }
365}
366
367/**
368 * Writes array data incrementally.
369 * @tparam TI The integral type of the array to write.
370 * @param bw The bit writer to use.
371 * @param data The array to read the data from.
372 */
373template<typename TI>
375{
376 if( !data.length() )
377 return;
378
379 using TUI= typename std::make_unsigned<TI>::type;
380
381 if( data.length() == 1 )
382 {
383 bw.Write(data.get(0));
384 return;
385 }
386
387 // calc min diff bits needed to write diff
388 data.calcMinMax();
389 auto bitCntPos= lang::MSB0(TUI( data.maxInc - data.minInc));
390 auto bitCntNeg= lang::MSB0(TUI( data.maxDec - data.minDec));
391
392 // write data
393 bw.Write<2 * (lang::Log2OfSize<TUI>() + 1)>( bitCntPos
394 | bitCntNeg << (lang::Log2OfSize<TUI>() + 1) );
395
396 bw.Write( data.minInc );
397 bw.Write( data.minDec );
398 TUI first= data.get(0);
399 bw.Write(first);
400 for(size_t i= 1; i < data.length(); ++i)
401 {
402 // send one bit indicating a positive (1) or negative (0) difference
403 // and then the difference as an unsigned value
404 TUI second= data.get(i);
405 if( second==first)
406 bw.Write( true );
407 else
408 {
409 bw.Write( false );
410 bool posNeg= second >= first;
411 bw.Write( posNeg );
412 bw.Write(posNeg ? bitCntPos : bitCntNeg,
413 posNeg ? TUI( second - first - data.minInc )
414 : TUI( first - second - data.minDec ) );
415 }
416 first= second;
417 }
418}
419
420/**
421 * Reads data compressed with \alib{bitbuffer::ac_v1;writeIncremental}.
422 * @tparam TI The integral type of the array to read back.
423 * @param br The bit reader to use.
424 * @param data The array to read the data to.
425 */
426template<typename TI>
428{
429 if( !data.length() )
430 return;
431
432 using TUI= typename std::make_unsigned<TI>::type;
433 if( data.length() == 1 )
434 {
435 data.set(0, br.Read<TUI>() );
436 return;
437 }
438
439 auto bitCntPos = br.Read<2 * (lang::Log2OfSize<TUI>()+1)>();
440 auto bitCntNeg = bitCntPos >> (lang::Log2OfSize<TUI>()+1);
441 bitCntPos&= lang::LowerMask<(lang::Log2OfSize<TUI>()+1), int>();
442 auto minDiffPos= br.Read<TUI>();
443 auto minDiffNeg= br.Read<TUI>();
444 auto prevVal = br.Read<TUI>();
445 data.set(0, prevVal);
446 for(size_t i= 1; i < data.length(); ++i)
447 {
448 TUI val;
449 if( br.Read<1>() )
450 val= prevVal;
451 else
452 {
453 bool posNeg= br.Read<1>();
454 TUI diff = br.Read<TUI>( posNeg ? bitCntPos : bitCntNeg );
455 val = posNeg ? TUI( prevVal + minDiffPos + diff )
456 : TUI( prevVal - minDiffNeg - diff );
457 }
458 data.set(i, prevVal= val);
459 }
460}
461
462
463
464}}} // namespace [alib::bitbuffer::ac_v1]
465
466#endif // HPP_ALIB_BITBUFFER_AC_V1_ALGOS
void Write(TIntegral value)
TUI minDec
Minimum decrease between two adjacent values.
Definition ac.hpp:124
TUI minInc
Minimum increase between two adjacent values.
Definition ac.hpp:123
TUI maxInc
Maximum increase between two adjacent values.
Definition ac.hpp:121
TUI maxDec
Maximum decrease between two adjacent values.
Definition ac.hpp:122
ALIB_FORCE_INLINE size_t length() const
Definition ac.hpp:177
ALIB_FORCE_INLINE TUI get(size_t idx) const
Definition ac.hpp:188
TUI min
Maximum value (when zig-zag encoded)
Definition ac.hpp:119
TUI max
Maximum value (when zig-zag encoded)
Definition ac.hpp:120
ALIB_FORCE_INLINE void set(size_t idx, TUI value)
Definition ac.hpp:211
ALIB_FORCE_INLINE void CountSymbol(uint8_t symbol)
Definition huffman.hpp:83
#define bitsof(type)
Definition bits.hpp:52
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_WARNINGS_ALLOW_SHIFT_COUNT_OVERFLOW
Definition alib.hpp:679
void writeHuffman(BitWriter &bw, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:29
void readSparse(BitReader &br, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:222
void writeSparse(BitWriter &bw, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:194
void readUncompressed(BitReader &br, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:130
void readIncremental(BitReader &br, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:427
void writeIncremental(BitWriter &bw, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:374
void readVerySparse(BitReader &br, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:336
void readMinMax(BitReader &br, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:171
void writeUncompressed(BitWriter &bw, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:114
void writeMinMax(BitWriter &bw, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:144
void writeVerySparse(BitWriter &bw, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:241
void readHuffman(BitReader &br, ArrayCompressor::Array< TI > &data)
Definition acalgos.inl:81
constexpr int MSB0(TIntegral value)
constexpr int MSB(TIntegral value)
Definition alib.cpp:57
int ShiftOpRHS
Type alias in namespace alib.