Project
Loading...
Searching...
No Matches
Symbol.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
16
17#ifndef RANS_INTERNAL_CONTAINERS_SYMBOL_H_
18#define RANS_INTERNAL_CONTAINERS_SYMBOL_H_
19
20#include <cassert>
21#include <cstdint>
22#include <cstring>
23
24#include <fairlogger/Logger.h>
25
27
28namespace o2::rans::internal
29{
30
31class Symbol
32{
33 public:
35 using size_type = size_t;
36 using difference_type = std::ptrdiff_t;
37
38 // TODO(milettri): fix once ROOT cling respects the standard http://wg21.link/p1286r2
39 constexpr Symbol() noexcept {}; // NOLINT
40 constexpr Symbol(value_type frequency, value_type cumulative, [[maybe_unused]] size_t symbolTablePrecision = 0)
41 : mSymbol{frequency, cumulative} {};
42 [[nodiscard]] inline constexpr value_type getFrequency() const noexcept { return mSymbol[0]; };
43 [[nodiscard]] inline constexpr value_type getCumulative() const noexcept { return mSymbol[1]; };
44 [[nodiscard]] inline constexpr const value_type* data() const noexcept { return mSymbol.data(); };
45
46 [[nodiscard]] inline bool operator==(const Symbol& other) const { return this->getCumulative() == other.getCumulative(); };
47 [[nodiscard]] inline bool operator!=(const Symbol& other) const { return !operator==(other); };
48
49 friend std::ostream& operator<<(std::ostream& os, const Symbol& symbol)
50 {
51 os << fmt::format("Symbol:{{Frequency: {}, Cumulative: {}}}", symbol.getFrequency(), symbol.getCumulative());
52 return os;
53 }
54
55 protected:
56 std::array<value_type, 2> mSymbol{0, 0};
57};
58
59template <typename source_T>
61{
62 public:
65 using size_type = size_t;
66 using difference_type = std::ptrdiff_t;
67
68 // TODO(milettri): fix once ROOT cling respects the standard http://wg21.link/p1286r2
69 constexpr DecoderSymbol() noexcept {}; // NOLINT
70 constexpr DecoderSymbol(source_type sourceSymbol, Symbol decoderSymbol) : mSourceSymbol{sourceSymbol}, mDecoderSymbol{decoderSymbol} {};
71 constexpr DecoderSymbol(source_type symbol, typename value_type::value_type frequency, typename value_type::value_type cumulative)
72 : mSourceSymbol{symbol}, mDecoderSymbol{frequency, cumulative} {};
73 [[nodiscard]] inline constexpr source_type getSourceSymbol() const noexcept { return mSourceSymbol; };
74 [[nodiscard]] inline constexpr const value_type& getDecoderSymbol() const noexcept { return mDecoderSymbol; };
75 [[nodiscard]] inline constexpr const value_type* getDecoderSymbolPtr() const noexcept { return &mDecoderSymbol; };
76
77 [[nodiscard]] inline bool operator==(const DecoderSymbol& other) const { return this->getSourceSymbol() == other.getSourceSymbol(); };
78 [[nodiscard]] inline bool operator!=(const DecoderSymbol& other) const { return !operator==(other); };
79
80 friend std::ostream& operator<<(std::ostream& os, const DecoderSymbol& symbol)
81 {
82 os << fmt::format("Symbol:{{Symbol: {}, Frequency: {}, Cumulative: {}}}",
83 symbol.getSourceSymbol(),
86 return os;
87 }
88
89 protected:
92};
93
95{
96 public:
98 using state_type = uint64_t;
99 using size_type = size_t;
100 using difference_type = std::ptrdiff_t;
101
102 // TODO(milettri): fix once ROOT cling respects the standard http://wg21.link/p1286r2
103 constexpr PrecomputedSymbol() noexcept {}; // NOLINT
104
105 constexpr PrecomputedSymbol(value_type frequency, value_type cumulative, size_t symbolTablePrecision)
106 {
107 assert(cumulative <= utils::pow2(symbolTablePrecision));
108 assert(frequency <= utils::pow2(symbolTablePrecision) - cumulative);
109
110 // Say M := 1 << symbolTablePrecision.
111 //
112 // The original encoder does:
113 // x_new = (x/frequency)*M + cumulative + (x%frequency)
114 //
115 // The fast encoder does (schematically):
116 // q = mul_hi(x, rcp_freq) >> rcp_shift (division)
117 // r = x - q*frequency (remainder)
118 // x_new = q*M + bias + r (new x)
119 // plugging in r into x_new yields:
120 // x_new = bias + x + q*(M - frequency)
121 // =: bias + x + q*cmpl_freq (*)
122 //
123 // and we can just precompute cmpl_freq. Now we just need to
124 // set up our parameters such that the original encoder and
125 // the fast encoder agree.
126
127 mFrequency = frequency;
128 mFrequencyComplement = static_cast<state_type>((utils::pow2(symbolTablePrecision)) - frequency);
129 if (frequency < 2) {
130 // frequency=0 symbols are never valid to encode, so it doesn't matter what
131 // we set our values to.
132 //
133 // frequency=1 is tricky, since the reciprocal of 1 is 1; unfortunately,
134 // our fixed-point reciprocal approximation can only multiply by values
135 // smaller than 1.
136 //
137 // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0.
138 // This gives:
139 // q = mul_hi(x, rcp_freq) >> rcp_shift
140 // = mul_hi(x, (1<<32) - 1)) >> 0
141 // = floor(x - x/(2^32))
142 // = x - 1 if 1 <= x < 2^32
143 // and we know that x>0 (x=0 is never in a valid normalization interval).
144 //
145 // So we now need to choose the other parameters such that
146 // x_new = x*M + cumulative
147 // plug it in:
148 // x*M + cumulative (desired result)
149 // = bias + x + q*cmpl_freq (*)
150 // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq)
151 // = bias + 1 + (x - 1)*M
152 // = x*M + (bias + 1 - M)
153 //
154 // so we have cumulative = bias + 1 - M, or equivalently
155 // bias = cumulative + M - 1.
156 mReciprocalFrequency = static_cast<state_type>(~0ul);
157 mReciprocalShift = 0;
158 mCumulative = cumulative + (utils::pow2(symbolTablePrecision)) - 1;
159 } else {
160 // Alverson, "Integer Division using reciprocals"
161 const uint32_t shift = std::ceil(std::log2(frequency));
162
163 // long divide ((uint128) (1 << (shift + 63)) + frequency-1) / frequency
164 // by splitting it into two 64:64 bit divides (this works because
165 // the dividend has a simple form.)
166 uint64_t x0 = frequency - 1;
167 const uint64_t x1 = 1ull << (shift + 31);
168
169 const uint64_t t1 = x1 / frequency;
170 x0 += (x1 % frequency) << 32;
171 const uint64_t t0 = x0 / frequency;
172
173 mReciprocalFrequency = t0 + (t1 << 32);
174
175 mReciprocalShift = shift - 1;
176
177 // With these values, 'q' is the correct quotient, so we
178 // have bias=cumulative.
179 mCumulative = cumulative;
180 }
181 };
182
183 [[nodiscard]] inline constexpr value_type getFrequency() const noexcept { return mFrequency; };
184 [[nodiscard]] inline constexpr value_type getCumulative() const noexcept { return mCumulative; };
185 [[nodiscard]] inline constexpr state_type getReciprocalFrequency() const noexcept { return mReciprocalFrequency; };
186 [[nodiscard]] inline constexpr value_type getFrequencyComplement() const noexcept { return mFrequencyComplement; };
187 [[nodiscard]] inline constexpr value_type getReciprocalShift() const noexcept { return mReciprocalShift; };
188 [[nodiscard]] inline bool operator==(const PrecomputedSymbol& other) const { return this->getCumulative() == other.getCumulative(); };
189 [[nodiscard]] inline bool operator!=(const PrecomputedSymbol& other) const { return !operator==(other); };
190
191 friend std::ostream& operator<<(std::ostream& os, const PrecomputedSymbol& symbol)
192 {
193 os << fmt::format("PrecomputedSymbol{{Frequency: {},Cumulative: {}, ReciprocalFrequency {}, FrequencyComplement {}, mReciprocalShift {}}}",
194 symbol.getFrequency(),
195 symbol.getCumulative(),
196 symbol.getReciprocalFrequency(),
197 symbol.getFrequencyComplement(),
198 symbol.getReciprocalShift());
199 return os;
200 };
201
202 private:
203 value_type mFrequency{};
204 value_type mCumulative{};
205 state_type mReciprocalFrequency{}; // Fixed-point reciprocal frequency
206 value_type mFrequencyComplement{}; // Complement of frequency: (1 << symbolTablePrecision) - frequency
207 value_type mReciprocalShift{}; // Reciprocal shift
208}; // namespace internal
209
210} // namespace o2::rans::internal
211
212#endif /* RANS_INTERNAL_CONTAINERS_SYMBOL_H_ */
common helper classes and functions
constexpr const value_type & getDecoderSymbol() const noexcept
Definition Symbol.h:74
bool operator==(const DecoderSymbol &other) const
Definition Symbol.h:77
constexpr source_type getSourceSymbol() const noexcept
Definition Symbol.h:73
bool operator!=(const DecoderSymbol &other) const
Definition Symbol.h:78
constexpr DecoderSymbol(source_type symbol, typename value_type::value_type frequency, typename value_type::value_type cumulative)
Definition Symbol.h:71
constexpr DecoderSymbol(source_type sourceSymbol, Symbol decoderSymbol)
Definition Symbol.h:70
friend std::ostream & operator<<(std::ostream &os, const DecoderSymbol &symbol)
Definition Symbol.h:80
constexpr DecoderSymbol() noexcept
Definition Symbol.h:69
std::ptrdiff_t difference_type
Definition Symbol.h:66
constexpr const value_type * getDecoderSymbolPtr() const noexcept
Definition Symbol.h:75
constexpr state_type getReciprocalFrequency() const noexcept
Definition Symbol.h:185
bool operator==(const PrecomputedSymbol &other) const
Definition Symbol.h:188
constexpr value_type getCumulative() const noexcept
Definition Symbol.h:184
friend std::ostream & operator<<(std::ostream &os, const PrecomputedSymbol &symbol)
Definition Symbol.h:191
constexpr value_type getFrequencyComplement() const noexcept
Definition Symbol.h:186
constexpr PrecomputedSymbol() noexcept
Definition Symbol.h:103
constexpr value_type getReciprocalShift() const noexcept
Definition Symbol.h:187
bool operator!=(const PrecomputedSymbol &other) const
Definition Symbol.h:189
constexpr value_type getFrequency() const noexcept
Definition Symbol.h:183
constexpr PrecomputedSymbol(value_type frequency, value_type cumulative, size_t symbolTablePrecision)
Definition Symbol.h:105
constexpr const value_type * data() const noexcept
Definition Symbol.h:44
constexpr Symbol() noexcept
Definition Symbol.h:39
constexpr value_type getCumulative() const noexcept
Definition Symbol.h:43
constexpr value_type getFrequency() const noexcept
Definition Symbol.h:42
bool operator!=(const Symbol &other) const
Definition Symbol.h:47
friend std::ostream & operator<<(std::ostream &os, const Symbol &symbol)
Definition Symbol.h:49
std::ptrdiff_t difference_type
Definition Symbol.h:36
bool operator==(const Symbol &other) const
Definition Symbol.h:46
std::array< value_type, 2 > mSymbol
Definition Symbol.h:56
constexpr Symbol(value_type frequency, value_type cumulative, size_t symbolTablePrecision=0)
Definition Symbol.h:40
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLuint GLfloat x0
Definition glcorearb.h:5034
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
constexpr size_t pow2(size_t n) noexcept
Definition utils.h:165
uint32_t count_t
Definition defaults.h:34
VectorOfTObjectPtrs other