Alexandria  2.16
Please provide a description of the project.
GridIterator.icpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2020 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 <algorithm>
26 #include "ElementsKernel/Exception.h"
27 #include "TemplateLoopCounter.h"
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(
35  const GridContainer<GridCellManager, AxesTypes...>& owner,
36  const cell_manager_iter_type& data_iter)
37  : m_owner(owner), m_data_iter {data_iter} { }
38 
39 template<typename GridCellManager, typename... AxesTypes>
40 template<typename CellType>
41 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator=(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>
49 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::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>
69 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator*() -> CellType& {
70  return *m_data_iter;
71 }
72 
73 template<typename GridCellManager, typename... AxesTypes>
74 template<typename CellType>
75 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator*() const -> typename std::add_const<CellType>::type& {
76  return *m_data_iter;
77 }
78 
79 template<typename GridCellManager, typename... AxesTypes>
80 template<typename CellType>
81 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator->() -> CellType* {
82  return &(*m_data_iter);
83 }
84 
85 template<typename GridCellManager, typename... AxesTypes>
86 template<typename CellType>
87 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator->() const -> typename std::add_const<CellType>::type* {
88  return &(*m_data_iter);
89 }
90 
91 template<typename GridCellManager, typename... AxesTypes>
92 template<typename CellType>
93 bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator==(const iter& other) const {
94  return m_data_iter == other.m_data_iter;
95 }
96 
97 template<typename GridCellManager, typename... AxesTypes>
98 template<typename CellType>
99 bool GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::operator!=(const iter& other) const {
100  return m_data_iter != other.m_data_iter;
101 }
102 
103 template<typename GridCellManager, typename... AxesTypes>
104 template<typename CellType>
105 template<int I>
106 size_t GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::axisIndex() const {
107  size_t index = m_data_iter - GridCellManagerTraits<GridCellManager>::begin(*(m_owner.m_cell_manager));
108  return m_owner.m_index_helper.axisIndex(I, index);
109 }
110 
111 template<typename GridCellManager, typename... AxesTypes>
112 template<typename CellType>
113 template<int I>
114 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::axisValue() const -> const axis_type<I>& {
115  size_t index = axisIndex<I>();
116  return std::get<I>(m_owner.m_axes)[index];
117 }
118 
119 template<typename GridCellManager, typename... AxesTypes>
120 template<typename CellType>
121 template<int I>
122 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::fixAxisByIndex(size_t index) -> iter& {
123  auto fixed_index = m_fixed_indices.find(I);
124  if (fixed_index != m_fixed_indices.end() && fixed_index->second != index) {
125  throw Elements::Exception() << "Axis " <<m_owner.getOriginalAxis<I>().name()
126  << " is already fixed";
127  }
128  if (index >= m_owner.getOriginalAxis<I>().size()) {
129  throw Elements::Exception() << "Index (" << index << ") out of axis "
130  << m_owner.getOriginalAxis<I>().name() << " size ("
131  << m_owner.getOriginalAxis<I>().size() << ")";
132  }
133  m_fixed_indices[I] = index;
134  forwardToIndex(I, index);
135  return *this;
136 }
137 
138 template<typename GridCellManager, typename... AxesTypes>
139 template<typename CellType>
140 template<int I>
141 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::fixAxisByValue(const axis_type<I>& value) -> iter& {
142  auto& axis = m_owner.getOriginalAxis<I>();
143  auto iter = std::find(axis.begin(), axis.end(), value);
144  if (iter == axis.end()) {
145  throw Elements::Exception() << "Failed to fix axis " << m_owner.getOriginalAxis<I>().name()
146  << " (given value not found)";
147  }
148  size_t index = iter - axis.begin();
149  return fixAxisByIndex<I>(index);
150 }
151 
152 template<typename GridCellManager, typename... AxesTypes>
153 template<typename CellType>
154 void GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::forwardToIndex(size_t axis, size_t fixed_index) {
155  size_t current_size = m_data_iter - GridCellManagerTraits<GridCellManager>::begin(*(m_owner.m_cell_manager));
156  size_t current_index = m_owner.m_index_helper.axisIndex(axis, current_size);
157  if (fixed_index != current_index) {
158  size_t axis_factor = m_owner.m_index_helper.m_axes_index_factors[axis];
159  size_t distance = (fixed_index > current_index)
160  ? fixed_index - current_index
161  : m_owner.m_index_helper.m_axes_sizes[axis] + fixed_index - current_index;
162  m_data_iter += distance * axis_factor;
163  }
164 }
165 
166 template<typename IterFrom, typename IterTo, int I>
167 static void fixSameAxes(IterFrom& from, IterTo& to, const TemplateLoopCounter<I>&) {
168  to.template fixAxisByValue<I>(from.template axisValue<I>());
169  fixSameAxes(from, to, TemplateLoopCounter<I-1>{});
170 }
171 
172 template<typename IterFrom, typename IterTo>
173 static void fixSameAxes(IterFrom&, IterTo&, const TemplateLoopCounter<-1>&) {
174 }
175 
176 template<typename GridCellManager, typename... AxesTypes>
177 template<typename CellType>
178 template<typename OtherIter>
179 auto GridContainer<GridCellManager, AxesTypes...>::iter<CellType>::fixAllAxes(const OtherIter& other) -> iter& {
180  fixSameAxes(other, *this, TemplateLoopCounter<sizeof...(AxesTypes)-1>{});
181  return *this;
182 }
183 
184 } // end of GridContainer namespace
185 } // end of namespace Euclid