Project
Loading...
Searching...
No Matches
test_ransSerialize.cxx
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#define BOOST_TEST_MODULE Utility test
17#define BOOST_TEST_MAIN
18#define BOOST_TEST_DYN_LINK
19
20#undef NDEBUG
21#include <cassert>
22
23#include <vector>
24#include <cstring>
25#include <random>
26#include <algorithm>
27
28#include <boost/test/unit_test.hpp>
29#include <boost/mp11.hpp>
30#include <fmt/core.h>
31
32#include "rANS/serialize.h"
33#include "rANS/histogram.h"
34#include "rANS/factory.h"
35#include "rANS/metrics.h"
37
38using namespace o2::rans;
39
40using buffer_types = boost::mp11::mp_list<uint8_t, uint16_t, uint32_t, uint64_t>;
41using source_types = boost::mp11::mp_list<uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t>;
42
43using test_types = boost::mp11::mp_product<boost::mp11::mp_list, source_types, buffer_types>;
44
45BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeEmptyHistogram, T, test_types)
46{
47 using source_type = boost::mp11::mp_first<T>;
48 using buffer_type = boost::mp11::mp_second<T>;
49
52 auto srcRenormedHistogram = renorm(h, metrics);
53 SizeEstimate sizeEstimate{metrics};
54 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
55
56 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
57 auto begin = serializationBuffer.data();
58 auto end = compressRenormedDictionary(srcRenormedHistogram, begin);
59
60 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
61 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
62 *iter = static_cast<buffer_type>(~0);
63 }
64
65 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
66
67 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
68 BOOST_CHECK_EQUAL(srcRenormedHistogram.getOffset(), restoredRenormedHistogram.getOffset());
69 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
70
71 DenseSymbolTable<source_type, internal::Symbol> srcSymbolTable(srcRenormedHistogram);
72 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
73
74 BOOST_CHECK_EQUAL_COLLECTIONS(srcSymbolTable.begin(), srcSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
75};
76
77BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeEmptySymbolTable, T, test_types)
78{
79 using source_type = boost::mp11::mp_first<T>;
80 using buffer_type = boost::mp11::mp_second<T>;
81
84 auto srcRenormedHistogram = renorm(h, metrics);
85 DenseSymbolTable<source_type, internal::Symbol> srcSymbolTable(srcRenormedHistogram);
86
87 SizeEstimate sizeEstimate{metrics};
88
89 std::vector<buffer_type> serializationBuffer(256, 0);
90 auto begin = serializationBuffer.data();
91 auto end = compressRenormedDictionary(srcSymbolTable, begin);
92
93 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
94 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
95 *iter = static_cast<buffer_type>(~0);
96 }
97
98 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
99
100 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
101 BOOST_CHECK_EQUAL(srcRenormedHistogram.getOffset(), restoredRenormedHistogram.getOffset());
102 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
103
104 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
105
106 BOOST_CHECK_EQUAL_COLLECTIONS(srcSymbolTable.begin(), srcSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
107};
108
109template <typename source_T>
110class SourceMessage
111{
112 public:
113 SourceMessage(size_t messageSize, source_T max = std::numeric_limits<source_T>::max(), source_T min = std::numeric_limits<source_T>::min()) : mMin{min}, mMax{max}
114 {
115 if (mSourceMessage.empty()) {
116 std::mt19937 mt(0); // same seed we want always the same distrubution of random numbers;
117 assert(max >= min);
118 const size_t draws = (max - min) + 1;
119 const double probability = 0.5;
120 std::binomial_distribution<int64_t> dist(draws, probability);
121 mSourceMessage.resize(messageSize);
122 std::generate(mSourceMessage.begin(), mSourceMessage.end(), [&dist, &mt, min]() -> source_T { return static_cast<int64_t>(dist(mt)) + min; });
123 }
124 }
125
126 inline constexpr source_T getMin() const noexcept { return mMin; };
127 inline constexpr source_T getMax() const noexcept { return mMax; };
128 inline constexpr auto& get() const noexcept { return mSourceMessage; };
129
130 private:
131 source_T mMin{};
132 source_T mMax{};
133 std::vector<source_T> mSourceMessage{};
134};
135
137{
138 public:
140
141 template <typename T>
142 const auto& getMessage() const noexcept
143 {
144 if constexpr (std::is_same_v<uint8_t, T>) {
145 return sourceMessage8u.get();
146 } else if constexpr (std::is_same_v<int8_t, T>) {
147 return sourceMessage8.get();
148 } else if constexpr (std::is_same_v<uint16_t, T>) {
149 return sourceMessage16u.get();
150 } else if constexpr (std::is_same_v<int16_t, T>) {
151 return sourceMessage16.get();
152 } else if constexpr (std::is_same_v<uint32_t, T>) {
153 return sourceMessage32u.get();
154 } else if constexpr (std::is_same_v<int32_t, T>) {
155 return sourceMessage32.get();
156 } else {
157 throw Exception{"unsupported source type"};
158 }
159 };
160
161 private:
162 inline static constexpr size_t MessageSize = utils::pow2(10);
163 inline static const SourceMessage<uint8_t> sourceMessage8u{MessageSize};
164 inline static const SourceMessage<int8_t> sourceMessage8{MessageSize};
165 inline static const SourceMessage<uint16_t> sourceMessage16u{MessageSize};
166 inline static const SourceMessage<int16_t> sourceMessage16{MessageSize};
167 inline static const SourceMessage<uint32_t> sourceMessage32u{MessageSize, utils::pow2(27)};
168 inline static const SourceMessage<int32_t> sourceMessage32{MessageSize, utils::pow2(26), -static_cast<int32_t>(utils::pow2(26))};
169};
170
172
173BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeHistogram, T, test_types)
174{
175 using source_type = boost::mp11::mp_first<T>;
176 using buffer_type = boost::mp11::mp_second<T>;
177
179 auto h = makeDenseHistogram::fromSamples(message.begin(), message.end());
181 auto srcRenormedHistogram = renorm(h, metrics);
182 ;
183 SizeEstimate sizeEstimate{metrics};
184 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
185
186 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
187 auto begin = serializationBuffer.data();
188 auto end = compressRenormedDictionary(srcRenormedHistogram, begin);
189
190 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
191 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
192 *iter = static_cast<buffer_type>(~0);
193 }
194
195 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
196
197 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
198 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
199
200 DenseSymbolTable<source_type, internal::Symbol> srcSymbolTable(srcRenormedHistogram);
201 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
202
203 BOOST_CHECK_EQUAL(srcSymbolTable.getOffset(), restoredSymbolTable.getOffset());
204 BOOST_CHECK_EQUAL_COLLECTIONS(srcSymbolTable.begin(), srcSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
205};
206
207BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeSymbolTable, T, test_types)
208{
209 using source_type = boost::mp11::mp_first<T>;
210 using buffer_type = boost::mp11::mp_second<T>;
211
213 auto h = makeDenseHistogram::fromSamples(message.begin(), message.end());
215 auto srcRenormedHistogram = renorm(h, metrics);
216 DenseSymbolTable<source_type, internal::Symbol> srcSymbolTable(srcRenormedHistogram);
217
218 SizeEstimate sizeEstimate{metrics};
219 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
220
221 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
222 auto begin = serializationBuffer.data();
223 auto end = compressRenormedDictionary(srcSymbolTable, begin);
224
225 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
226 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
227 *iter = static_cast<buffer_type>(~0);
228 }
229
230 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
231
232 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
233 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
234
235 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
236
237 BOOST_CHECK_EQUAL(srcSymbolTable.getOffset(), restoredSymbolTable.getOffset());
238 BOOST_CHECK_EQUAL_COLLECTIONS(srcSymbolTable.begin(), srcSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
239};
240
241using adaptiveSource_types = boost::mp11::mp_list<uint32_t, int32_t>;
242
243using adaptiveTest_types = boost::mp11::mp_product<boost::mp11::mp_list, source_types, buffer_types>;
244
245BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeAdaptiveHistogram, T, adaptiveTest_types)
246{
247 using source_type = boost::mp11::mp_first<T>;
248 using buffer_type = boost::mp11::mp_second<T>;
249
251 auto h = makeSparseHistogram::fromSamples(message.begin(), message.end());
253 auto srcRenormedHistogram = renorm(h, metrics);
254 auto h1 = makeDenseHistogram::fromSamples(message.begin(), message.end());
255 auto crossCheckRenormedHistogram = renorm(h1, metrics);
256 SizeEstimate sizeEstimate{metrics};
257 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
258
259 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
260 auto begin = serializationBuffer.data();
261 auto end = compressRenormedDictionary(srcRenormedHistogram, begin);
262
263 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
264 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
265 *iter = static_cast<buffer_type>(~0);
266 }
267
268 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
269
270 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
271 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
272
273 DenseSymbolTable<source_type, internal::Symbol> srcSymbolTable(crossCheckRenormedHistogram);
274 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
275
276 BOOST_CHECK_EQUAL(srcSymbolTable.getOffset(), restoredSymbolTable.getOffset());
277 BOOST_CHECK_EQUAL_COLLECTIONS(srcSymbolTable.begin(), srcSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
278};
279
280BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeAdaptiveSymbolTable, T, adaptiveTest_types)
281{
282 using source_type = boost::mp11::mp_first<T>;
283 using buffer_type = boost::mp11::mp_second<T>;
284
286 auto h = makeSparseHistogram::fromSamples(message.begin(), message.end());
287 auto h1 = makeDenseHistogram::fromSamples(message.begin(), message.end());
289 auto srcRenormedHistogram = renorm(h, metrics);
290 AdaptiveSymbolTable<source_type, internal::Symbol> srcSymbolTable(srcRenormedHistogram);
292
293 SizeEstimate sizeEstimate{metrics};
294 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
295
296 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
297 auto begin = serializationBuffer.data();
298 auto end = compressRenormedDictionary(srcSymbolTable, begin);
299
300 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
301 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
302 *iter = static_cast<buffer_type>(~0);
303 }
304
305 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
306
307 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
308 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
309
310 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
311
312 BOOST_CHECK_EQUAL(srcCrossCheckSymbolTable.getOffset(), restoredSymbolTable.getOffset());
313 BOOST_CHECK_EQUAL_COLLECTIONS(srcCrossCheckSymbolTable.begin(), srcCrossCheckSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
314};
315
317
318BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeSparseHistogram, T, sparseTest_types)
319{
320 using source_type = boost::mp11::mp_first<T>;
321 using buffer_type = boost::mp11::mp_second<T>;
322
324 auto h = makeSparseHistogram::fromSamples(message.begin(), message.end());
326 auto srcRenormedHistogram = renorm(h, metrics);
327 auto h1 = makeDenseHistogram::fromSamples(message.begin(), message.end());
328 auto crossCheckRenormedHistogram = renorm(h1, metrics);
329 SizeEstimate sizeEstimate{metrics};
330 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
331
332 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
333 auto begin = serializationBuffer.data();
334 auto end = compressRenormedDictionary(srcRenormedHistogram, begin);
335
336 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
337 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
338 *iter = static_cast<buffer_type>(~0);
339 }
340
341 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
342
343 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
344 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
345
346 DenseSymbolTable<source_type, internal::Symbol> srcSymbolTable(crossCheckRenormedHistogram);
347 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
348
349 BOOST_CHECK_EQUAL(srcSymbolTable.getOffset(), restoredSymbolTable.getOffset());
350 BOOST_CHECK_EQUAL_COLLECTIONS(srcSymbolTable.begin(), srcSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
351};
352
353BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeSparseSymbolTable, T, sparseTest_types)
354{
355 using source_type = boost::mp11::mp_first<T>;
356 using buffer_type = boost::mp11::mp_second<T>;
357
359 auto h = makeSparseHistogram::fromSamples(message.begin(), message.end());
360 auto h1 = makeDenseHistogram::fromSamples(message.begin(), message.end());
362 auto srcRenormedHistogram = renorm(h, metrics);
363 SparseSymbolTable<source_type, internal::Symbol> srcSymbolTable(srcRenormedHistogram);
365
366 SizeEstimate sizeEstimate{metrics};
367 size_t bufferSize = sizeEstimate.getCompressedDictionarySize<buffer_type>();
368
369 std::vector<buffer_type> serializationBuffer(bufferSize, 0);
370 auto begin = serializationBuffer.data();
371 auto end = compressRenormedDictionary(srcSymbolTable, begin);
372
373 // fill the rest of the serialization buffer with 1s to test that we are not reading bits from the buffer that comes after.
374 for (auto iter = end; iter != begin + serializationBuffer.size(); ++iter) {
375 *iter = static_cast<buffer_type>(~0);
376 }
377
378 auto restoredRenormedHistogram = readRenormedDictionary(begin, end, *metrics.getCoderProperties().min, *metrics.getCoderProperties().max, srcRenormedHistogram.getRenormingBits());
379
380 BOOST_CHECK_EQUAL(srcRenormedHistogram.getIncompressibleSymbolFrequency(), restoredRenormedHistogram.getIncompressibleSymbolFrequency());
381 BOOST_CHECK_EQUAL(srcRenormedHistogram.getNumSamples(), restoredRenormedHistogram.getNumSamples());
382
383 DenseSymbolTable<source_type, internal::Symbol> restoredSymbolTable(restoredRenormedHistogram);
384
385 BOOST_CHECK_EQUAL(srcCrossCheckSymbolTable.getOffset(), restoredSymbolTable.getOffset());
386 BOOST_CHECK_EQUAL_COLLECTIONS(srcCrossCheckSymbolTable.begin(), srcCrossCheckSymbolTable.end(), restoredSymbolTable.begin(), restoredSymbolTable.end());
387};
Contains statistical information for one source symbol, required for encoding/decoding.
constexpr size_t MessageSize
uint32_t source_type
Class for time synchronization of RawReader instances.
SourceMessageProxy()=default
const auto & getMessage() const noexcept
constexpr source_T getMin() const noexcept
constexpr auto & get() const noexcept
constexpr source_T getMax() const noexcept
SourceMessage(size_t messageSize, source_T max=std::numeric_limits< source_T >::max(), source_T min=std::numeric_limits< source_T >::min())
size_t getCompressedDictionarySize(double_t safetyFactor=2) const
const_iterator begin() const noexcept
Definition Container.h:53
const_iterator end() const noexcept
Definition Container.h:55
source_type getOffset() const noexcept
Definition Container.h:104
static factory classes for building histograms, encoders and decoders.
GLuint GLuint end
Definition glcorearb.h:469
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
Definition glcorearb.h:5500
GLuint GLsizei const GLchar * message
Definition glcorearb.h:2517
public interface for building and renorming histograms from source data.
dest_IT compressRenormedDictionary(const container_T &container, dest_IT dstBufferBegin)
Definition serialize.h:142
RenormedDenseHistogram< source_T > readRenormedDictionary(buffer_IT begin, buffer_IT end, source_T min, source_T max, size_t renormingPrecision)
Definition serialize.h:188
decltype(auto) renorm(histogram_T histogram, size_t newPrecision, RenormingPolicy renormingPolicy=RenormingPolicy::Auto, size_t lowProbabilityCutoffBits=0)
Definition renorm.h:203
public interface for serializing histograms (dictionaries) to JSON or compressed binary.
static decltype(auto) fromSamples(source_IT begin, source_IT end)
Definition factory.h:65
static decltype(auto) fromSamples(source_IT begin, source_IT end, typename std::iterator_traits< source_IT >::value_type min, typename std::iterator_traits< source_IT >::value_type max)
Definition factory.h:144
boost::mp11::mp_list< uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t > source_types
uint32_t buffer_type
constexpr size_t min
constexpr size_t max
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())
boost::mp11::mp_list< int8_t, int16_t, int32_t, int64_t > buffer_types
boost::mp11::mp_product< boost::mp11::mp_list, source_types, buffer_types > test_types
boost::mp11::mp_list< uint32_t, int32_t > adaptiveSource_types
adaptiveTest_types sparseTest_types
const SourceMessageProxy MessageProxy
boost::mp11::mp_product< boost::mp11::mp_list, source_types, buffer_types > adaptiveTest_types
BOOST_AUTO_TEST_CASE_TEMPLATE(testSerializeDeserializeEmptyHistogram, T, test_types)