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>
35 using value_type =
typename std::iterator_traits<IT>::value_type;
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();
41 return {nonZeroBegin, nonZeroEnd};
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>
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;
52 auto isZero = [&zeroElem](
const auto&
i) {
return i == zeroElem; };
59 iterator_type nonZeroBegin = [&]() -> iterator_type {
60 auto lutIter = begin.getLUTIterator();
61 if (lutIter !=
end.getLUTIterator()) {
63 auto nonZeroBegin = std::find_if_not(begin.getBucketIterator(), lutIter->end(), isZero);
64 if (nonZeroBegin != lutIter->end()) {
65 return {begin.getContainer(), lutIter, nonZeroBegin};
69 for (++lutIter; lutIter !=
end.getLUTIterator(); ++lutIter) {
71 auto nonZeroBegin = std::find_if_not(lutIter->begin(), lutIter->end(), isZero);
72 if (nonZeroBegin != lutIter->end()) {
73 return {
begin.getContainer(), lutIter, nonZeroBegin};
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};
89 if (nonZeroBegin ==
end) {
93 iterator_type nonZeroEnd = [&]() -> iterator_type {
94 auto lutIter =
end.getLUTIterator();
96 if (
end.getBucketIterator() != bucket_iterator{}) {
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()};
105 for (; lutIter-- >
begin.getLUTIterator();) {
107 auto nonZeroEnd = std::find_if_not(lutIter->rbegin(), lutIter->rend(), isZero);
108 if (nonZeroEnd != lutIter->rend()) {
109 return {
begin.getContainer(), lutIter, nonZeroEnd.base()};
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()};
123 return {nonZeroBegin, nonZeroEnd};
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>
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>
135 using value_type =
typename std::iterator_traits<IT>::value_type;
137 auto isZero = [&zeroElem](
const value_type& keyValuePair) {
return keyValuePair.second == zeroElem; };
138 auto nonZeroBegin = std::find_if_not(begin,
end, isZero);
141 IT nonZeroEnd = [&]() {
142 if (nonZeroBegin ==
end) {
145 size_t size = std::distance(begin,
end);
147 for (
size_t i =
size;
i-- > 0;) {
148 if ((begin +
i)->second != zeroElem) {
155 return {nonZeroBegin, nonZeroEnd};
158template <
typename container_T,
typename IT,
class F, std::enable_if_t<isDenseContainer_v<container_T>,
bool> = true>
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]);
169template <
typename container_T,
typename IT,
class F, std::enable_if_t<isAdaptiveContainer_v<container_T>,
bool> = true>
174 using source_type =
typename container_type::source_type;
175 using value_type =
typename container_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;
181 auto& sparseContainer = begin.getContainer();
188 auto lutIter = begin.getLUTIterator();
189 size_t lut = std::distance<>(sparseContainer.data(), lutIter.base());
190 auto incLut = [&lutIter, &lut]() {
195 if (lutIter !=
end.getLUTIterator()) {
197 auto bucketRange =
gsl::make_span(lutIter->begin().base(), lutIter->end().base());
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]);
204 for (incLut(); lutIter !=
end.getLUTIterator(); incLut()) {
207 for (
size_t bucket = 0; bucket < bucketRange.size(); ++bucket) {
208 functor(storage_type::joinIndex(lut, bucket), bucketRange.data()[bucket]);
213 if (
end.getBucketIterator() != bucket_iterator{}) {
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]);
224template <
typename container_T,
typename IT,
class F, std::enable_if_t<isHashContainer_v<container_T>,
bool> = true>
227 using iterator_type = IT;
229 std::vector<iterator_type> orderedIterators{};
230 orderedIterators.reserve(container.size());
231 for (
auto iter = begin; iter !=
end; ++iter) {
232 orderedIterators.push_back(iter);
235 std::sort(orderedIterators.begin(), orderedIterators.end(), [](
const iterator_type&
a,
const iterator_type&
b) {
236 return a->first < b->first;
239 for (
const auto& iter : orderedIterators) {
240 functor(iter->first, iter->second);
244template <
typename container_T,
typename IT,
class F, std::enable_if_t<isSetContainer_v<container_T>,
bool> = true>
247 using container_type = removeCVRef_t<container_T>;
249 for (
auto iter = begin; iter !=
end; ++iter) {
250 functor(iter->first, iter->second);