Project
Loading...
Searching...
No Matches
HistogramView.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_HISTOGRAMVIEW_H_
17#define RANS_INTERNAL_CONTAINERS_HISTOGRAMVIEW_H_
18
19#include <iterator>
20#include <algorithm>
21#include <ostream>
22#include <iterator>
23
24#include <fairlogger/Logger.h>
25
28
29namespace o2::rans
30{
31
32template <typename Hist_IT>
34{
35 public:
36 using size_type = size_t;
37 using value_type = typename std::iterator_traits<Hist_IT>::value_type;
41 using const_pointer = const value_type*;
42 using difference_type = std::ptrdiff_t;
43 using iterator = Hist_IT;
44 using reverse_iterator = std::reverse_iterator<iterator>;
45
46 HistogramView() = default;
47 HistogramView(const HistogramView&) = default;
51 ~HistogramView() = default;
52
54
55 [[nodiscard]] inline size_t size() const { return std::distance(mBegin, mEnd); };
56
57 [[nodiscard]] inline bool empty() const { return mBegin == mEnd; };
58
59 [[nodiscard]] inline difference_type getOffset() const noexcept { return mOffset; };
60
61 [[nodiscard]] inline difference_type getMin() const noexcept { return this->getOffset(); };
62
63 [[nodiscard]] inline difference_type getMax() const { return this->getOffset() + static_cast<difference_type>(this->size() - !this->empty()); };
64
65 [[nodiscard]] inline iterator begin() const { return mBegin; };
66
67 [[nodiscard]] inline iterator end() const { return mEnd; };
68
69 [[nodiscard]] inline reverse_iterator rbegin() const { return std::make_reverse_iterator(this->end()); };
70
71 [[nodiscard]] inline reverse_iterator rend() const { return std::make_reverse_iterator(this->begin()); };
72
73 friend std::ostream& operator<<(std::ostream& os, const HistogramView& view)
74 {
75 os << fmt::format("HistogramView: size {}, offset {}", view.size(), view.getOffset());
76 return os;
77 };
78
79 [[nodiscard]] inline const value_type& operator[](difference_type idx) const
80 {
81 auto iter = utils::advanceIter(mBegin, idx - this->getOffset());
82
83 assert(iter >= this->begin());
84 assert(iter < this->end());
85 return *iter;
86 }
87
88 [[nodiscard]] inline const_pointer data() const
89 {
90 assert(mBegin != mEnd);
91 return &(*mBegin);
92 }
93
94 private:
95 iterator mBegin{};
96 iterator mEnd{};
97 difference_type mOffset{};
98
99 static_assert(std::is_same_v<typename std::iterator_traits<Hist_IT>::iterator_category, std::random_access_iterator_tag>, "This template is defined only for random access iterators");
100};
101
102template <typename Hist_IT>
104{
105
106 using value_type = typename HistogramView<Hist_IT>::value_type;
107
108 auto isZero = [](const value_type& i) { return i == value_type{}; };
109 auto nonZeroBegin = std::find_if_not(buffer.begin(), buffer.end(), isZero);
110 auto nonZeroEnd = nonZeroBegin == buffer.end() ? buffer.end() : std::find_if_not(std::make_reverse_iterator(buffer.end()), std::make_reverse_iterator(buffer.begin()), isZero).base();
111
112 std::ptrdiff_t newOffset;
113 if (nonZeroBegin == nonZeroEnd) {
114 newOffset = buffer.getOffset();
115 } else {
116 newOffset = buffer.getMin() + std::distance(buffer.begin(), nonZeroBegin);
117 }
118
119 return {nonZeroBegin, nonZeroEnd, newOffset};
120};
121
122template <typename HistA_IT, typename HistB_IT>
123[[nodiscard]] inline std::ptrdiff_t getLeftOffset(const HistogramView<HistA_IT>& histA, const HistogramView<HistB_IT>& histB) noexcept
124{
125 return histB.getOffset() - histA.getOffset();
126}
127
128template <typename HistA_IT, typename HistB_IT>
129[[nodiscard]] inline std::ptrdiff_t getRightOffset(const HistogramView<HistA_IT>& histA, const HistogramView<HistB_IT>& histB)
130{
131 return histB.getMax() - histA.getMax();
132}
133
134template <typename HistA_IT, typename HistB_IT>
136{
137 auto mkEmpty = [&histA]() { return HistogramView(histA.end(), histA.end(), 0); };
138
139 if (histA.empty() || histB.empty()) {
140 // one is empty
141 return mkEmpty();
142 } else if (histA.getMin() > histB.getMax() || histA.getMax() < histB.getMin()) {
143 // disjoint
144 return mkEmpty();
145 } else {
146 // intersecting
147 const std::ptrdiff_t leftOffset = getLeftOffset(histA, histB);
148 const std::ptrdiff_t rightOffset = getRightOffset(histA, histB);
149 HistA_IT begin = leftOffset > 0 ? utils::advanceIter(histA.begin(), leftOffset) : histA.begin();
150 HistA_IT end = rightOffset < 0 ? utils::advanceIter(histA.end(), rightOffset) : histA.end();
151 std::ptrdiff_t offset = leftOffset > 0 ? histA.getOffset() + leftOffset : histA.getOffset();
152 return {begin, end, offset};
153 }
154} // namespace utils
155
156template <typename HistA_IT, typename HistB_IT>
158{
159 if (histA.empty() || histB.empty()) {
160 return histA;
161 }
162
163 const std::ptrdiff_t leftOffset = getLeftOffset(histA, histB);
164 if (leftOffset <= 0) {
165 // case 1 no left difference
166 return {histA.end(), histA.end(), 0};
167 } else if (histA.getMin() > histB.getMax()) {
168 // case 2 disjoint
169 return histA;
170 } else {
171 // case 3 0 < leftOffset <= histA.size()
172 return {histA.begin(), utils::advanceIter(histA.begin(), leftOffset), histA.getOffset()};
173 }
174};
175
176template <typename HistA_IT, typename HistB_IT>
178{
179 if (histA.empty() || histB.empty()) {
180 return histA;
181 }
182
183 const std::ptrdiff_t rightOffset = getRightOffset(histA, histB);
184
185 if (rightOffset > 0) {
186 // case 1 no right tail
187 return {histA.end(), histA.end(), 0};
188 } else if (histA.getMax() < histB.getMin()) {
189 // case 2 disjoint
190 return histA;
191 } else {
192 // case 3 0 < -rightOffset <= histA.size()
193 auto newBegin = utils::advanceIter(histA.end(), rightOffset);
194 return {newBegin, histA.end(), *newBegin};
195 }
196};
197
198template <typename container_T>
199inline auto makeHistogramView(container_T& container, std::ptrdiff_t offset) noexcept -> HistogramView<decltype(std::begin(container))>
200{
201 return {std::begin(container), std::end(container), offset};
202}
203
204template <typename container_T>
205inline auto makeHistogramView(const container_T& container, std::ptrdiff_t offset) noexcept -> HistogramView<decltype(std::cbegin(container))>
206{
207 return {std::cbegin(container), std::cend(container), offset};
208}
209
210namespace histogramview_impl
211{
212
213template <class, class = void>
214struct has_getOffset : std::false_type {
215};
216
217template <class T>
218struct has_getOffset<T, std::void_t<decltype(std::declval<T>().getOffset())>> : std::true_type {
219};
220
221template <typename T>
222inline constexpr bool has_getOffset_v = has_getOffset<T>::value;
223
224} // namespace histogramview_impl
225
226template <typename container_T, std::enable_if_t<histogramview_impl::has_getOffset_v<container_T>, bool> = true>
227inline auto makeHistogramView(const container_T& container) noexcept -> HistogramView<decltype(std::cbegin(container))>
228{
229 return {std::cbegin(container), std::cend(container), container.getOffset()};
230}
231
232template <typename container_T, std::enable_if_t<histogramview_impl::has_getOffset_v<container_T>, bool> = true>
233inline auto makeHistogramView(container_T& container) noexcept -> HistogramView<decltype(std::begin(container))>
234{
235 return {std::begin(container), std::end(container), container.getOffset()};
236}
237
238} // namespace o2::rans
239
240#endif /* RANS_INTERNAL_CONTAINERS_HISTOGRAMVIEW_H_ */
int32_t i
common helper classes and functions
helper functionalities useful for packing operations
iterator end() const
const value_type & operator[](difference_type idx) const
const value_type * const_pointer
const value_type & const_reference
HistogramView(HistogramView &&)=default
reverse_iterator rend() const
iterator begin() const
std::reverse_iterator< iterator > reverse_iterator
difference_type getMax() const
reverse_iterator rbegin() const
difference_type getMin() const noexcept
HistogramView(const HistogramView &)=default
const_pointer data() const
friend std::ostream & operator<<(std::ostream &os, const HistogramView &view)
HistogramView(iterator begin, iterator end, difference_type offset=0)
HistogramView & operator=(const HistogramView &)=default
typename std::iterator_traits< Hist_IT >::value_type value_type
HistogramView & operator=(HistogramView &&)=default
std::ptrdiff_t difference_type
difference_type getOffset() const noexcept
GLuint buffer
Definition glcorearb.h:655
GLuint GLuint end
Definition glcorearb.h:469
GLintptr offset
Definition glcorearb.h:660
Freq_IT advanceIter(Freq_IT iter, std::ptrdiff_t distance)
Definition utils.h:191
std::ptrdiff_t getLeftOffset(const HistogramView< HistA_IT > &histA, const HistogramView< HistB_IT > &histB) noexcept
HistogramView< HistA_IT > getIntersection(const HistogramView< HistA_IT > &histA, const HistogramView< HistB_IT > &histB)
auto makeHistogramView(container_T &container, std::ptrdiff_t offset) noexcept -> HistogramView< decltype(std::begin(container))>
HistogramView< Hist_IT > trim(const HistogramView< Hist_IT > &buffer)
HistogramView< HistA_IT > getRightTail(const HistogramView< HistA_IT > &histA, const HistogramView< HistB_IT > &histB)
std::ptrdiff_t getRightOffset(const HistogramView< HistA_IT > &histA, const HistogramView< HistB_IT > &histB)
HistogramView< HistA_IT > getLeftTail(const HistogramView< HistA_IT > &histA, const HistogramView< HistB_IT > &histB)
Defining DataPointCompositeObject explicitly as copiable.