Project
Loading...
Searching...
No Matches
DenseHistogram.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_CONTAINERS_DENSEHISTOGRAM_H_
17#define RANS_INTERNAL_CONTAINERS_DENSEHISTOGRAM_H_
18
19#include <algorithm>
20#include <cassert>
21
22#include <gsl/span>
23
24#include <fairlogger/Logger.h>
25#include <utility>
26
32
33#ifdef RANS_SIMD
36#endif /* RANS_SIMD */
37
38namespace o2::rans
39{
40
41namespace internal
42{
43namespace histogramImpl
44{
45
46template <typename source_T>
47inline std::pair<source_T, source_T> minmaxImpl(const source_T* begin, const source_T* end)
48{
49 const auto [minIter, maxIter] = std::minmax_element(begin, end);
50 return {*minIter, *maxIter};
51};
52
53#ifdef RANS_SIMD
54template <>
55inline std::pair<uint32_t, uint32_t> minmaxImpl<uint32_t>(const uint32_t* begin, const uint32_t* end)
56{
57 return internal::simd::minmax(begin, end);
58};
59
60template <>
61inline std::pair<int32_t, int32_t> minmaxImpl<int32_t>(const int32_t* begin, const int32_t* end)
62{
63 return internal::simd::minmax(begin, end);
64};
65#endif /* RANS_SIMD */
66
67}; // namespace histogramImpl
68
69template <typename source_T>
70inline std::pair<source_T, source_T> minmax(gsl::span<const source_T> range)
71{
72 const auto begin = range.data();
73 const auto end = begin + range.size();
74 return histogramImpl::minmaxImpl<source_T>(begin, end);
75};
76
77} // namespace internal
78
79namespace utils
80{
81template <typename source_T>
82inline std::pair<source_T, source_T> minmax(gsl::span<const source_T> range)
83{
84 return internal::minmax(range);
85}
86} // namespace utils
87
88template <typename source_T, typename = void>
89class DenseHistogram;
90
91template <typename source_T>
92class DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>> : public internal::VectorContainer<source_T, uint32_t>,
93 public internal::HistogramConcept<source_T,
94 typename internal::VectorContainer<source_T, uint32_t>::value_type,
95 typename internal::VectorContainer<source_T, uint32_t>::difference_type,
96 DenseHistogram<source_T>>
97{
103
104 friend containerBase_type;
106
107 public:
118
119 DenseHistogram() = default;
120
121 template <typename freq_IT>
123
124 // operations
125 using HistogramConcept_type::addSamples;
126
127 using HistogramConcept_type::addFrequencies;
128
129 template <typename source_IT>
131 {
132 if constexpr (std::is_pointer_v<source_IT>) {
133 return addSamplesImpl(gsl::make_span(begin, end), min, max);
134 } else {
135 return addSamplesImpl(begin, end, min, max);
136 }
137 };
138
139 template <typename source_IT>
140 DenseHistogram& addSamples(gsl::span<const source_type> span, source_type min, source_type max)
141 {
142 return addSamplesImpl(span, min, max);
143 };
144
146
148 {
149 return resize(this->getOffset(), this->getOffset() + newSize);
150 };
151
152 protected:
153 DenseHistogram& addSamplesImpl(gsl::span<const source_type> span);
154
155 template <typename source_IT>
156 DenseHistogram& addSamplesImpl(source_IT begin, source_IT end);
157
158 template <typename source_IT>
160
161 DenseHistogram& addSamplesImpl(gsl::span<const source_type> span, source_type min, source_type max);
162
163 template <typename freq_IT>
165
166 private:
167 inline static constexpr size_t MaxSize{utils::pow2(30)}; // 4GB per histogram size limit;
168
169 bool isValidRange(difference_type min, difference_type max);
170};
171
172template <typename source_T>
173inline bool DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>>::isValidRange(difference_type min, difference_type max)
174{
175 bool ret = true;
176 if constexpr (std::is_unsigned_v<source_T>) {
177 if (min < 0) {
178 LOGP(warning, "trying to add frequencies for a signed symbol to a DenseHistogram of an unsiged type.");
179 ret = false;
180 }
181 }
182 if (max - min > static_cast<difference_type>(this->MaxSize)) {
183 LOGP(warning, "DenseHistogram exceeds {} elements threshold", this->MaxSize);
184 ret = false;
185 }
186 return ret;
187}
188
189template <typename source_T>
190inline auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>>::addSamplesImpl(gsl::span<const source_type> samples) -> DenseHistogram&
191{
192 if (samples.size() > 0) {
193 const auto [min, max] = internal::minmax(samples);
194 addSamplesImpl(samples, min, max);
195 } else {
196 LOG(warning) << "Passed empty message to " << __func__; // RS this is ok for empty columns
197 }
198 return *this;
199}
200
201template <typename source_T>
202template <typename source_IT>
203inline auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>>::addSamplesImpl(source_IT begin, source_IT end) -> DenseHistogram&
204{
205 if (begin != end) {
206 const auto [minIter, maxIter] = std::minmax_element(begin, end);
207 addSamplesImpl(begin, end, *minIter, *maxIter);
208 } else {
209 LOG(warning) << "Passed empty message to " << __func__; // RS this is ok for empty columns
210 }
211 return *this;
212}
213
214template <typename source_T>
215inline auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>>::addSamplesImpl(gsl::span<const source_type> samples, source_type min, source_type max) -> DenseHistogram&
216{
217 using namespace internal;
218 using namespace utils;
219
220 if (samples.empty()) {
221 return *this;
222 }
223 this->resize(min, max);
224
225 const auto begin = samples.data();
226 const auto end = begin + samples.size();
227 constexpr size_t ElemsPerQWord = sizeof(uint64_t) / sizeof(source_type);
228 constexpr size_t nUnroll = 4 * ElemsPerQWord;
229 auto iter = begin;
230
231 if (getRangeBits(min, max) <= 17) {
232 container_type histogram{this->mContainer.size(), this->mContainer.getOffset()};
233
234 auto addQWord = [&, this](uint64_t in64) {
235 uint64_t i = in64;
236 ++this->mContainer[static_cast<source_type>(i)];
237 i = in64 >> 32;
238 ++histogram[static_cast<source_type>(i)];
239 };
240
241 if (end - nUnroll > begin) {
242 for (; iter < end - nUnroll; iter += nUnroll) {
243 addQWord(load64(iter));
244 addQWord(load64(iter + ElemsPerQWord));
245 addQWord(load64(iter + 2 * ElemsPerQWord));
246 addQWord(load64(iter + 3 * ElemsPerQWord));
247 this->mNSamples += nUnroll;
248 __builtin_prefetch(iter + 512, 0);
249 }
250 }
251
252 while (iter != end) {
253 ++this->mNSamples;
254 ++this->mContainer[*iter++];
255 }
256#if defined(RANS_OPENMP) && defined(RANS_SIMD)
257#pragma omp simd
258#endif
259 for (size_t i = 0; i < this->size(); ++i) {
260 this->mContainer.data()[i] += histogram.data()[i];
261 }
262 } else {
263 auto addQWord = [&, this](uint64_t in64) {
264 uint64_t i = in64;
265 ++this->mContainer[static_cast<source_type>(i)];
266 i = in64 >> 32;
267 ++this->mContainer[static_cast<source_type>(i)];
268 };
269
270 if (end - nUnroll > begin) {
271 for (; iter < end - nUnroll; iter += nUnroll) {
272 addQWord(load64(iter));
273 addQWord(load64(iter + ElemsPerQWord));
274 addQWord(load64(iter + 2 * ElemsPerQWord));
275 addQWord(load64(iter + 3 * ElemsPerQWord));
276 this->mNSamples += nUnroll;
277 __builtin_prefetch(iter + 512, 0);
278 }
279 }
280
281 while (iter != end) {
282 ++this->mNSamples;
283 ++this->mContainer[*iter++];
284 }
285 }
286
287 return *this;
288};
289
290template <typename source_T>
291template <typename source_IT>
292auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>>::addSamplesImpl(source_IT begin, source_IT end, source_type min, source_type max) -> DenseHistogram&
293{
294 if (begin == end) {
295 LOG(warning) << "Passed empty message to " << __func__; // RS this is ok for empty columns
296 } else {
297
298 if (!this->isValidRange(min, max)) {
299 throw HistogramError(fmt::format("Incompatible Frequency table dimensions: Cannot add samples in range [{},{}] to {} int32 histogram.",
300 min, max, []() {if constexpr (std::is_signed_v<source_T>) {return "signed";} else {return "unsigned";} }()));
301 }
302 this->resize(min, max);
303 // add new symbols
304 std::for_each(begin, end, [this](source_type symbol) {
305 ++this->mContainer[symbol];
306 ++this->mNSamples; });
307 }
308
309 return *this;
310}
311
312template <typename source_T>
313template <typename freq_IT>
314auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) == 4>>::addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset) -> DenseHistogram&
315{
316 using namespace internal;
317
318 const auto thisHistogramView = makeHistogramView(this->mContainer);
319 const auto addedHistogramView = trim(HistogramView{begin, end, offset});
320 if (addedHistogramView.empty()) {
321 LOG(warning) << "Passed empty DenseHistogram to " << __func__; // RS this is ok for empty columns
322 } else {
323
324 const difference_type newMin = std::min(thisHistogramView.getMin(), addedHistogramView.getMin());
325 const difference_type newMax = std::max(thisHistogramView.getMax(), addedHistogramView.getMax());
326
327 if (!this->isValidRange(newMin, newMax) ||
328 newMin < static_cast<difference_type>(std::numeric_limits<source_T>::min()) ||
329 newMax > static_cast<difference_type>(std::numeric_limits<source_T>::max())) {
330 throw HistogramError(fmt::format("Incompatible Frequency table dimensions: Cannot add [{},{}] to {} int32 histogram.",
331 addedHistogramView.getMin(),
332 addedHistogramView.getMax(),
333 []() {if constexpr (std::is_signed_v<source_T>) {return "signed";} else {return "unsigned";} }()));
334 };
335
336 if (thisHistogramView.empty()) {
337 this->mContainer = container_type(addedHistogramView.size(), addedHistogramView.getOffset());
338 std::transform(addedHistogramView.begin(), addedHistogramView.end(), this->mContainer.begin(), [this](count_t frequency) {
339 return this->countSamples(frequency);
340 });
341 } else {
342 const difference_type newSize = newMax - newMin + 1;
343 typename container_type::container_type newHistogram(newSize, 0);
344 const auto newHistogramView = makeHistogramView(newHistogram, newMin);
345 auto histogramOverlap = getIntersection(newHistogramView, thisHistogramView);
346 assert(!histogramOverlap.empty());
347 assert(histogramOverlap.size() == thisHistogramView.size());
348 std::copy(thisHistogramView.begin(), thisHistogramView.end(), histogramOverlap.begin());
349
350 histogramOverlap = getIntersection(newHistogramView, addedHistogramView);
351 assert(!histogramOverlap.empty());
352 assert(histogramOverlap.size() == addedHistogramView.size());
353 std::transform(addedHistogramView.begin(), addedHistogramView.end(),
354 histogramOverlap.begin(), histogramOverlap.begin(),
355 [this](const count_t& a, const count_t& b) { return safeadd(this->countSamples(a), b); });
356
357 this->mContainer = container_type{std::move(newHistogram), static_cast<source_type>(newHistogramView.getOffset())};
358 }
359 }
360
361 return *this;
362}
363
364template <typename source_T>
366{
367 using namespace utils;
368
369 auto getMaxSymbol = [this]() {
370 return static_cast<source_type>(this->getOffset() + std::max(0l, static_cast<int32_t>(this->size()) - 1l));
371 };
372
373 min = std::min(min, this->getOffset());
374 max = std::max(max, getMaxSymbol());
375
376 if (min > max) {
377 throw HistogramError(fmt::format("{} failed: min {} > max {} ", __func__, min, max));
378 }
379
380 const size_type newSize = max - min + 1;
381 const source_type oldOffset = this->getOffset();
382 this->mNSamples = 0;
383
384 if (this->mContainer.empty()) {
385 this->mContainer = container_type{newSize, min};
386 return *this;
387 } else {
388 container_type oldHistogram = std::move(this->mContainer);
389 const auto oldHistogramView = makeHistogramView(oldHistogram, oldOffset);
390 this->mContainer = container_type{newSize, min};
391 return this->addFrequencies(oldHistogramView.begin(), oldHistogramView.end(), oldHistogramView.getMin());
392 }
393}
394
395template <typename source_T>
396class DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) <= 2>> : public internal::VectorContainer<source_T, uint32_t>,
398 typename internal::VectorContainer<source_T, uint32_t>::value_type,
399 typename internal::VectorContainer<source_T, uint32_t>::difference_type,
400 DenseHistogram<source_T>>
401{
402 using containerBase_type = internal::VectorContainer<source_T, uint32_t>;
403 using HistogramConcept_type = internal::HistogramConcept<source_T,
407
408 friend containerBase_type;
409 friend HistogramConcept_type;
410
411 public:
412 using source_type = source_T;
413 using value_type = typename containerBase_type::value_type;
414 using container_type = typename containerBase_type::container_type;
415 using size_type = typename containerBase_type::size_type;
416 using difference_type = typename containerBase_type::difference_type;
417 using reference = typename containerBase_type::reference;
418 using const_reference = typename containerBase_type::const_reference;
419 using pointer = typename containerBase_type::pointer;
420 using const_pointer = typename containerBase_type::const_pointer;
421 using const_iterator = typename containerBase_type::const_iterator;
422
423 DenseHistogram() : containerBase_type{MaxSize, std::numeric_limits<source_type>::min()} {};
424
425 template <typename freq_IT>
426 DenseHistogram(freq_IT begin, freq_IT end, difference_type offset) : containerBase_type{MaxSize, std::numeric_limits<source_type>::min()},
427 HistogramConcept_type{begin, end, offset} {};
428
429 using HistogramConcept_type::addSamples;
430
431 template <typename source_IT>
432 inline DenseHistogram& addSamples(source_IT begin, source_IT end, source_type min, source_type max)
433 {
434 return addSamplesImpl(begin, end);
435 };
436
437 template <typename source_IT>
438 DenseHistogram& addSamples(gsl::span<const source_type> span, source_type min, source_type max)
439 {
440 return addSamplesImpl(span);
441 };
442
443 using HistogramConcept_type::addFrequencies;
444
445 protected:
446 template <typename source_IT>
447 DenseHistogram& addSamplesImpl(source_IT begin, source_IT end);
448
449 DenseHistogram& addSamplesImpl(gsl::span<const source_type> samples);
450
451 template <typename freq_IT>
452 DenseHistogram& addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset);
453
454 private:
455 inline static constexpr size_t MaxSize = utils::pow2(utils::toBits<source_type>());
456};
457
458template <typename source_T>
459template <typename source_IT>
460auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) <= 2>>::addSamplesImpl(source_IT begin, source_IT end) -> DenseHistogram&
461{
462 if constexpr (std::is_pointer_v<source_IT>) {
463 return addSamplesImpl({begin, end});
464 } else {
465 std::for_each(begin, end, [this](const source_type& symbol) {
466 ++this->mNSamples;
467 ++this->mContainer[symbol]; });
468 }
469 return *this;
470}
471
472template <typename source_T>
473auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) <= 2>>::addSamplesImpl(gsl::span<const source_type> samples) -> DenseHistogram&
474{
475 using namespace internal;
476 using namespace utils;
477
478 if (samples.empty()) {
479 return *this;
480 }
481
482 const auto begin = samples.data();
483 const auto end = begin + samples.size();
484 constexpr size_t ElemsPerQWord = sizeof(uint64_t) / sizeof(source_type);
485 constexpr size_t nUnroll = 2 * ElemsPerQWord;
486 auto iter = begin;
487
488 if constexpr (sizeof(source_type) == 1) {
489
490 std::array<ShiftableVector<source_type, value_type>, 3> histograms{
491 {{this->mContainer.size(), this->mContainer.getOffset()},
492 {this->mContainer.size(), this->mContainer.getOffset()},
493 {this->mContainer.size(), this->mContainer.getOffset()}}};
494
495 auto addQWord = [&, this](uint64_t in64) {
496 uint64_t i = in64;
497 ++histograms[0][static_cast<source_type>(i)];
498 ++histograms[1][static_cast<source_type>(static_cast<uint16_t>(i) >> 8)];
499 i >>= 16;
500 ++histograms[2][static_cast<source_type>(i)];
501 ++this->mContainer[static_cast<source_type>(static_cast<uint16_t>(i) >> 8)];
502 i = in64 >>= 32;
503 ++histograms[0][static_cast<source_type>(i)];
504 ++histograms[1][static_cast<source_type>(static_cast<uint16_t>(i) >> 8)];
505 i >>= 16;
506 ++histograms[2][static_cast<source_type>(i)];
507 ++this->mContainer[static_cast<source_type>(static_cast<uint16_t>(i) >> 8)];
508 };
509
510 if (end - nUnroll > begin) {
511 for (; iter < end - nUnroll; iter += nUnroll) {
512 addQWord(load64(iter));
513 addQWord(load64(iter + ElemsPerQWord));
514 this->mNSamples += nUnroll;
515 __builtin_prefetch(iter + 512, 0);
516 }
517 }
518
519 while (iter != end) {
520 ++this->mNSamples;
521 ++this->mContainer[*iter++];
522 }
523
524#if defined(RANS_OPENMP)
525#pragma omp unroll full
526#endif
527 for (size_t j = 0; j < 3; ++j) {
528#if defined(RANS_OPENMP) && defined(RANS_SIMD)
529#pragma omp simd
530#endif
531 for (size_t i = 0; i < 256; ++i) {
532 this->mContainer(i) += histograms[j](i);
533 }
534 }
535 } else {
536 container_type histogram{this->mContainer.size(), this->mContainer.getOffset()};
537
538 auto addQWord = [&, this](uint64_t in64) {
539 uint64_t i = in64;
540 ++histogram[static_cast<source_type>(i)];
541 ++this->mContainer[static_cast<source_type>(static_cast<uint32_t>(i) >> 16)];
542 i = in64 >> 32;
543 ++histogram[static_cast<source_type>(i)];
544 ++this->mContainer[static_cast<source_type>(static_cast<uint32_t>(i) >> 16)];
545 };
546
547 if (end - nUnroll > begin) {
548 for (; iter < end - nUnroll; iter += nUnroll) {
549 addQWord(load64(iter));
550 addQWord(load64(iter + ElemsPerQWord));
551 this->mNSamples += nUnroll;
552 __builtin_prefetch(iter + 512, 0);
553 }
554 }
555
556 while (iter != end) {
557 ++this->mNSamples;
558 ++this->mContainer[*iter++];
559 }
560#if defined(RANS_OPENMP) && defined(RANS_SIMD)
561#pragma omp simd
562#endif
563 for (size_t i = 0; i < this->size(); ++i) {
564 this->mContainer.data()[i] += histogram.data()[i];
565 }
566 }
567
568 return *this;
569}
570
571template <typename source_T>
572template <typename freq_IT>
573auto DenseHistogram<source_T, std::enable_if_t<sizeof(source_T) <= 2>>::addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset) -> DenseHistogram&
574{
575 using namespace internal;
576
577 // bounds check
579 addedHistogramView = trim(addedHistogramView);
580
581 if constexpr (std::is_unsigned_v<source_T>) {
582 LOG_IF(warning, addedHistogramView.getMin() < 0) << fmt::format("trying to add frequencies of a signed symbol type to a DenseHistogram of an unsiged type.");
583 }
584 if constexpr (std::is_signed_v<source_T>) {
585 const std::ptrdiff_t sourceTypeMax = std::numeric_limits<source_T>::max();
586 const bool isMinOutOfRange = addedHistogramView.getMin() > sourceTypeMax;
587 const bool isMaxOutOfRange = addedHistogramView.getMax() > sourceTypeMax;
588
589 if (isMaxOutOfRange || isMinOutOfRange) {
590 LOGP(warning, "trying to add frequencies of an unsigned symbol type to a DenseHistogram of a signed type");
591 }
592 }
593
594 const auto thisHistogramView = makeHistogramView(this->mContainer);
595 const bool isInvalidFrequencyRange = utils::toBytes(utils::getRangeBits(addedHistogramView.getMin(), addedHistogramView.getMax())) > sizeof(source_T);
596
597 if (isInvalidFrequencyRange) {
598 throw HistogramError(fmt::format("Incompatible Frequency table dimensions: Cannot add [{},{}] to [{}, {}] ",
599 addedHistogramView.getMin(),
600 addedHistogramView.getMax(),
601 thisHistogramView.getMin(),
602 thisHistogramView.getMax()));
603 }
604
605 auto idx = static_cast<source_type>(addedHistogramView.getOffset()); // We tolerate uint8_t <-> int8_t and uint16_t <-> int16_t conversion.
606 // The resulting overflows are handled correctly by the container via [] operator.
607 for (freq_IT iter = addedHistogramView.begin(); iter != addedHistogramView.end(); ++iter) {
608 auto frequency = *iter;
609 this->mContainer[idx] = safeadd(this->mContainer[idx], this->countSamples(frequency));
610 ++idx;
611 }
612 return *this;
613}
614
615template <typename source_T>
617{
618 return std::count_if(histogram.begin(), histogram.end(), [](typename DenseHistogram<source_T>::const_reference v) { return v != typename DenseHistogram<source_T>::value_type{}; });
619}
620
621} // namespace o2::rans
622
623#endif /* RANS_INTERNAL_CONTAINERS_DENSEHISTOGRAM_H_ */
unsigned int uint32_t
unsigned short int uint16_t
int32_t i
Operations that will be performed on a histogram.
Non-owning, lightweight structure for histogram manipulation.
uint32_t j
Definition RawData.h:0
common helper classes and functions
Abstract container class that defines and implements basic properties shared by histograms and lookup...
uint32_t source_type
DenseHistogram & addSamplesImpl(source_IT begin, source_IT end)
DenseHistogram & addSamplesImpl(source_IT begin, source_IT end, source_type min, source_type max)
DenseHistogram(freq_IT begin, freq_IT end, difference_type offset)
DenseHistogram & addSamples(source_IT begin, source_IT end, source_type min, source_type max)
DenseHistogram & addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset)
DenseHistogram & addSamples(gsl::span< const source_type > span, source_type min, source_type max)
typename base_type::const_pointer const_pointer
Definition Container.h:97
typename base_type::const_reference const_reference
Definition Container.h:95
typename base_type::value_type value_type
Definition Container.h:90
typename base_type::const_iterator const_iterator
Definition Container.h:98
typename base_type::container_type container_type
Definition Container.h:91
typename base_type::difference_type difference_type
Definition Container.h:93
rans exceptions
GLenum void ** pointer
Definition glcorearb.h:805
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLsizei samples
Definition glcorearb.h:1309
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum GLint * range
Definition glcorearb.h:1899
GLint reference
Definition glcorearb.h:5487
GLintptr offset
Definition glcorearb.h:660
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
auto make_span(const o2::rans::internal::simd::AlignedArray< T, width_V, size_V > &array)
std::pair< source_T, source_T > minmaxImpl(const source_T *begin, const source_T *end)
uint64_t load64(const void *__restrict src)
Definition utils.h:74
std::pair< source_T, source_T > minmax(gsl::span< const source_T > range)
constexpr size_t pow2(size_t n) noexcept
Definition utils.h:165
std::pair< source_T, source_T > minmax(gsl::span< const source_T > range)
auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset) -> DenseHistogram &HistogramView addedHistogramView
const auto thisHistogramView
class DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > > :public internal::VectorContainer< source_T, uint32_t >, internal::HistogramConcept< source_T, typename internal::VectorContainer< source_T, uint32_t >::value_type, typename internal::VectorContainer< source_T, uint32_t >::difference_type, DenseHistogram< source_T > >{ using containerBase_type=internal::VectorContainer< source_T, uint32_t >;using HistogramConcept_type=internal::HistogramConcept< source_T, typename internal::VectorContainer< source_T, uint32_t >::value_type, typename internal::VectorContainer< source_T, uint32_t >::difference_type, DenseHistogram< source_T > >;friend containerBase_type;friend HistogramConcept_type;public:using source_type=source_T;using value_type=typename containerBase_type::value_type;using container_type=typename containerBase_type::container_type;using size_type=typename containerBase_type::size_type;using difference_type=typename containerBase_type::difference_type;using reference=typename containerBase_type::reference;using const_reference=typename containerBase_type::const_reference;using pointer=typename containerBase_type::pointer;using const_pointer=typename containerBase_type::const_pointer;using const_iterator=typename containerBase_type::const_iterator;DenseHistogram() :containerBase_type{MaxSize, std::numeric_limits< source_type >::min()} {};template< typename freq_IT > DenseHistogram(freq_IT begin, freq_IT end, difference_type offset) :containerBase_type{MaxSize, std::numeric_limits< source_type >::min()}, HistogramConcept_type{begin, end, offset} {};using HistogramConcept_type::addSamples;template< typename source_IT > inline DenseHistogram &addSamples(source_IT begin, source_IT end, source_type min, source_type max) { return addSamplesImpl(begin, end);};template< typename source_IT > DenseHistogram &addSamples(gsl::span< const source_type > span, source_type min, source_type max) { return addSamplesImpl(span);};using HistogramConcept_type::addFrequencies;protected:template< typename source_IT > DenseHistogram &addSamplesImpl(source_IT begin, source_IT end);DenseHistogram &addSamplesImpl(gsl::span< const source_type > samples);template< typename freq_IT > DenseHistogram &addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset);private:inline static constexpr size_t MaxSize=utils::pow2(utils::toBits< source_type >());};template< typename source_T >template< typename source_IT >auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addSamplesImpl(source_IT begin, source_IT end) -> DenseHistogram &{ if constexpr(std::is_pointer_v< source_IT >) { return addSamplesImpl({begin, end});} else { std::for_each(begin, end, [this](const source_type &symbol) {++this->mNSamples;++this->mContainer[symbol];});} return *this;}template< typename source_T >auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addSamplesImpl(gsl::span< const source_type > samples) -> DenseHistogram &{ using namespace internal;using namespace utils;if(samples.empty()) { return *this;} const auto begin=samples.data();const auto end=begin+samples.size();constexpr size_t ElemsPerQWord=sizeof(uint64_t)/sizeof(source_type);constexpr size_t nUnroll=2 *ElemsPerQWord;auto iter=begin;if constexpr(sizeof(source_type)==1) { std::array< ShiftableVector< source_type, value_type >, 3 > histograms{ {{this-> mContainer this mContainer auto addQWord
class DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > > :public internal::VectorContainer< source_T, uint32_t >, internal::HistogramConcept< source_T, typename internal::VectorContainer< source_T, uint32_t >::value_type, typename internal::VectorContainer< source_T, uint32_t >::difference_type, DenseHistogram< source_T > >{ using containerBase_type=internal::VectorContainer< source_T, uint32_t >;using HistogramConcept_type=internal::HistogramConcept< source_T, typename internal::VectorContainer< source_T, uint32_t >::value_type, typename internal::VectorContainer< source_T, uint32_t >::difference_type, DenseHistogram< source_T > >;friend containerBase_type;friend HistogramConcept_type;public:using source_type=source_T;using value_type=typename containerBase_type::value_type;using container_type=typename containerBase_type::container_type;using size_type=typename containerBase_type::size_type;using difference_type=typename containerBase_type::difference_type;using reference=typename containerBase_type::reference;using const_reference=typename containerBase_type::const_reference;using pointer=typename containerBase_type::pointer;using const_pointer=typename containerBase_type::const_pointer;using const_iterator=typename containerBase_type::const_iterator;DenseHistogram() :containerBase_type{MaxSize, std::numeric_limits< source_type >::min()} {};template< typename freq_IT > DenseHistogram(freq_IT begin, freq_IT end, difference_type offset) :containerBase_type{MaxSize, std::numeric_limits< source_type >::min()}, HistogramConcept_type{begin, end, offset} {};using HistogramConcept_type::addSamples;template< typename source_IT > inline DenseHistogram &addSamples(source_IT begin, source_IT end, source_type min, source_type max) { return addSamplesImpl(begin, end);};template< typename source_IT > DenseHistogram &addSamples(gsl::span< const source_type > span, source_type min, source_type max) { return addSamplesImpl(span);};using HistogramConcept_type::addFrequencies;protected:template< typename source_IT > DenseHistogram &addSamplesImpl(source_IT begin, source_IT end);DenseHistogram &addSamplesImpl(gsl::span< const source_type > samples);template< typename freq_IT > DenseHistogram &addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset);private:inline static constexpr size_t MaxSize=utils::pow2(utils::toBits< source_type >());};template< typename source_T >template< typename source_IT >auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addSamplesImpl(source_IT begin, source_IT end) -> DenseHistogram &{ if constexpr(std::is_pointer_v< source_IT >) { return addSamplesImpl({begin, end});} else { std::for_each(begin, end, [this](const source_type &symbol) {++this->mNSamples;++this->mContainer[symbol];});} return *this;}template< typename source_T >auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addSamplesImpl(gsl::span< const source_type > samples) -> DenseHistogram &{ using namespace internal;using namespace utils;if(samples.empty()) { return *this;} const auto begin=samples.data();const auto end=begin+samples.size();constexpr size_t ElemsPerQWord=sizeof(uint64_t)/sizeof(source_type);constexpr size_t nUnroll=2 *ElemsPerQWord;auto iter=begin;if constexpr(sizeof(source_type)==1) { std::array< ShiftableVector< source_type, value_type >, 3 > histograms{ {{this-> mContainer this mContainer getOffset()}
HistogramView< HistA_IT > getIntersection(const HistogramView< HistA_IT > &histA, const HistogramView< HistB_IT > &histB)
class DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > > :public internal::VectorContainer< source_T, uint32_t >, internal::HistogramConcept< source_T, typename internal::VectorContainer< source_T, uint32_t >::value_type, typename internal::VectorContainer< source_T, uint32_t >::difference_type, DenseHistogram< source_T > >{ using containerBase_type=internal::VectorContainer< source_T, uint32_t >;using HistogramConcept_type=internal::HistogramConcept< source_T, typename internal::VectorContainer< source_T, uint32_t >::value_type, typename internal::VectorContainer< source_T, uint32_t >::difference_type, DenseHistogram< source_T > >;friend containerBase_type;friend HistogramConcept_type;public:using source_type=source_T;using value_type=typename containerBase_type::value_type;using container_type=typename containerBase_type::container_type;using size_type=typename containerBase_type::size_type;using difference_type=typename containerBase_type::difference_type;using reference=typename containerBase_type::reference;using const_reference=typename containerBase_type::const_reference;using pointer=typename containerBase_type::pointer;using const_pointer=typename containerBase_type::const_pointer;using const_iterator=typename containerBase_type::const_iterator;DenseHistogram() :containerBase_type{MaxSize, std::numeric_limits< source_type >::min()} {};template< typename freq_IT > DenseHistogram(freq_IT begin, freq_IT end, difference_type offset) :containerBase_type{MaxSize, std::numeric_limits< source_type >::min()}, HistogramConcept_type{begin, end, offset} {};using HistogramConcept_type::addSamples;template< typename source_IT > inline DenseHistogram &addSamples(source_IT begin, source_IT end, source_type min, source_type max) { return addSamplesImpl(begin, end);};template< typename source_IT > DenseHistogram &addSamples(gsl::span< const source_type > span, source_type min, source_type max) { return addSamplesImpl(span);};using HistogramConcept_type::addFrequencies;protected:template< typename source_IT > DenseHistogram &addSamplesImpl(source_IT begin, source_IT end);DenseHistogram &addSamplesImpl(gsl::span< const source_type > samples);template< typename freq_IT > DenseHistogram &addFrequenciesImpl(freq_IT begin, freq_IT end, difference_type offset);private:inline static constexpr size_t MaxSize=utils::pow2(utils::toBits< source_type >());};template< typename source_T >template< typename source_IT >auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addSamplesImpl(source_IT begin, source_IT end) -> DenseHistogram &{ if constexpr(std::is_pointer_v< source_IT >) { return addSamplesImpl({begin, end});} else { std::for_each(begin, end,[this](const source_type &symbol) {++this->mNSamples;++this->mContainer[symbol];});} return *this;}template< typename source_T >auto DenseHistogram< source_T, std::enable_if_t< sizeof(source_T)<=2 > >::addSamplesImpl(gsl::span< const source_type > samples) -> DenseHistogram &{ using namespace internal;using namespace utils;if(samples.empty()) { return *this;} const auto begin=samples.data();const auto end=begin+samples.size();constexpr size_t ElemsPerQWord=sizeof(uint64_t)/sizeof(source_type);constexpr size_t nUnroll=2 *ElemsPerQWord;auto iter=begin;if constexpr(sizeof(source_type)==1) { std::array< ShiftableVector< source_type, value_type >, 3 > histograms{ {{this-> mContainer size()
auto makeHistogramView(container_T &container, std::ptrdiff_t offset) noexcept -> HistogramView< decltype(std::begin(container))>
return * this
HistogramView< Hist_IT > trim(const HistogramView< Hist_IT > &buffer)
size_t countNUsedAlphabetSymbols(const AdaptiveHistogram< source_T > &histogram)
const bool isInvalidFrequencyRange
Enum< T >::Iterator begin(Enum< T >)
Definition Defs.h:158
Common utility functions.
wrapper around basic SIMD operations
basic SIMD datatypes and traits
constexpr size_t min
constexpr size_t max
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
pedsdata resize(norbits)
auto getOffset(const map_T &resultsMap) -> typename map_T::key_type