Alexandria  2.19
Please provide a description of the 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>
34 GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::iter(const GridContainer<GridCellManager, AxesTypes...>& owner,
35  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>
40 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator=(const iter& other) -> iter& {
41  m_data_iter = other.m_data_iter;
42  m_fixed_indices = other.m_fixed_indices;
43  return *this;
44 }
45 
46 template <typename GridCellManager, typename... AxesTypes>
47 template <typename CellType>
48 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator++() -> iter& {
49  ++m_data_iter;
50  if (!m_fixed_indices.empty()) {
51  for (auto& fixed_index_pair : m_fixed_indices) {
52  size_t axis = fixed_index_pair.first;
53  size_t fixed_index = fixed_index_pair.second;
54  forwardToIndex(axis, fixed_index);
55  }
56  // Because we make big steps there is the possibility we went after the end.
57  // In this case we set the iterator to the end.
58  auto end_iter = GridCellManagerTraits<GridCellManager>::end(*(m_owner.m_cell_manager));
59  if (m_data_iter > end_iter) {
60  m_data_iter = end_iter;
61  }
62  }
63  return *this;
64 }
65 
66 template <typename GridCellManager, typename... AxesTypes>
67 template <typename CellType>
68 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator*() -> CellType& {
69  return *m_data_iter;
70 }
71 
72 template <typename GridCellManager, typename... AxesTypes>
73 template <typename CellType>
74 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator*() const -> typename std::add_const<CellType>::type& {
75  return *m_data_iter;
76 }
77 
78 template <typename GridCellManager, typename... AxesTypes>
79 template <typename CellType>
80 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator->() -> CellType* {
81  return &(*m_data_iter);
82 }
83 
84 template <typename GridCellManager, typename... AxesTypes>
85 template <typename CellType>
86 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator->() const -> typename std::add_const<CellType>::type* {
87  return &(*m_data_iter);
88 }
89 
90 template <typename GridCellManager, typename... AxesTypes>
91 template <typename CellType>
92 bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator==(const iter& other) const {
93  return m_data_iter == other.m_data_iter;
94 }
95 
96 template <typename GridCellManager, typename... AxesTypes>
97 template <typename CellType>
98 bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator!=(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>
104 template <int I>
105 size_t GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::axisIndex() const {
106  size_t index = m_data_iter - GridCellManagerTraits<GridCellManager>::begin(*(m_owner.m_cell_manager));
107  return m_owner.m_index_helper.axisIndex(I, index);
108 }
109 
110 template <typename GridCellManager, typename... AxesTypes>
111 template <typename CellType>
112 template <int I>
113 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::axisValue() const -> const axis_type<I>& {
114  size_t index = axisIndex<I>();
115  return std::get<I>(m_owner.m_axes)[index];
116 }
117 
118 template <typename GridCellManager, typename... AxesTypes>
119 template <typename CellType>
120 template <int I>
121 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::fixAxisByIndex(size_t index) -> iter& {
122  auto fixed_index = m_fixed_indices.find(I);
123  if (fixed_index != m_fixed_indices.end() && fixed_index->second != index) {
124  throw Elements::Exception() << "Axis " << m_owner.getOriginalAxis<I>().name() << " is already fixed";
125  }
126  if (index >= m_owner.getOriginalAxis<I>().size()) {
127  throw Elements::Exception() << "Index (" << index << ") out of axis " << m_owner.getOriginalAxis<I>().name() << " size ("
128  << m_owner.getOriginalAxis<I>().size() << ")";
129  }
130  m_fixed_indices[I] = index;
131  forwardToIndex(I, index);
132  return *this;
133 }
134 
135 template <typename GridCellManager, typename... AxesTypes>
136 template <typename CellType>
137 template <int I>
138 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::fixAxisByValue(const axis_type<I>& value) -> iter& {
139  auto& axis = m_owner.getOriginalAxis<I>();
140  auto found_axis = std::find(axis.begin(), axis.end(), value);
141  if (found_axis == axis.end()) {
142  throw Elements::Exception() << "Failed to fix axis " << m_owner.getOriginalAxis<I>().name() << " (given value not found)";
143  }
144  size_t index = found_axis - axis.begin();
145  return fixAxisByIndex<I>(index);
146 }
147 
148 template <typename GridCellManager, typename... AxesTypes>
149 template <typename CellType>
150 void GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::forwardToIndex(size_t axis, size_t fixed_index) {
151  size_t current_size = m_data_iter - GridCellManagerTraits<GridCellManager>::begin(*(m_owner.m_cell_manager));
152  size_t current_index = m_owner.m_index_helper.axisIndex(axis, current_size);
153  if (fixed_index != current_index) {
154  size_t axis_factor = m_owner.m_index_helper.m_axes_index_factors[axis];
155  size_t distance = (fixed_index > current_index) ? fixed_index - current_index
156  : m_owner.m_index_helper.m_axes_sizes[axis] + fixed_index - current_index;
157  m_data_iter += distance * axis_factor;
158  }
159 }
160 
161 template <typename IterFrom, typename IterTo, int I>
162 static void fixSameAxes(IterFrom& from, IterTo& to, const TemplateLoopCounter<I>&) {
163  to.template fixAxisByValue<I>(from.template axisValue<I>());
164  fixSameAxes(from, to, TemplateLoopCounter<I - 1>{});
165 }
166 
167 template <typename IterFrom, typename IterTo>
168 static void fixSameAxes(IterFrom&, IterTo&, const TemplateLoopCounter<-1>&) {}
169 
170 template <typename GridCellManager, typename... AxesTypes>
171 template <typename CellType>
172 template <typename OtherIter>
173 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::fixAllAxes(const OtherIter& other) -> iter& {
174  fixSameAxes(other, *this, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{});
175  return *this;
176 }
177 
178 } // namespace GridContainer
179 } // end of namespace Euclid