Alexandria  2.27.0
SDC-CH common library for the Euclid project
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 
29 namespace Euclid {
30 namespace GridContainer {
31 
32 template <typename GridCellManager, typename... AxesTypes>
33 template <typename CellType, typename PointerType, typename ReferenceType>
34 GridContainer<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 
38 template <typename GridCellManager, typename... AxesTypes>
39 template <typename CellType, typename PointerType, typename ReferenceType>
40 auto 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 
47 template <typename GridCellManager, typename... AxesTypes>
48 template <typename CellType, typename PointerType, typename ReferenceType>
49 auto 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 
67 template <typename GridCellManager, typename... AxesTypes>
68 template <typename CellType, typename PointerType, typename ReferenceType>
69 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator*()
70  -> ReferenceType {
71  return *m_data_iter;
72 }
73 
74 template <typename GridCellManager, typename... AxesTypes>
75 template <typename CellType, typename PointerType, typename ReferenceType>
76 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator*() const ->
77  typename std::add_const<ReferenceType>::type {
78  return *m_data_iter;
79 }
80 
81 template <typename GridCellManager, typename... AxesTypes>
82 template <typename CellType, typename PointerType, typename ReferenceType>
83 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator->()
84  -> PointerType {
85  return m_data_iter.operator->();
86 }
87 
88 template <typename GridCellManager, typename... AxesTypes>
89 template <typename CellType, typename PointerType, typename ReferenceType>
90 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator->() const ->
91  typename std::add_const<PointerType>::type {
92  return m_data_iter.operator->();
93 }
94 
95 template <typename GridCellManager, typename... AxesTypes>
96 template <typename CellType, typename PointerType, typename ReferenceType>
97 bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator==(
98  const iter& other) const {
99  return m_data_iter == other.m_data_iter;
100 }
101 
102 template <typename GridCellManager, typename... AxesTypes>
103 template <typename CellType, typename PointerType, typename ReferenceType>
104 bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType, PointerType, ReferenceType>::operator!=(
105  const iter& other) const {
106  return m_data_iter != other.m_data_iter;
107 }
108 
109 template <typename GridCellManager, typename... AxesTypes>
110 template <typename CellType, typename PointerType, typename ReferenceType>
111 template <int I>
112 size_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 
117 template <typename GridCellManager, typename... AxesTypes>
118 template <typename CellType, typename PointerType, typename ReferenceType>
119 template <int I>
120 auto 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 
126 template <typename GridCellManager, typename... AxesTypes>
127 template <typename CellType, typename PointerType, typename ReferenceType>
128 template <int I>
129 auto 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 
144 template <typename GridCellManager, typename... AxesTypes>
145 template <typename CellType, typename PointerType, typename ReferenceType>
146 template <int I>
147 auto 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 
159 template <typename GridCellManager, typename... AxesTypes>
160 template <typename CellType, typename PointerType, typename ReferenceType>
161 void 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 
174 template <typename IterFrom, typename IterTo, int I>
175 static 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 
180 template <typename IterFrom, typename IterTo>
181 static void fixSameAxes(IterFrom&, IterTo&, const TemplateLoopCounter<-1>&) {}
182 
183 template <typename GridCellManager, typename... AxesTypes>
184 template <typename CellType, typename PointerType, typename ReferenceType>
185 template <typename OtherIter>
186 auto 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