Project
Loading...
Searching...
No Matches
algorithmImpl.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_TRANSFORM_ALGORITHMIMPL_H_
17#define RANS_INTERNAL_TRANSFORM_ALGORITHMIMPL_H_
18
19#include <array>
20#include <cstdint>
21#include <cstring>
22#include <type_traits>
23
24#include <gsl/span>
25
28
30{
31
32template <typename container_T, typename IT, std::enable_if_t<isDenseContainer_v<container_T>, bool> = true>
33inline auto trim(IT begin, IT end, typename container_T::const_reference zeroElem) -> std::pair<IT, IT>
34{
35 using value_type = typename std::iterator_traits<IT>::value_type;
36
37 auto isZero = [&zeroElem](value_type i) { return i == zeroElem; };
38 auto nonZeroBegin = std::find_if_not(begin, end, isZero);
39 auto nonZeroEnd = nonZeroBegin == end ? end : std::find_if_not(std::make_reverse_iterator(end), std::make_reverse_iterator(begin), isZero).base();
40
41 return {nonZeroBegin, nonZeroEnd};
42};
43
44template <typename container_T, typename IT, std::enable_if_t<isAdaptiveContainer_v<container_T>, bool> = true>
45inline auto trim(IT begin, IT end, typename container_T::const_reference zeroElem) -> std::pair<IT, IT>
46{
47 using value_type = typename container_T::value_type;
48 using iterator_type = IT;
49 using lut_iterator = typename iterator_type::lut_iterator;
50 using bucket_iterator = typename iterator_type::bucket_iterator;
51
52 auto isZero = [&zeroElem](const auto& i) { return i == zeroElem; };
53
54 // no range
55 if (begin == end) {
56 return {end, end};
57 }
58
59 iterator_type nonZeroBegin = [&]() -> iterator_type {
60 auto lutIter = begin.getLUTIterator();
61 if (lutIter != end.getLUTIterator()) {
62 // finish first incomplete bucket
63 auto nonZeroBegin = std::find_if_not(begin.getBucketIterator(), lutIter->end(), isZero);
64 if (nonZeroBegin != lutIter->end()) {
65 return {begin.getContainer(), lutIter, nonZeroBegin};
66 }
67
68 // go over all remaining buckets
69 for (++lutIter; lutIter != end.getLUTIterator(); ++lutIter) {
70 // and process each element in each bucket
71 auto nonZeroBegin = std::find_if_not(lutIter->begin(), lutIter->end(), isZero);
72 if (nonZeroBegin != lutIter->end()) {
73 return {begin.getContainer(), lutIter, nonZeroBegin};
74 }
75 }
76 }
77 // go over the tail, i.e. the last, possibly incomplete or empty bucket
78 if (end.getBucketIterator() != bucket_iterator{}) {
79 auto iter = (begin.getLUTIterator() == end.getLUTIterator()) ? begin.getBucketIterator() : lutIter->begin();
80 auto nonZeroBegin = std::find_if_not(iter, end.getBucketIterator(), isZero);
81 if (nonZeroBegin != lutIter->end()) {
82 return {begin.getContainer(), lutIter, nonZeroBegin};
83 }
84 }
85 return end;
86 }();
87
88 // empty
89 if (nonZeroBegin == end) {
90 return {end, end};
91 }
92
93 iterator_type nonZeroEnd = [&]() -> iterator_type {
94 auto lutIter = end.getLUTIterator();
95 // start at the tail, i.e. the last, possibly incomplete or empty bucket
96 if (end.getBucketIterator() != bucket_iterator{}) {
97 // if a tail exists, process it
98 auto nonZeroEnd = std::find_if_not(std::make_reverse_iterator(end.getBucketIterator()), lutIter->rend(), isZero);
99 if (nonZeroEnd != lutIter->rend()) {
100 return {begin.getContainer(), lutIter, nonZeroEnd.base()};
101 }
102 }
103
104 // go over all full buckets, appart from the last one.
105 for (; lutIter-- > begin.getLUTIterator();) {
106 // and process each element in each bucket
107 auto nonZeroEnd = std::find_if_not(lutIter->rbegin(), lutIter->rend(), isZero);
108 if (nonZeroEnd != lutIter->rend()) {
109 return {begin.getContainer(), lutIter, nonZeroEnd.base()};
110 }
111 }
112
113 // finish at first ,possibly incomplete bucket
114 assert(lutIter == begin.getLUTIterator());
115 auto bucketREnd = std::make_reverse_iterator(begin.getBucketIterator());
116 auto nonZeroEnd = std::find_if_not(lutIter->rbegin(), bucketREnd, isZero);
117 if (nonZeroEnd != bucketREnd) {
118 return {begin.getContainer(), lutIter, nonZeroEnd.base()};
119 }
120 return begin;
121 }();
122
123 return {nonZeroBegin, nonZeroEnd};
124};
125
126template <typename container_T, typename IT, std::enable_if_t<isHashContainer_v<container_T>, bool> = true>
127inline auto trim(IT begin, IT end, const typename container_T::const_reference zeroElem) -> std::pair<IT, IT>
128{
129 return {begin, end};
130};
131
132template <typename container_T, typename IT, std::enable_if_t<isSetContainer_v<container_T>, bool> = true>
133inline auto trim(IT begin, IT end, typename container_T::const_reference zeroElem) -> std::pair<IT, IT>
134{
135 using value_type = typename std::iterator_traits<IT>::value_type;
136
137 auto isZero = [&zeroElem](const value_type& keyValuePair) { return keyValuePair.second == zeroElem; };
138 auto nonZeroBegin = std::find_if_not(begin, end, isZero);
139
140 // workaround, because we cannot use reverse iterators with this type
141 IT nonZeroEnd = [&]() {
142 if (nonZeroBegin == end) {
143 return end;
144 }
145 size_t size = std::distance(begin, end);
146
147 for (size_t i = size; i-- > 0;) {
148 if ((begin + i)->second != zeroElem) {
149 return ++(begin + i); // don't forget the +1 for one-past the end iterator
150 }
151 }
152 return begin;
153 }();
154
155 return {nonZeroBegin, nonZeroEnd};
156};
157
158template <typename container_T, typename IT, class F, std::enable_if_t<isDenseContainer_v<container_T>, bool> = true>
159inline void forEachIndexValue(container_T&& container, IT begin, IT end, F functor)
160{
161 using container_type = removeCVRef_t<container_T>;
162
163 typename container_type::source_type index = container.getOffset() + std::distance(container.begin(), begin);
164 for (std::ptrdiff_t i = 0; i < std::distance(begin, end); ++i) {
165 functor(index++, begin[i]);
166 }
167}
168
169template <typename container_T, typename IT, class F, std::enable_if_t<isAdaptiveContainer_v<container_T>, bool> = true>
170inline void forEachIndexValue(container_T&& container, IT begin, IT end, F functor)
171{
172 using container_type = removeCVRef_t<container_T>;
173
174 using source_type = typename container_type::source_type;
175 using value_type = typename container_type::value_type;
176 using storage_type = SparseVector<source_type, value_type>;
177 using iterator_type = IT;
178 using lut_iterator = typename iterator_type::lut_iterator;
179 using bucket_iterator = typename iterator_type::bucket_iterator;
180
181 auto& sparseContainer = begin.getContainer();
182
183 // empty
184 if (begin == end) {
185 return;
186 }
187
188 auto lutIter = begin.getLUTIterator();
189 size_t lut = std::distance<>(sparseContainer.data(), lutIter.base());
190 auto incLut = [&lutIter, &lut]() {
191 ++lutIter;
192 ++lut;
193 };
194
195 if (lutIter != end.getLUTIterator()) {
196 // go over first bucket
197 auto bucketRange = gsl::make_span(lutIter->begin().base(), lutIter->end().base());
198 // but start at the bucket position indicated by begin
199 for (size_t bucket = std::distance(bucketRange.data(), begin.getBucketIterator().base()); bucket < bucketRange.size(); ++bucket) {
200 functor(storage_type::joinIndex(lut, bucket), bucketRange.data()[bucket]);
201 }
202
203 // go over all remaining buckets
204 for (incLut(); lutIter != end.getLUTIterator(); incLut()) {
205 // and process each element in each bucket
206 bucketRange = gsl::make_span(*lutIter);
207 for (size_t bucket = 0; bucket < bucketRange.size(); ++bucket) {
208 functor(storage_type::joinIndex(lut, bucket), bucketRange.data()[bucket]);
209 }
210 }
211 }
212 // go over the tail, i.e. the last, possibly incomplete or empty bucket
213 if (end.getBucketIterator() != bucket_iterator{}) {
214 // start at the begining of the last bucket and go till bucket position indicated at "end"
215 // special case if there is only a single, incomplete bucket, we must use the bucket indicated by "begin", otherwise we can use 0
216 size_t bucket = (begin.getLUTIterator() == end.getLUTIterator()) ? std::distance(begin.getLUTIterator()->begin(), begin.getBucketIterator()) : 0;
217 auto bucketRange = gsl::make_span(lutIter->begin().base(), end.getBucketIterator().base());
218 for (; bucket < bucketRange.size(); ++bucket) {
219 functor(storage_type::joinIndex(lut, bucket), bucketRange.data()[bucket]);
220 }
221 }
222};
223
224template <typename container_T, typename IT, class F, std::enable_if_t<isHashContainer_v<container_T>, bool> = true>
225inline void forEachIndexValue(container_T&& container, IT begin, IT end, F functor)
226{
227 using iterator_type = IT;
228
229 std::vector<iterator_type> orderedIterators{};
230 orderedIterators.reserve(container.size());
231 for (auto iter = begin; iter != end; ++iter) {
232 orderedIterators.push_back(iter);
233 };
234
235 std::sort(orderedIterators.begin(), orderedIterators.end(), [](const iterator_type& a, const iterator_type& b) {
236 return a->first < b->first;
237 });
238
239 for (const auto& iter : orderedIterators) {
240 functor(iter->first, iter->second);
241 }
242};
243
244template <typename container_T, typename IT, class F, std::enable_if_t<isSetContainer_v<container_T>, bool> = true>
245inline void forEachIndexValue(container_T&& container, IT begin, IT end, F functor)
246{
247 using container_type = removeCVRef_t<container_T>;
248
249 for (auto iter = begin; iter != end; ++iter) {
250 functor(iter->first, iter->second);
251 }
252}
253
254} // namespace o2::rans::internal::algorithmImpl
255
256#endif /* RANS_INTERNAL_TRANSFORM_ALGORITHMIMPL_H_ */
int32_t i
common helper classes and functions
uint32_t source_type
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLuint end
Definition glcorearb.h:469
GLuint index
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
auto make_span(const o2::rans::internal::simd::AlignedArray< T, width_V, size_V > &array)
void forEachIndexValue(container_T &&container, IT begin, IT end, F functor)
auto trim(IT begin, IT end, typename container_T::const_reference zeroElem) -> std::pair< IT, IT >
typename removeCVRef< T >::type removeCVRef_t
Enum< T >::Iterator begin(Enum< T >)
Definition Defs.h:173