Alexandria 2.31.0
SDC-CH common library for the Euclid project
Loading...
Searching...
No Matches
GridIterator.icpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2021 Euclid Science Ground Segment
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 3.0 of the License, or (at your option)
7 * any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/**
20 * @file GridContainer/_impl/GridIterator.icpp
21 * @date May 14, 2014
22 * @author Nikolaos Apostolakos
23 */
24
25#include "ElementsKernel/Exception.h"
26#include "TemplateLoopCounter.h"
27#include <algorithm>
28
29namespace Euclid {
30namespace GridContainer {
31
32template <typename GridCellManager, typename... AxesTypes>
33template <typename CellType, typename PointerType, typename ReferenceType>
34GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::iter(
35 const GridContainer<GridCellManager, AxesTypes...>& owner, const cell_manager_iter_type& data_iter)
36 : m_owner(owner), m_data_iter{data_iter} {}
37
38template <typename GridCellManager, typename... AxesTypes>
39template <typename CellType, typename PointerType, typename ReferenceType>
40auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator=(
41 const iter& other) -> iter& {
42 m_data_iter = other.m_data_iter;
43 m_fixed_indices = other.m_fixed_indices;
44 return *this;
45}
46
47template <typename GridCellManager, typename... AxesTypes>
48template <typename CellType, typename PointerType, typename ReferenceType>
49auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator++() -> iter& {
50 ++m_data_iter;
51 if (!m_fixed_indices.empty()) {
52 for (auto& fixed_index_pair : m_fixed_indices) {
53 size_t axis = fixed_index_pair.first;
54 size_t fixed_index = fixed_index_pair.second;
55 forwardToIndex(axis, fixed_index);
56 }
57 // Because we make big steps there is the possibility we went after the end.
58 // In this case we set the iterator to the end.
59 auto end_iter = GridCellManagerTraits<GridCellManager>::end(*(m_owner.m_cell_manager));
60 if (m_data_iter > end_iter) {
61 m_data_iter = end_iter;
62 }
63 }
64 return *this;
65}
66
67template <typename GridCellManager, typename... AxesTypes>
68template <typename CellType, typename PointerType, typename ReferenceType>
69auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator*()
70 -> ReferenceType {
71 return *m_data_iter;
72}
73
74template <typename GridCellManager, typename... AxesTypes>
75template <typename CellType, typename PointerType, typename ReferenceType>
76auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator*() const ->
77 typename std::add_const<ReferenceType>::type {
78 return *m_data_iter;
79}
80
81template <typename GridCellManager, typename... AxesTypes>
82template <typename CellType, typename PointerType, typename ReferenceType>
83auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator->()
84 -> PointerType {
85 return m_data_iter.operator->();
86}
87
88template <typename GridCellManager, typename... AxesTypes>
89template <typename CellType, typename PointerType, typename ReferenceType>
90auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator->() const ->
91 typename std::add_const<PointerType>::type {
92 return m_data_iter.operator->();
93}
94
95template <typename GridCellManager, typename... AxesTypes>
96template <typename CellType, typename PointerType, typename ReferenceType>
97bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator==(
98 const iter& other) const {
99 return m_data_iter == other.m_data_iter;
100}
101
102template <typename GridCellManager, typename... AxesTypes>
103template <typename CellType, typename PointerType, typename ReferenceType>
104bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator!=(
105 const iter& other) const {
106 return m_data_iter != other.m_data_iter;
107}
108
109template <typename GridCellManager, typename... AxesTypes>
110template <typename CellType, typename PointerType, typename ReferenceType>
111template <int I>
112size_t GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::axisIndex() const {
113 size_t index = m_data_iter - GridCellManagerTraits<GridCellManager>::begin(*(m_owner.m_cell_manager));
114 return m_owner.m_index_helper.axisIndex(I, index);
115}
116
117template <typename GridCellManager, typename... AxesTypes>
118template <typename CellType, typename PointerType, typename ReferenceType>
119template <int I>
120auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::axisValue() const
121 -> const axis_type<I>& {
122 size_t index = axisIndex<I>();
123 return std::get<I>(m_owner.m_axes)[index];
124}
125
126template <typename GridCellManager, typename... AxesTypes>
127template <typename CellType, typename PointerType, typename ReferenceType>
128template <int I>
129auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::fixAxisByIndex(
130 size_t index) -> iter& {
131 auto fixed_index = m_fixed_indices.find(I);
132 if (fixed_index != m_fixed_indices.end() && fixed_index->second != index) {
133 throw Elements::Exception() << "Axis " << m_owner.getOriginalAxis<I>().name() << " is already fixed";
134 }
135 if (index >= m_owner.getOriginalAxis<I>().size()) {
136 throw Elements::Exception() << "Index (" << index << ") out of axis " << m_owner.getOriginalAxis<I>().name()
137 << " size (" << m_owner.getOriginalAxis<I>().size() << ")";
138 }
139 m_fixed_indices[I] = index;
140 forwardToIndex(I, index);
141 return *this;
142}
143
144template <typename GridCellManager, typename... AxesTypes>
145template <typename CellType, typename PointerType, typename ReferenceType>
146template <int I>
147auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::fixAxisByValue(
148 const axis_type<I>& value) -> iter& {
149 auto& axis = m_owner.getOriginalAxis<I>();
150 auto found_axis = std::find(axis.begin(), axis.end(), value);
151 if (found_axis == axis.end()) {
152 throw Elements::Exception() << "Failed to fix axis " << m_owner.getOriginalAxis<I>().name()
153 << " (given value not found)";
154 }
155 size_t index = found_axis - axis.begin();
156 return fixAxisByIndex<I>(index);
157}
158
159template <typename GridCellManager, typename... AxesTypes>
160template <typename CellType, typename PointerType, typename ReferenceType>
161void GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::forwardToIndex(
162 size_t axis, size_t fixed_index) {
163 size_t current_size = m_data_iter - GridCellManagerTraits<GridCellManager>::begin(*(m_owner.m_cell_manager));
164 size_t current_index = m_owner.m_index_helper.axisIndex(axis, current_size);
165 if (fixed_index != current_index) {
166 size_t axis_factor = m_owner.m_index_helper.m_axes_index_factors[axis];
167 size_t distance = (fixed_index > current_index)
168 ? fixed_index - current_index
169 : m_owner.m_index_helper.m_axes_sizes[axis] + fixed_index - current_index;
170 m_data_iter += distance * axis_factor;
171 }
172}
173
174template <typename IterFrom, typename IterTo, int I>
175static void fixSameAxes(IterFrom& from, IterTo& to, const TemplateLoopCounter<I>&) {
176 to.template fixAxisByValue<I>(from.template axisValue<I>());
177 fixSameAxes(from, to, TemplateLoopCounter<I - 1>{});
178}
179
180template <typename IterFrom, typename IterTo>
181static void fixSameAxes(IterFrom&, IterTo&, const TemplateLoopCounter<-1>&) {}
182
183template <typename GridCellManager, typename... AxesTypes>
184template <typename CellType, typename PointerType, typename ReferenceType>
185template <typename OtherIter>
186auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::fixAllAxes(
187 const OtherIter& other) -> iter& {
188 fixSameAxes(other, *this, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{});
189 return *this;
190}
191
192} // namespace GridContainer
193} // end of namespace Euclid