Project
Loading...
Searching...
No Matches
ExternalEntropyCoder.h
Go to the documentation of this file.
1// Copyright 2019-2023 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#ifndef ALICEO2_EXTERNALENTROPYCODER_H_
17#define ALICEO2_EXTERNALENTROPYCODER_H_
18
19#include <type_traits>
20
22
23#include "rANS/encode.h"
24#include "rANS/factory.h"
25#include "rANS/histogram.h"
26#include "rANS/metrics.h"
27#include "rANS/serialize.h"
28
30{
31
32template <typename source_T>
34{
35 public:
38
39 ExternalEntropyCoder(const encoder_type& encoder);
40
41 [[nodiscard]] inline const encoder_type& getEncoder() const noexcept { return *mEncoder; };
42
43 template <typename dst_T = uint8_t>
44 [[nodiscard]] inline size_t computePayloadSizeEstimate(size_t nElements, double_t safetyFactor = 1);
45
46 template <typename src_IT, typename dst_IT>
47 [[nodiscard]] dst_IT encode(src_IT srcBegin, src_IT srcEnd, dst_IT dstBegin, dst_IT dstEnd);
48
49 [[nodiscard]] inline size_t getNIncompressibleSamples() const noexcept { return mIncompressibleBuffer.size(); };
50
51 [[nodiscard]] inline source_type getIncompressibleSymbolOffset() const noexcept { return mIncompressiblePacker.getOffset(); };
52
53 [[nodiscard]] inline size_t getIncompressibleSymbolPackingBits() const noexcept { return mIncompressiblePacker.getPackingWidth(); };
54
55 template <typename dst_T = uint8_t>
56 [[nodiscard]] size_t computePackedIncompressibleSize() const noexcept;
57
58 template <typename dst_T>
59 [[nodiscard]] dst_T* writeIncompressible(dst_T* dstBegin, dst_T* dstEnd) const;
60
61 private:
62 const encoder_type* mEncoder{};
63 std::vector<source_type> mIncompressibleBuffer{};
64 Packer<source_type> mIncompressiblePacker{};
65};
66
67template <typename source_T>
69{
70 if (!getEncoder().getSymbolTable().hasEscapeSymbol()) {
71 throw std::runtime_error("External entropy encoder must be able to handle incompressible symbols.");
72 }
73};
74
75template <typename source_T>
76template <typename dst_T>
77[[nodiscard]] inline size_t ExternalEntropyCoder<source_T>::computePayloadSizeEstimate(size_t nElements, double_t safetyFactor)
78{
79 constexpr size_t Overhead = 10 * rans::utils::pow2(10); // 10KB overhead safety margin
80 const double_t RelativeSafetyFactor = 2.0 * safetyFactor;
81 const size_t messageSizeB = nElements * sizeof(source_type);
82 return rans::utils::nBytesTo<dst_T>(std::ceil(RelativeSafetyFactor * messageSizeB) + Overhead);
83}
84
85template <typename source_T>
86template <typename src_IT, typename dst_IT>
87[[nodiscard]] dst_IT ExternalEntropyCoder<source_T>::encode(src_IT srcBegin, src_IT srcEnd, dst_IT dstBegin, dst_IT dstEnd)
88{
89 const size_t incompressibleSymbolFrequency = [&]() {
90 const auto& symbolTable = mEncoder->getSymbolTable();
91 const double_t incompressibleSymbolProbability = static_cast<double_t>(symbolTable.getEscapeSymbol().getFrequency()) / rans::utils::pow2(symbolTable.getPrecision());
92 return std::ceil(std::distance(srcBegin, srcEnd) * incompressibleSymbolProbability);
93 }();
94
95 mIncompressibleBuffer.reserve(incompressibleSymbolFrequency);
96 auto [encodedMessageEnd, literalsEnd] = mEncoder->process(srcBegin, srcEnd, dstBegin, std::back_inserter(mIncompressibleBuffer));
97 rans::utils::checkBounds(encodedMessageEnd, dstEnd);
98 mIncompressiblePacker = Packer<source_type>{mIncompressibleBuffer.data(), mIncompressibleBuffer.data() + mIncompressibleBuffer.size()};
99
100 return encodedMessageEnd;
101};
102
103template <typename source_T>
104template <typename dst_T>
105[[nodiscard]] inline size_t ExternalEntropyCoder<source_T>::computePackedIncompressibleSize() const noexcept
106{
107 return mIncompressiblePacker.template getPackingBufferSize<dst_T>(mIncompressibleBuffer.size());
108};
109
110template <typename source_T>
111template <typename dst_T>
112[[nodiscard]] inline dst_T* ExternalEntropyCoder<source_T>::writeIncompressible(dst_T* dstBegin, dst_T* dstEnd) const
113{
114 return mIncompressiblePacker.pack(mIncompressibleBuffer.data(), mIncompressibleBuffer.size(), dstBegin, dstEnd);
115};
116
117} // namespace o2::ctf::internal
118
119#endif /* ALICEO2_EXTERNALENTROPYCODER_H_ */
Interfaces for BitPacking using librans.
uint32_t source_type
size_t getIncompressibleSymbolPackingBits() const noexcept
size_t computePayloadSizeEstimate(size_t nElements, double_t safetyFactor=1)
ExternalEntropyCoder(const encoder_type &encoder)
source_type getIncompressibleSymbolOffset() const noexcept
const encoder_type & getEncoder() const noexcept
size_t computePackedIncompressibleSize() const noexcept
typename rans::denseEncoder_type< source_type > encoder_type
dst_T * writeIncompressible(dst_T *dstBegin, dst_T *dstEnd) const
dst_IT encode(src_IT srcBegin, src_IT srcEnd, dst_IT dstBegin, dst_IT dstEnd)
source_type getOffset() const noexcept
Definition Packer.h:42
size_t getPackingWidth() const noexcept
Definition Packer.h:44
public interface for encoding.
static factory classes for building histograms, encoders and decoders.
public interface for building and renorming histograms from source data.
constexpr size_t pow2(size_t n) noexcept
Definition utils.h:165
void checkBounds(IT iteratorPosition, IT upperBound)
Definition utils.h:244
decltype(makeDenseEncoder<>::fromRenormed(RenormedDenseHistogram< source_T >{})) denseEncoder_type
Definition factory.h:229
public interface for serializing histograms (dictionaries) to JSON or compressed binary.