8#ifndef HPP_ALIB_BITBUFFER_AC_V1
9#define HPP_ALIB_BITBUFFER_AC_V1
14#include "alib/bitbuffer/bitbuffer.hpp"
22namespace alib {
namespace bitbuffer {
82 template <
typename TIntegral>
87 using TUI =
typename std::make_unsigned<TIntegral>::type;
102 #if !DOXYGEN && ALIB_DEBUG_ARRAY_COMPRESSION
103 bool dbgIsCheckRead=
false;
115 reinterpret_cast<const char*
>(arrayStart) );
119 min= (std::numeric_limits<TUI>::max)();
120 max= (std::numeric_limits<TUI>::min)();
131 Array(
const TIntegral& firstValue,
const TIntegral& secondValue,
size_t length )
135 reinterpret_cast<const char*
>(&firstValue) );
136 distance= size_t(
reinterpret_cast<const char*
>(&secondValue)
137 -
reinterpret_cast<const char*
>(&firstValue)) ;
140 min= (std::numeric_limits<TUI>::max)();
141 max= (std::numeric_limits<TUI>::min)();
161 if constexpr ( std::is_unsigned<TIntegral>::value )
166 return val >= 0 ?
TUI( val << 1 )
167 :
TUI( ((-val - 1) << 1) | 1 );
180 #if ALIB_DEBUG_ARRAY_COMPRESSION
188 if constexpr ( std::is_unsigned<TIntegral>::value )
189 *(
reinterpret_cast<TIntegral*
>(
firstVal + idx *
distance))= TIntegral(value);
193 (value & 1) == 0 ? TIntegral( value >> 1)
194 : -( TIntegral( value >> 1) + 1 );
197 #if ALIB_DEBUG_ARRAY_COMPRESSION
200 "BITBUFFER/AC",
"Error reading back compressed array data" )
225 minInc= (std::numeric_limits<TUI>::max)();
226 minDec= (std::numeric_limits<TUI>::max)();
229 min= (std::min)(
min, prevVal );
230 max= (std::max)(
max, prevVal );
232 for(
size_t i= 1; i <
len; ++i)
235 min= (std::min)(
min, val );
236 max= (std::max)(
max, val );
422 template <
typename TValue>
447 template <
typename TValue>
463 alib::bitbuffer::ac_v1::ArrayCompressor::Algorithm::END_OF_ENUM )
465#define HPP_ALIB_MONOMEM_DETAIL_ARRAY_COMPRESSION_ALLOW
468#undef HPP_ALIB_MONOMEM_DETAIL_ARRAY_COMPRESSION_ALLOW
472namespace alib {
namespace bitbuffer {
namespace ac_v1 {
475template <
typename TValue>
479 Algorithm algorithmsToTry,
480 Statistics* statistics )
483 "BitBuffer is smaller than uncompressed data."
484 " No buffer overflow checks are performed during compression." )
486 "
BitBuffer remaining size should be twice as large as uncompressed data."
487 " No buffer overflow checks are performed during compression." )
489 auto initialBufferState= bw.GetIndex();
490 auto initialBufferFill = bw.Usage();
491 int multipleAlgorithms= CountElements(algorithmsToTry) > 1;
492 ALIB_ASSERT_ERROR(UnderlyingIntegral(algorithmsToTry) != 0, "BITBUFFER/AC", "No algorithms to check given" )
495 auto bestAlgoNo= (std::numeric_limits<
int>::max)();
497 auto leastBits = (std::numeric_limits<
size_t>::max)();
499 bool isFirstAlgo = true;
506 if ( !HasBits(algorithmsToTry, algo ) )
510 bw.Reset(initialBufferState);
515 if( multipleAlgorithms )
516 bw.Write<3>( algoNo );
521 switch( lastAlgo= algo )
523 case Algorithm::Uncompressed: writeUncompressed(bw, data); break;
524 case Algorithm::MinMax: writeMinMax (bw, data); break;
525 case Algorithm::Sparse: writeSparse (bw, data); break;
526 case Algorithm::VerySparse: writeVerySparse (bw, data); break;
527 case Algorithm::Incremental: writeIncremental (bw, data); break;
528 case Algorithm::Huffman: writeHuffman (bw, data); break;
529 default: ALIB_ERROR(
"BITBUFFER/AC",
"Internal error: Unknown compression algorithm number read") break;
532 auto bufferFill= bw.Usage();
536 ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
538 statistics->writeTimes [algoNo]+= tm.Age();
540 statistics->sumCompressed[algoNo]+= (bufferFill - initialBufferFill)/8;
541 ALIB_WARNINGS_RESTORE
544 ALIB_ASSERT_ERROR( bufferFill > initialBufferFill,
"BITBUFFER/AC",
"Array compression: Nothing written")
545 if( leastBits > bufferFill - initialBufferFill )
547 leastBits= bufferFill - initialBufferFill;
553 #if ALIB_DEBUG_ARRAY_COMPRESSION
556 BitReader br(bw.GetBuffer(), initialBufferState);
557 if( multipleAlgorithms )
559 auto readBackAlgo=
Algorithm( 1 << br.Read<3>() );
561 "Wrong algorithm id was read back. This must never happen." )
564 data.dbgIsCheckRead=
true;
575 default:
ALIB_ERROR(
"Internal error: Unknown compression algorithm number read") break;
579 data.dbgIsCheckRead= false;
583 if( !multipleAlgorithms )
590 statistics->ctdCompressions++;
591 statistics->sumUncompressed+= data.length() *
sizeof(TValue);
592 statistics->ctdWins [bestAlgoNo]++;
593 statistics->sumCompressedWon [bestAlgoNo]+= leastBits/8;
594 statistics->sumUnCompressedWon[bestAlgoNo]+= data.length() *
sizeof(TValue);
600 if( multipleAlgorithms && (bestAlgo != lastAlgo) )
602 bw.Reset( initialBufferState );
603 bw.Write<3>( bestAlgoNo );
613 default:
ALIB_ERROR(
"BITBUFFER/AC",
"Internal error: Unknown compression algorithm number read") break;
619 return std::make_pair( leastBits, bestAlgo );
622template <typename TValue>
626 Statistics* statistics )
629 "No algorithms to check given" )
630 bool multipleAlgorithms= CountElements(algorithmsToTry) > 1;
635 auto algo= multipleAlgorithms ?
Algorithm( 1 << br.Read<3>() )
646 default:
ALIB_ERROR(
"Internal error: Unknown compression algorithm number read") break;
654 auto algoNo= ToSequentialEnumeration( algo );
655 statistics->readTimes[algoNo]+= tm.Age();
656 statistics->ctdReads [algoNo]++;
Reads bits from a BitBufferBase.
Writes bits into a BitBufferBase.
typename std::make_unsigned< TIntegral >::type TUI
The unsigned version of template type TIntegral.
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)
ArrayCompressor()=delete
Deleted default constructor (this class cannot be created)
static constexpr int NumberOfAlgorithms
The number of algorithms implemented.
@ Huffman
Huffman encoding (byte based).
@ Incremental
Only distances of the values are written.
@ ALL
All compression methods selected.
@ Sparse
Writes '1' if next value is equal to previous, '0' plus next value otherwise.
@ MinMax
Stores the differences between the minimum and maximum value found.
@ VerySparse
Writes the number of following equal or non equal values.
@ NONE
No compression method selected.
static void Decompress(BitReader &bitReader, Array< TValue > &data, Algorithm algorithm=Algorithm::ALL, Statistics *statistics=nullptr)
#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)
constexpr std::underlying_type< TEnum >::type UnderlyingIntegral(TEnum element) noexcept
bitbuffer::BitWriter BitWriter
Type alias in namespace alib.
time::Ticks Ticks
Type alias in namespace alib.
bitbuffer::BitReader BitReader
Type alias in namespace alib.
enums::EnumIterator< TEnum, TEnableIf > EnumIterator
Type alias in namespace alib.
bitbuffer::BitBuffer BitBuffer
Type alias in namespace alib.
int ctdReads[NumberOfAlgorithms]
The number of measured decompression runs of each algorithm.
Ticks::Duration writeTimes[NumberOfAlgorithms]
The overall compression time of each algorithm.
size_t sumCompressed[NumberOfAlgorithms]
For each algorithm, the sum of resulting bytes of all compressions performed.
size_t sumUncompressed
The overall given array data to compress.
Statistics & operator+=(const Statistics &other)
ALIB_API void Print(AString &result, const String &headline, bool printTotals)
Ticks::Duration readTimes[NumberOfAlgorithms]
The overall decompression time of each algorithm.
size_t sumCompressedWon[NumberOfAlgorithms]
int ctdWins[NumberOfAlgorithms]
size_t sumUnCompressedWon[NumberOfAlgorithms]
int ctdCompressions
The number of executed compressions.