8#ifndef HPP_AWORX_ALIB_BITBUFFER_AC_V1
9#define HPP_AWORX_ALIB_BITBUFFER_AC_V1
11#if !defined (HPP_AWORX_ALIB_BITBUFFER)
18#if !defined (HPP_ALIB_ENUMS_UNDERLYING_INTEGRAL)
21#if !defined(HPP_ALIB_ENUMS_BW_IT_CONVERSION)
24#if !defined(HPP_ALIB_ENUMS_SERIALIZATION)
28#if ALIB_TIME && !defined (HPP_ALIB_TIME_TICKS)
32#if !defined(ALIB_DEBUG_ARRAY_COMPRESSION)
33# define ALIB_DEBUG_ARRAY_COMPRESSION ALIB_DEBUG
34#elif !ALIB_DEBUG && ALIB_DEBUG_ARRAY_COMPRESSION
35# undef ALIB_DEBUG_ARRAY_COMPRESSION
36# define ALIB_DEBUG_ARRAY_COMPRESSION 0
37# pragma message "Symbol ALIB_DEBUG_ARRAY_COMPRESSION set (from outside!) while ALIB_DEBUG is not. The symbol got disabled."
40namespace alib {
namespace bitbuffer {
106 template <
typename TIntegral>
111 using TUI =
typename std::make_unsigned<TIntegral>::type;
126 #if !defined(ALIB_DOX) && ALIB_DEBUG_ARRAY_COMPRESSION
127 bool dbgIsCheckRead=
false;
141 reinterpret_cast<const char*
>(arrayStart) );
145 min= (std::numeric_limits<TUI>::max)();
146 max= (std::numeric_limits<TUI>::min)();
159 Array(
const TIntegral& firstValue,
const TIntegral& secondValue,
size_t length )
163 reinterpret_cast<const char*
>(&firstValue) );
164 distance= size_t(
reinterpret_cast<const char*
>(&secondValue)
165 -
reinterpret_cast<const char*
>(&firstValue)) ;
168 min= (std::numeric_limits<TUI>::max)();
169 max= (std::numeric_limits<TUI>::min)();
193 if constexpr ( std::is_unsigned<TIntegral>::value )
198 return val >= 0 ?
TUI( val << 1 )
199 :
TUI( ((-val - 1) << 1) | 1 );
214 #if ALIB_DEBUG_ARRAY_COMPRESSION
222 if constexpr ( std::is_unsigned<TIntegral>::value )
223 *(
reinterpret_cast<TIntegral*
>(
firstVal + idx *
distance))= TIntegral(value);
227 (value & 1) == 0 ? TIntegral( value >> 1)
228 : -( TIntegral( value >> 1) + 1 );
231 #if ALIB_DEBUG_ARRAY_COMPRESSION
234 "BITBUFFER/AC",
"Error reading back compressed array data" )
261 minInc= (std::numeric_limits<TUI>::max)();
262 minDec= (std::numeric_limits<TUI>::max)();
265 min= (std::min)(
min, prevVal );
266 max= (std::max)(
max, prevVal );
268 for(
size_t i= 1; i <
len; ++i)
271 min= (std::min)(
min, val );
272 max= (std::max)(
max, val );
431#if !defined(ALIB_DOX)
469 template <
typename TValue>
496 template <
typename TValue>
509#if ALIB_ENUMS && !defined(ALIB_DOX)
513 alib::bitbuffer::ac_v1::ArrayCompressor::Algorithm::END_OF_ENUM )
517#define HPP_ALIB_MONOMEM_DETAIL_ARRAY_COMPRESSION_ALLOW
519#undef HPP_ALIB_MONOMEM_DETAIL_ARRAY_COMPRESSION_ALLOW
523namespace alib {
namespace bitbuffer {
namespace ac_v1 {
525template <
typename TValue>
533 "BitBuffer is smaller than uncompressed data."
534 " No buffer overflow checks are performed during compression." )
536 "BitBuffer remaining size should be twice as large as uncompressed data."
537 " No buffer overflow checks are performed during compression." )
539 auto initialBufferState= bw.
GetIndex();
540 auto initialBufferFill = bw.
Usage();
541 int multipleAlgorithms= CountElements(algorithmsToTry) > 1;
542 ALIB_ASSERT_ERROR(UnderlyingIntegral(algorithmsToTry) != 0,
"BITBUFFER/AC",
"No algorithms to check given" )
545 auto bestAlgoNo= (std::numeric_limits<int>::max)();
547 auto leastBits = (std::numeric_limits<size_t>::max)();
549 bool isFirstAlgo =
true;
556 if ( !HasBits(algorithmsToTry, algo ) )
560 bw.
Reset(initialBufferState);
565 if( multipleAlgorithms )
566 bw.
Write<3>( algoNo );
571 switch( lastAlgo= algo )
579 default:
ALIB_ERROR(
"BITBUFFER/AC",
"Internal error: Unknown compression algorithm number read")
break;
582 auto bufferFill= bw.
Usage();
590 statistics->
sumCompressed[algoNo]+= (bufferFill - initialBufferFill)/8;
594 ALIB_ASSERT_ERROR( bufferFill > initialBufferFill,
"BITBUFFER/AC",
"Array compression: Nothing written")
595 if( leastBits > bufferFill - initialBufferFill )
597 leastBits= bufferFill - initialBufferFill;
603 #if ALIB_DEBUG_ARRAY_COMPRESSION
607 if( multipleAlgorithms )
611 "Wrong algorithm id was read back. This must never happen." )
614 data.dbgIsCheckRead=
true;
625 default:
ALIB_ERROR(
"Internal error: Unknown compression algorithm number read")
break;
629 data.dbgIsCheckRead=
false;
633 if( !multipleAlgorithms )
642 statistics->
qtyWins [bestAlgoNo]++;
650 if( multipleAlgorithms && (bestAlgo != lastAlgo) )
652 bw.
Reset( initialBufferState );
653 bw.
Write<3>( bestAlgoNo );
663 default:
ALIB_ERROR(
"BITBUFFER/AC",
"Internal error: Unknown compression algorithm number read")
break;
669 return std::make_pair( leastBits, bestAlgo );
672template <
typename TValue>
679 "No algorithms to check given" )
680 bool multipleAlgorithms= CountElements(algorithmsToTry) > 1;
685 auto algo= multipleAlgorithms ?
Algorithm( 1 << br.
Read<3>() )
696 default:
ALIB_ERROR(
"Internal error: Unknown compression algorithm number read")
break;
704 auto algoNo= ToSequentialEnumeration( algo );
uinteger RemainingSize() const
BitBufferBase & GetBuffer() const
BitBufferBase::Index GetIndex() const
void Write(TIntegral value)
typename std::make_unsigned< TIntegral >::type TUI
TUI minDec
Minimum decrease between two adjacent values.
TUI minInc
Minimum increase between two adjacent values.
Array(const TIntegral &firstValue, const TIntegral &secondValue, size_t length)
TUI maxInc
Maximum increase between two adjacent values.
TUI maxDec
Maximum decrease between two adjacent values.
ALIB_FORCE_INLINE size_t length() const
size_t distance
The distance in memory between two array values.
size_t len
The length of the array.
ALIB_FORCE_INLINE TUI get(size_t idx) const
char * firstVal
Pointer to the first array value.
Array(const TIntegral *arrayStart, size_t length)
TUI min
Maximum value (when zig-zag encoded)
TUI max
Maximum value (when zig-zag encoded)
ALIB_FORCE_INLINE void set(size_t idx, TUI value)
static std::pair< size_t, Algorithm > Compress(BitWriter &bitWriter, Array< TValue > &data, Algorithm algorithmsToTry=Algorithm::ALL, Statistics *statistics=nullptr)
static void Decompress(BitReader &bitReader, Array< TValue > &data, Algorithm algorithm=Algorithm::ALL, Statistics *statistics=nullptr)
static constexpr int QtyAlgorithms
The number of algorithms implemented.
#define ALIB_ASSERT_MODULE(modulename)
#define ALIB_ENUMS_MAKE_BITWISE(TEnum)
#define ALIB_WARNINGS_RESTORE
#define ALIB_FORCE_INLINE
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
#define ALIB_ENUMS_MAKE_ITERABLE(TEnum, StopElement)
#define ALIB_WARNINGS_IGNORE_DOCS
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ALIB_ASSERT_WARNING(cond,...)
void writeHuffman(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readSparse(BitReader &br, ArrayCompressor::Array< TI > &data)
void writeSparse(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readUncompressed(BitReader &br, ArrayCompressor::Array< TI > &data)
void readIncremental(BitReader &br, ArrayCompressor::Array< TI > &data)
void writeIncremental(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readVerySparse(BitReader &br, ArrayCompressor::Array< TI > &data)
void readMinMax(BitReader &br, ArrayCompressor::Array< TI > &data)
void writeUncompressed(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void writeMinMax(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void writeVerySparse(BitWriter &bw, ArrayCompressor::Array< TI > &data)
void readHuffman(BitReader &br, ArrayCompressor::Array< TI > &data)
size_t sumCompressedWon[QtyAlgorithms]
Ticks::Duration writeTimes[QtyAlgorithms]
Statistics & operator+=(const Statistics &other)
size_t sumUnCompressedWon[QtyAlgorithms]
int qtyWins[QtyAlgorithms]
int qtyReads[QtyAlgorithms]
Ticks::Duration readTimes[QtyAlgorithms]
size_t sumCompressed[QtyAlgorithms]
ALIB_API void Print(AString &result, const String &headline, bool printTotals)