Project
Loading...
Searching...
No Matches
pack.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 RANS_INTERNAL_PACK_PACK_H_
17#define RANS_INTERNAL_PACK_PACK_H_
18
19#include <cstdint>
20#include <cstring>
21#include <array>
22#include <type_traits>
23
24#include <iostream>
25
29
30namespace o2::rans
31{
32
33template <typename storageBuffer_T = uint8_t>
34[[nodiscard]] constexpr size_t computePackingBufferSize(size_t extent, size_t packingWidthBits) noexcept
35{
36 using namespace internal;
37 using namespace utils;
38 if (extent > 0) {
39 constexpr size_t PackingBufferBits = toBits<packing_type>();
40 const size_t packedSizeBits = extent * packingWidthBits;
41
42 const size_t packingBufferElems = packedSizeBits / PackingBufferBits + 1;
43 const size_t packingBufferBytes = packingBufferElems * sizeof(packing_type);
44 const size_t storageBufferElems = utils::nBytesTo<storageBuffer_T>(packingBufferBytes);
45 return storageBufferElems;
46 } else {
47 return 0;
48 }
49}
50
51namespace internal
52{
53
54inline BitPtr packShort(BitPtr pos, uint64_t data, size_t packingWidth)
55{
56 assert(pos != BitPtr{});
57 assert(packingWidth <= 58);
58 uint8_t* posPtr = pos.toPtr<uint8_t>();
59 const size_t posBitOffset = pos.getOffset<uint8_t>();
60
61 packing_type buffer = load64(reinterpret_cast<void*>(posPtr));
62 buffer |= data << posBitOffset;
63 write64(posPtr, buffer);
64
65 return pos += packingWidth;
66};
67
68inline BitPtr pack(BitPtr pos, uint64_t data, size_t packingWidth)
69{
70 return packShort(pos, data, packingWidth);
71}
72
73inline BitPtr packLong(BitPtr pos, uint64_t data, size_t packingWidth)
74{
75 assert(pos != BitPtr{});
76 uint8_t* posPtr = pos.toPtr<uint8_t>();
77 const size_t posBitOffset = pos.getOffset<uint8_t>();
78
79 const size_t bitOffsetEnd = posBitOffset + packingWidth;
80 packing_type buffer = load64(reinterpret_cast<void*>(posPtr));
81
82 constexpr size_t PackingBufferBits = utils::toBits<packing_type>();
83
84 if (bitOffsetEnd <= PackingBufferBits) {
85 buffer |= data << posBitOffset;
86 write64(posPtr, buffer);
87 } else {
88 const size_t tailBits = PackingBufferBits - posBitOffset;
89 buffer |= bitExtract(data, 0, tailBits) << posBitOffset;
90 write64(posPtr, buffer);
91 posPtr += sizeof(packing_type);
92 buffer = load64(reinterpret_cast<void*>(posPtr));
93 buffer |= data >> tailBits;
94 write64(posPtr, buffer);
95 }
96
97 return pos += packingWidth;
98};
99
100template <typename T>
101inline T unpack(BitPtr pos, size_t packingWidth)
102{
103 assert(pos != BitPtr{});
104 assert(packingWidth <= utils::toBits<T>());
105 assert(packingWidth <= 58);
106
107 uint8_t* posPtr = pos.toPtr<uint8_t>();
108 size_t posBitOffset = pos.getOffset<uint8_t>();
109
110 packing_type buffer = load64(reinterpret_cast<void*>(posPtr));
111 return static_cast<T>(bitExtract(buffer, posBitOffset, packingWidth));
112};
113
114inline uint64_t unpackLong(BitPtr pos, size_t packingWidth)
115{
116 assert(pos != BitPtr{});
117 assert(packingWidth < 64);
118
119 uint8_t* posPtr = pos.toPtr<uint8_t>();
120 size_t bitOffset = pos.getOffset<uint8_t>();
121
122 constexpr size_t PackingBufferBits = utils::toBits<packing_type>();
123 const size_t bitOffsetEnd = bitOffset + packingWidth;
124 packing_type buffer = load64(reinterpret_cast<void*>(posPtr));
125 uint64_t ret{};
126 if (bitOffsetEnd <= PackingBufferBits) {
127 ret = bitExtract(buffer, bitOffset, packingWidth);
128 } else {
129 // first part
130 ret = bitExtract(buffer, bitOffset, PackingBufferBits - bitOffset);
131 // second part
132 bitOffset = bitOffsetEnd - PackingBufferBits;
133 posPtr += sizeof(packing_type);
134 buffer = load64(reinterpret_cast<void*>(posPtr));
135 ret |= bitExtract(buffer, 0, bitOffset) << (packingWidth - bitOffset);
136 }
137
138 return ret;
139};
140
141template <typename input_T, typename output_T, size_t width_V>
142constexpr BitPtr packStreamImpl(const input_T* __restrict inputBegin, size_t extent, output_T* outputBegin, input_T offset)
143{
144 assert(inputBegin != nullptr);
145 assert(outputBegin != nullptr);
146
147 constexpr size_t PackingBufferBits = utils::toBits<packing_type>();
148 constexpr size_t PackingWidth = width_V;
149
150 constexpr size_t NPackAtOnce = PackingBufferBits / PackingWidth;
151
152 uint8_t* outputIter = reinterpret_cast<uint8_t*>(outputBegin);
153 size_t outputIterBitOffset = {};
154
155 const size_t nIterations = extent / NPackAtOnce;
156 const size_t nRemainderIterations = extent % NPackAtOnce;
157
158 auto inputIter = inputBegin;
159 const auto iterEnd = inputIter + NPackAtOnce * nIterations;
160 packing_type overflowBuffer{0};
161
162 for (; inputIter < iterEnd; inputIter += NPackAtOnce) {
163 packing_type packed = packMultiple<input_T, width_V>(inputIter, offset);
164
165 const size_t tail = PackingBufferBits - outputIterBitOffset;
166 overflowBuffer |= packed << outputIterBitOffset;
167 outputIterBitOffset += NPackAtOnce * PackingWidth;
168
169 if constexpr (PackingBufferBits % PackingWidth == 0) {
170 write64(outputIter, overflowBuffer);
171 overflowBuffer = 0;
172 outputIterBitOffset = 0;
173 outputIter += sizeof(packing_type);
174 } else {
175 if (outputIterBitOffset >= PackingBufferBits) {
176 write64(outputIter, overflowBuffer);
177 outputIter += sizeof(packing_type);
178 overflowBuffer = packed >> tail;
179 }
180 outputIterBitOffset %= PackingBufferBits;
181 }
182 }
183 write64(outputIter, overflowBuffer);
184
185 BitPtr bitPos{outputIter, static_cast<intptr_t>(outputIterBitOffset)};
186 for (size_t i = 0; i < nRemainderIterations; ++i) {
187 const int64_t adjustedValue = static_cast<int64_t>(inputIter[i]) - offset;
188 bitPos = pack(bitPos, adjustedValue, PackingWidth);
189 }
190
191 return bitPos;
192};
193} // namespace internal
194
195template <typename input_T, typename output_T>
196inline constexpr BitPtr pack(const input_T* __restrict inputBegin, size_t extent, output_T* __restrict outputBegin, size_t packingWidth, input_T offset = static_cast<input_T>(0))
197{
198 using namespace internal;
199 using namespace utils;
200
201 assert(inputBegin != nullptr);
202 assert(outputBegin != nullptr);
203
204 switch (packingWidth) {
205 case 0:
206 if (extent > 0) {
207 throw PackingError("Cannot pack data into 0 Bit wide blocks");
208 } else {
209 return BitPtr(outputBegin);
210 }
211 break;
212 case 1:
213 return packStreamImpl<input_T, output_T, 1>(inputBegin, extent, outputBegin, offset);
214 break;
215 case 2:
216 return packStreamImpl<input_T, output_T, 2>(inputBegin, extent, outputBegin, offset);
217 break;
218 case 3:
219 return packStreamImpl<input_T, output_T, 3>(inputBegin, extent, outputBegin, offset);
220 break;
221 case 4:
222 return packStreamImpl<input_T, output_T, 4>(inputBegin, extent, outputBegin, offset);
223 break;
224 case 5:
225 return packStreamImpl<input_T, output_T, 5>(inputBegin, extent, outputBegin, offset);
226 break;
227 case 6:
228 return packStreamImpl<input_T, output_T, 6>(inputBegin, extent, outputBegin, offset);
229 break;
230 case 7:
231 return packStreamImpl<input_T, output_T, 7>(inputBegin, extent, outputBegin, offset);
232 break;
233 case 8:
234 return packStreamImpl<input_T, output_T, 8>(inputBegin, extent, outputBegin, offset);
235 break;
236 case 9:
237 return packStreamImpl<input_T, output_T, 9>(inputBegin, extent, outputBegin, offset);
238 break;
239 case 10:
240 return packStreamImpl<input_T, output_T, 10>(inputBegin, extent, outputBegin, offset);
241 break;
242 case 11:
243 return packStreamImpl<input_T, output_T, 11>(inputBegin, extent, outputBegin, offset);
244 break;
245 case 12:
246 return packStreamImpl<input_T, output_T, 12>(inputBegin, extent, outputBegin, offset);
247 break;
248 case 13:
249 return packStreamImpl<input_T, output_T, 13>(inputBegin, extent, outputBegin, offset);
250 break;
251 case 14:
252 return packStreamImpl<input_T, output_T, 14>(inputBegin, extent, outputBegin, offset);
253 break;
254 case 15:
255 return packStreamImpl<input_T, output_T, 15>(inputBegin, extent, outputBegin, offset);
256 break;
257 case 16:
258 return packStreamImpl<input_T, output_T, 16>(inputBegin, extent, outputBegin, offset);
259 break;
260 case 17:
261 return packStreamImpl<input_T, output_T, 17>(inputBegin, extent, outputBegin, offset);
262 break;
263 case 18:
264 return packStreamImpl<input_T, output_T, 18>(inputBegin, extent, outputBegin, offset);
265 break;
266 case 19:
267 return packStreamImpl<input_T, output_T, 19>(inputBegin, extent, outputBegin, offset);
268 break;
269 case 20:
270 return packStreamImpl<input_T, output_T, 20>(inputBegin, extent, outputBegin, offset);
271 break;
272 case 21:
273 return packStreamImpl<input_T, output_T, 21>(inputBegin, extent, outputBegin, offset);
274 break;
275 case 22:
276 return packStreamImpl<input_T, output_T, 22>(inputBegin, extent, outputBegin, offset);
277 break;
278 case 23:
279 return packStreamImpl<input_T, output_T, 23>(inputBegin, extent, outputBegin, offset);
280 break;
281 case 24:
282 return packStreamImpl<input_T, output_T, 24>(inputBegin, extent, outputBegin, offset);
283 break;
284 case 25:
285 return packStreamImpl<input_T, output_T, 25>(inputBegin, extent, outputBegin, offset);
286 break;
287 case 26:
288 return packStreamImpl<input_T, output_T, 26>(inputBegin, extent, outputBegin, offset);
289 break;
290 case 27:
291 return packStreamImpl<input_T, output_T, 27>(inputBegin, extent, outputBegin, offset);
292 break;
293 case 28:
294 return packStreamImpl<input_T, output_T, 28>(inputBegin, extent, outputBegin, offset);
295 break;
296 case 29:
297 return packStreamImpl<input_T, output_T, 29>(inputBegin, extent, outputBegin, offset);
298 break;
299 case 30:
300 return packStreamImpl<input_T, output_T, 30>(inputBegin, extent, outputBegin, offset);
301 break;
302 case 31:
303 return packStreamImpl<input_T, output_T, 31>(inputBegin, extent, outputBegin, offset);
304 break;
305 case 32:
306 return packStreamImpl<input_T, output_T, 32>(inputBegin, extent, outputBegin, offset);
307 break;
308 default:
309 BitPtr iter{outputBegin};
310 for (size_t i = 0; i < extent; ++i) {
311 const int64_t adjustedValue = static_cast<int64_t>(inputBegin[i]) - offset;
312 iter = packLong(iter, adjustedValue, packingWidth);
313 }
314 return iter;
315 break;
316 }
317 return {};
318};
319
320template <typename input_IT, typename output_T>
321inline constexpr BitPtr pack(input_IT inputBegin, size_t extent, output_T* __restrict outputBegin, size_t packingWidth,
322 typename std::iterator_traits<input_IT>::value_type offset = 0)
323{
324 using namespace internal;
325 using namespace utils;
326 using source_type = typename std::iterator_traits<input_IT>::value_type;
327 input_IT inputEnd = advanceIter(inputBegin, extent);
328 BitPtr outputIter{outputBegin};
329
330 auto packImpl = [](input_IT inputBegin, input_IT inputEnd, BitPtr outputIter, source_type offset, size_t packingWidth, auto packingFunctor) -> BitPtr {
331 for (auto inputIter = inputBegin; inputIter != inputEnd; ++inputIter) {
332 const int64_t adjustedValue = static_cast<int64_t>(*inputIter) - offset;
333 outputIter = packingFunctor(outputIter, adjustedValue, packingWidth);
334 }
335 return outputIter;
336 };
337
338 if (packingWidth <= 58) {
339 return packImpl(inputBegin, inputEnd, outputIter, offset, packingWidth, packShort);
340 } else {
341 return packImpl(inputBegin, inputEnd, outputIter, offset, packingWidth, packLong);
342 }
343}
344
345template <typename input_T, typename output_IT>
346inline void unpack(const input_T* __restrict inputBegin, size_t extent, output_IT outputBegin, size_t packingWidth, typename std::iterator_traits<output_IT>::value_type offset = static_cast<typename std::iterator_traits<output_IT>::value_type>(0))
347{
348 using namespace internal;
349 using namespace utils;
350 using dst_type = typename std::iterator_traits<output_IT>::value_type;
351
352 // cannot unpack into 0 bits
353 if (packingWidth == 0) {
354 if (extent == 0) {
355 return;
356 } else {
357 throw PackingError("Cannot unpack into 0 Bit wide data");
358 }
359 }
360
361 auto unpackImpl = [&](auto packer) {
362 output_IT outputIt = outputBegin;
363 BitPtr iter{inputBegin};
364 for (size_t i = 0; i < extent; ++i) {
365 auto unpacked = packer(iter, packingWidth) + offset;
366 *outputIt++ = unpacked;
367 iter += packingWidth;
368 }
369 };
370
371 if (packingWidth <= 58) {
372 unpackImpl(unpack<dst_type>);
373 } else {
374 unpackImpl(unpackLong);
375 }
376};
377
378} // namespace o2::rans
379
380#endif /* RANS_INTERNAL_PACK_PACK_H_ */
Pointer type helper class for bitwise Packing.
int32_t i
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h internal
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
uint16_t pos
Definition RawData.h:3
common helper classes and functions
helper functionalities useful for packing operations
GLintptr offset
Definition glcorearb.h:660
uint64_t load64(const void *__restrict src)
Definition utils.h:74
void write64(void *__restrict dest, uint64_t src)
Definition utils.h:81
BitPtr packShort(BitPtr pos, uint64_t data, size_t packingWidth)
Definition pack.h:54
uint64_t packing_type
Definition utils.h:33
constexpr BitPtr packStreamImpl(const input_T *__restrict inputBegin, size_t extent, output_T *outputBegin, input_T offset)
Definition pack.h:142
uint64_t bitExtract(uint64_t data, uint32_t start, uint32_t length) noexcept
Definition utils.h:58
uint64_t unpackLong(BitPtr pos, size_t packingWidth)
Definition pack.h:114
T unpack(BitPtr pos, size_t packingWidth)
Definition pack.h:101
BitPtr packLong(BitPtr pos, uint64_t data, size_t packingWidth)
Definition pack.h:73
constexpr size_t computePackingBufferSize(size_t extent, size_t packingWidthBits) noexcept
Definition pack.h:34
void unpack(const input_T *__restrict inputBegin, size_t extent, output_IT outputBegin, size_t packingWidth, typename std::iterator_traits< output_IT >::value_type offset=static_cast< typename std::iterator_traits< output_IT >::value_type >(0))
Definition pack.h:346
Common utility functions.