ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
acalgos.inl.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-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace bitbuffer { namespace ac_v1 {
9
10/// Writes data compressed using class \alib{bitbuffer::ac_v1;HuffmanEncoder}.
11/// @tparam TI The integral type of the array to write.
12/// @param bw The bit writer to use.
13/// @param data The array to read the data from.
14template<typename TI>
16 using TUI= typename std::make_unsigned<TI>::type;
17 if( !data.length() )
18 return;
19
20 HuffmanEncoder he( bw );
21
22 // count all occurrences of bytes
23 for(size_t i= 0; i < data.length(); ++i) {
24 TUI val= data.get( i );
25 int bytes= sizeof(TUI);
26
27 // using a loop here (instead of "if constexpr..." because hd.read() is inlined
28 // (two times something similar below)
29 COUNTNEXT:
30 he.CountSymbol(uint8_t (val) );
31 if( --bytes ) {
33 val>>= 8;
35 goto COUNTNEXT;
36 } }
37 // build huffman code
38 he.Generate();
39
40 // write out
41 for(size_t i= 0; i < data.length(); ++i) {
42 TUI val= data.get( i );
43 ShiftOpRHS bits= bitsof(TUI) - 8;
44 while( bits >= 0 ) {
46 he.Write(uint8_t (val >> bits ) );
48
49 bits-= 8;
50} } }
51
52/// Reads data compressed using class \alib{bitbuffer::ac_v1;HuffmanDecoder}.
53/// @tparam TI The integral type of the array to read back.
54/// @param br The bit reader to use.
55/// @param data The array to read the data to.
56template<typename TI>
58 using TUI= typename std::make_unsigned<TI>::type;
59 if( !data.length() )
60 return;
61 HuffmanDecoder hd( br );
62 hd.ReadTree();
63 for(size_t i= 0; i < data.length(); ++i) {
64 TUI val= 0;
65 int bytes= sizeof(TUI);
66 READNEXT:
67 val|= hd.Read();
68 if( --bytes ) {
70 val<<= 8;
72 goto READNEXT;
73 }
74 data.set(i, val);
75} }
76
77
78/// Writes array data by simply using the mechanics provided with class \alib{bitbuffer;BitWriter},
79/// which tries to shorten integrals on writing.
80/// @tparam TI The integral type of the array to write.
81/// @param bw The bit writer to use.
82/// @param data The array to read the data from.
83template<typename TI>
85 for(size_t i= 0; i < data.length(); ++i) {
86 bw.Write( data.get( i ) );
87} }
88
89/// Reads data compressed using simply the mechanics provided with class \alib{bitbuffer;BitWriter}
90/// which tries to shorten integrals on writing.
91/// @tparam TI The integral type of the array to read back.
92/// @param br The bit reader to use.
93/// @param data The array to read the data to.
94template<typename TI>
96 using TUI= typename std::make_unsigned<TI>::type;
97 for(size_t i= 0; i < data.length(); ++i)
98 data.set(i, br.Read<TUI>() );
99}
100
101/// Writes array data by writing only the difference to the minimum found value.
102/// @tparam TI The integral type of the array to write.
103/// @param bw The bit writer to use.
104/// @param data The array to read the data from.
105template<typename TI>
107 using TUI= typename std::make_unsigned<TI>::type;
108
109 // calc min/max
110 data.calcMinMax();
111
112 // get bits needed
113 int bitCnt= lang::MSB0(TUI(data.max - data.min));
114
115 // write data
116 bw.Write<lang::Log2OfSize<TUI>() + 1>( bitCnt );
117 bw.Write( data.min );
118 if( !bitCnt )
119 return;
120
121 for(size_t i= 0; i < data.length(); ++i )
122 bw.Write( bitCnt, TUI( data.get(i) - data.min ) );
123}
124
125/// Reads data compressed with method \alib{bitbuffer::ac_v1;writeMinMax}.
126/// @tparam TI The integral type of the array to read back.
127/// @param br The bit reader to use.
128/// @param data The array to read the data to.
129template<typename TI>
131 using TUI= typename std::make_unsigned<TI>::type;
132 auto bitCnt= br.Read<lang::Log2OfSize<TUI>() + 1>();
133 TUI min = br.Read<TUI>();
134
135 if( !bitCnt ) {
136 for(size_t i= 0; i < data.length(); ++i)
137 data.set(i, min );
138 return;
139 }
140 for(size_t i= 0; i < data.length(); ++i)
141 data.set(i, br.Read<TUI>( bitCnt ) + min );
142}
143
144/// Writes array data assuming it is sparsely set.
145/// @tparam TI The integral type of the array to write.
146/// @param bw The bit writer to use.
147/// @param data The array to read the data from.
148template<typename TI>
150 if( !data.length() )
151 return;
152 using TUI= typename std::make_unsigned<TI>::type;
153 TUI first= data.get(0);
154 bw.Write(first);
155 for(size_t i= 1; i < data.length(); ++i) {
156 TUI second= data.get(i);
157 if( second==first)
158 bw.Write<1>( 1) ;
159 else {
160 bw.Write<1>( 0 );
161 bw.Write(second);
162 }
163 first= second;
164} }
165
166/// Reads data compressed with method \alib{bitbuffer::ac_v1;writeSparse}.
167/// @tparam TI The integral type of the array to read back.
168/// @param br The bit reader to use.
169/// @param data The array to read the data to.
170template<typename TI>
172 if( !data.length() )
173 return;
174 using TUI= typename std::make_unsigned<TI>::type;
175 auto prevVal= br.Read<TUI>();
176 data.set(0, prevVal);
177 for(size_t i= 1; i < data.length(); ++i)
178 data.set(i, prevVal= br.Read<1>() ? prevVal
179 : br.Read<TUI>() );
180}
181
182/// Writes array data assuming it is very sparsely set.
183/// @tparam TI The integral type of the array to write.
184/// @param bw The bit writer to use.
185/// @param data The array to read the data from.
186template<typename TI>
188 using TUI= typename std::make_unsigned<TI>::type;
189 if( !data.length() )
190 return;
191
192 // calc min/max
193 data.calcMinMax();
194
195 // loop twice:
196 // 1st pass: calc longest repetition
197 // 2nd pass: write data
198 auto maxSegLen = (std::numeric_limits<size_t>::min)();
199 auto bitCntVal = 0;
200 auto bitCntRep = 0;
201 for( int pass= 0 ; pass < 2 ; ++ pass ) {
202 size_t segStart= 0;
203 TUI val = data.get(0);
204 TUI prevVal;
205 do
206 {
207 // find next segment [segStart - segEnd[
208 bool sparse;
209 size_t segEnd= segStart + 1;
210 prevVal= val;
211
212 // only one value left?
213 if( segEnd == data.length() ) {
214 sparse= false; // could also be set to true
215 } else {
216 val= data.get(segEnd);
217
218 sparse= (prevVal == val);
219
220 // find end
221 while( ( (prevVal == val) == sparse )
222 && ++segEnd < data.length())
223 {
224 prevVal= val;
225 val = data.get(segEnd);
226 }
227 if( !sparse ) // in diff mode, we have to go one back!
228 segEnd--;
229 }
230
231 // Pass 0: just note maximum segment length
232 if( pass== 0)
233 maxSegLen= (std::max)( maxSegLen, segEnd - segStart );
234 // Pass 1: write segment
235 else {
236 // write
237 if( sparse )
238 { // write an extra 0 to indicate sparse mode
239 bw.Write( bitCntRep +1, (segEnd - segStart) << 1 );
240 bw.Write( bitCntVal , TUI(prevVal - data.min ) );
241 }
242 else
243 { // write an extra 1 to indicate non-sparse mode
244 bw.Write( bitCntRep +1, ((segEnd - segStart) << 1) | 1 );
245 for( size_t j= segStart; j < segEnd; ++j)
246 bw.Write( bitCntVal, TUI(data.get(j) - data.min ) );
247 } }
248
249 // next segment
250 segStart= segEnd;
251 }
252 while( segStart < data.length() );
253
254 // pass 0 done: calc and write bits needed for value and repetition
255 if( pass == 0) {
256 bitCntVal= lang::MSB0( TUI(data.max - data.min) );
257 bitCntRep= lang::MSB (maxSegLen);
258
260 bitCntRep
261 | bitCntVal << (lang::Log2OfSize<uint32_t>()+1) );
262 bw.Write( data.min );
263 }
264 } // 2 pass loop
265}
266
267/// Reads data compressed with method \alib{bitbuffer::ac_v1;writeVerySparse}.
268/// @tparam TI The integral type of the array to read back.
269/// @param br The bit reader to use.
270/// @param data The array to read the data to.
271template<typename TI>
273 using TUI= typename std::make_unsigned<TI>::type;
274 if( !data.length() ) return;
275
276 auto bitCntRep = br.Read<lang::Log2OfSize<uint32_t>()+1 + lang::Log2OfSize<TUI>()+1>();
277 auto bitCntVal = bitCntRep >> (lang::Log2OfSize<uint32_t>() + 1);
278 bitCntRep&= lang::LowerMask<lang::Log2OfSize<uint32_t>() + 1, int>();
279
280 TUI minVal = br.Read<TUI>();
281
282 size_t segStart= 0;
283 while( segStart < data.length() ) {
284 size_t cntRep= br.Read<size_t>( bitCntRep + 1 );
285 size_t segEnd= segStart + (cntRep >> 1);
286 if( (cntRep & 1) == 0 ) { // sparse
287 TUI val = br.Read<TUI>( bitCntVal ) + minVal;
288 for( size_t i= segStart ; i < segEnd ; ++i )
289 data.set(i, val);
290 }
291 else { // different values
292 for( size_t i= segStart ; i < segEnd ; ++i )
293 data.set(i, br.Read<TUI>( bitCntVal ) + minVal);
294 }
295 segStart= segEnd;
296} }
297
298/// Writes array data incrementally.
299/// @tparam TI The integral type of the array to write.
300/// @param bw The bit writer to use.
301/// @param data The array to read the data from.
302template<typename TI>
304 if( !data.length() )
305 return;
306
307 using TUI= typename std::make_unsigned<TI>::type;
308
309 if( data.length() == 1 ) {
310 bw.Write(data.get(0));
311 return;
312 }
313
314 // calc min diff bits needed to write diff
315 data.calcMinMax();
316 auto bitCntPos= lang::MSB0(TUI( data.maxInc - data.minInc));
317 auto bitCntNeg= lang::MSB0(TUI( data.maxDec - data.minDec));
318
319 // write data
320 bw.Write<2 * (lang::Log2OfSize<TUI>() + 1)>( bitCntPos
321 | bitCntNeg << (lang::Log2OfSize<TUI>() + 1) );
322
323 bw.Write( data.minInc );
324 bw.Write( data.minDec );
325 TUI first= data.get(0);
326 bw.Write(first);
327 for(size_t i= 1; i < data.length(); ++i) {
328 // send one bit indicating a positive (1) or negative (0) difference
329 // and then the difference as an unsigned value
330 TUI second= data.get(i);
331 if( second==first)
332 bw.Write( true );
333 else {
334 bw.Write( false );
335 bool posNeg= second >= first;
336 bw.Write( posNeg );
337 bw.Write(posNeg ? bitCntPos : bitCntNeg,
338 posNeg ? TUI( second - first - data.minInc )
339 : TUI( first - second - data.minDec ) );
340 }
341 first= second;
342} }
343
344/// Reads data compressed with \alib{bitbuffer::ac_v1;writeIncremental}.
345/// @tparam TI The integral type of the array to read back.
346/// @param br The bit reader to use.
347/// @param data The array to read the data to.
348template<typename TI>
350 if( !data.length() )
351 return;
352
353 using TUI= typename std::make_unsigned<TI>::type;
354 if( data.length() == 1 ) {
355 data.set(0, br.Read<TUI>() );
356 return;
357 }
358
359 auto bitCntPos = br.Read<2 * (lang::Log2OfSize<TUI>()+1)>();
360 auto bitCntNeg = bitCntPos >> (lang::Log2OfSize<TUI>()+1);
361 bitCntPos&= lang::LowerMask<(lang::Log2OfSize<TUI>()+1), int>();
362 auto minDiffPos= br.Read<TUI>();
363 auto minDiffNeg= br.Read<TUI>();
364 auto prevVal = br.Read<TUI>();
365 data.set(0, prevVal);
366 for(size_t i= 1; i < data.length(); ++i) {
367 TUI val;
368 if( br.Read<1>() )
369 val= prevVal;
370 else {
371 bool posNeg= br.Read<1>();
372 TUI diff = br.Read<TUI>( posNeg ? bitCntPos : bitCntNeg );
373 val = posNeg ? TUI( prevVal + minDiffPos + diff )
374 : TUI( prevVal - minDiffNeg - diff );
375 }
376 data.set(i, prevVal= val);
377} }
378
379
380
381}}} // namespace [alib::bitbuffer::ac_v1]
Reads bits from a BitBufferBase.
Writes bits into a BitBufferBase.
void Write(TIntegral value)
TUI maxDec
Maximum decrease between two adjacent values.
Definition ac.inl:84
TUI max
Maximum value (when zig-zag encoded)
Definition ac.inl:82
void set(size_t idx, TUI value)
Definition ac.inl:150
TUI maxInc
Maximum increase between two adjacent values.
Definition ac.inl:83
TUI min
Maximum value (when zig-zag encoded)
Definition ac.inl:81
TUI minInc
Minimum increase between two adjacent values.
Definition ac.inl:85
TUI minDec
Minimum decrease between two adjacent values.
Definition ac.inl:86
ALIB_DLL void Generate()
Generates the huffman encoding table and writes this information to the bit writer.
Definition huffman.cpp:110
#define bitsof(type)
Definition alib.inl:1435
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:719
#define ALIB_WARNINGS_ALLOW_SHIFT_COUNT_OVERFLOW
Definition alib.inl:657
#define ALIB_EXPORT
Definition alib.inl:497
void writeHuffman(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void writeVerySparse(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readHuffman(BitReader &br, ArrayCompressor::Array< TI > &data)
void readSparse(BitReader &br, ArrayCompressor::Array< TI > &data)
void writeUncompressed(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readMinMax(BitReader &br, ArrayCompressor::Array< TI > &data)
void writeIncremental(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readVerySparse(BitReader &br, ArrayCompressor::Array< TI > &data)
void readUncompressed(BitReader &br, ArrayCompressor::Array< TI > &data)
void readIncremental(BitReader &br, ArrayCompressor::Array< TI > &data)
void writeSparse(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void writeMinMax(BitWriter &bw, ArrayCompressor::Array< TI > &data)
constexpr int Log2OfSize()
Definition bits.inl:199
constexpr int MSB(TIntegral value)
Definition bits.inl:314
constexpr int MSB0(TIntegral value)
Definition bits.inl:332
constexpr TIntegral LowerMask()
Definition bits.inl:51
int ShiftOpRHS
Type alias in namespace alib.