Alexandria  2.25.0
SDC-CH common library for the Euclid project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GridContainer.icpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2022 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 
26 #include "GridConstructionHelper.h"
27 
28 namespace Euclid {
29 namespace GridContainer {
30 
31 template <typename GridCellManager, typename... AxesTypes>
35  m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}));
36 }
37 
38 template <typename GridCellManager, typename... AxesTypes>
40  : m_axes{std::move(axes_tuple)} {
43  m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}));
44 }
45 
46 template <typename GridCellManager, typename... AxesTypes>
47 template <typename... Args>
49  Args&&... args)
50  : m_axes{std::move(axes_tuple)} {
53  std::forward<Args>(args)...);
54 }
55 
56 template <typename... AxesTypes>
58  size_t index) {
59  std::tuple<GridAxis<AxesTypes>...> result{original};
60  GridConstructionHelper<AxesTypes...>::template findAndFixAxis(result, axis, index, TemplateLoopCounter<0>{});
61  return result;
62 }
63 
64 template <typename GridCellManager, typename... AxesTypes>
68  m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}))} {}
69 
70 template <typename GridCellManager, typename... AxesTypes>
71 GridContainer<GridCellManager, AxesTypes...>::GridContainer(const GridContainer<GridCellManager, AxesTypes...>& other,
72  size_t axis, size_t index)
73  : m_axes{other.m_axes}
74  , m_axes_fixed{fixAxis(other.m_axes, axis, index)}
75  , m_fixed_indices{other.m_fixed_indices}
76  , m_cell_manager{other.m_cell_manager} {
77  // Update the fixed indices
78  if (m_fixed_indices.find(axis) != m_fixed_indices.end()) {
79  throw Elements::Exception() << "Axis " << axis << " is already fixed";
80  }
81  m_fixed_indices[axis] = index;
82 }
83 
84 template <typename GridCellManager, typename... AxesTypes>
85 template <int I>
86 auto GridContainer<GridCellManager, AxesTypes...>::getOriginalAxis() const -> const GridAxis<axis_type<I>>& {
87  return std::get<I>(m_axes);
88 }
89 
90 template <typename GridCellManager, typename... AxesTypes>
92  return std::tuple_size<decltype(m_axes_fixed)>::value;
93 }
94 
95 template <typename GridCellManager, typename... AxesTypes>
96 template <int I>
97 auto GridContainer<GridCellManager, AxesTypes...>::getAxis() const -> const GridAxis<axis_type<I>>& {
98  return std::get<I>(m_axes_fixed);
99 }
100 
101 template <typename GridCellManager, typename... AxesTypes>
103  return m_axes_fixed;
104 }
105 
106 template <typename GridCellManager, typename... AxesTypes>
108  iterator result{*this, GridCellManagerTraits<GridCellManager>::begin(*m_cell_manager)};
109  GridConstructionHelper<AxesTypes...>::fixIteratorAxes(result, m_fixed_indices, TemplateLoopCounter<0>{});
110  return result;
111 }
112 
113 template <typename GridCellManager, typename... AxesTypes>
114 auto GridContainer<GridCellManager, AxesTypes...>::begin() const -> const_iterator {
115  const_iterator result{*this, GridCellManagerTraits<GridCellManager>::begin(*m_cell_manager)};
116  GridConstructionHelper<AxesTypes...>::fixIteratorAxes(result, m_fixed_indices, TemplateLoopCounter<0>{});
117  return result;
118 }
119 
120 template <typename GridCellManager, typename... AxesTypes>
122  const_iterator result{*this, GridCellManagerTraits<GridCellManager>::begin(*m_cell_manager)};
123  GridConstructionHelper<AxesTypes...>::fixIteratorAxes(result, m_fixed_indices, TemplateLoopCounter<0>{});
124  return result;
125 }
126 
127 template <typename GridCellManager, typename... AxesTypes>
129  return iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
130 }
131 
132 template <typename GridCellManager, typename... AxesTypes>
133 auto GridContainer<GridCellManager, AxesTypes...>::end() const -> const_iterator {
134  return const_iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
135 }
136 
137 template <typename GridCellManager, typename... AxesTypes>
139  return const_iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
140 }
141 
142 template <typename GridCellManager, typename... AxesTypes>
144  return m_index_helper_fixed.m_axes_index_factors.back();
145 }
146 
147 template <typename GridCellManager, typename... AxesTypes>
149  decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) const -> const reference_type {
150  size_t total_index = m_index_helper.totalIndex(indices...);
151  // If we have fixed axes we need to move the index accordingly
152  for (auto& pair : m_fixed_indices) {
153  total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
154  }
155  return (*m_cell_manager)[total_index];
156 }
157 
158 template <typename GridCellManager, typename... AxesTypes>
160  decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) -> reference_type {
161  size_t total_index = m_index_helper.totalIndex(indices...);
162  // If we have fixed axes we need to move the index accordingly
163  for (auto& pair : m_fixed_indices) {
164  total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
165  }
166  return (*m_cell_manager)[total_index];
167 }
168 
169 template <typename GridCellManager, typename... AxesTypes>
171  decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) const -> const reference_type {
172  return const_cast<GridContainer*>(this)->at(indices...);
173 }
174 
175 template <typename GridCellManager, typename... AxesTypes>
176 auto GridContainer<GridCellManager, AxesTypes...>::at(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices)
177  -> reference_type {
178  // First make a check that all the fixed axes are zero
179  m_index_helper.checkAllFixedAreZero(m_fixed_indices, indices...);
180  size_t total_index = m_index_helper.totalIndexChecked(indices...);
181  // If we have fixed axes we need to move the index accordingly
182  for (auto& pair : m_fixed_indices) {
183  total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
184  }
185  return (*m_cell_manager)[total_index];
186 }
187 
188 template <std::size_t I>
189 struct InfimumHelper {
190  template <typename>
191  using Index = std::size_t;
192 
193  template <typename... AxesType>
194  static std::tuple<Index<AxesType>...> getIndex(const std::tuple<AxesType...>& coords,
195  const std::tuple<GridAxis<AxesType>...>& axes) {
196  std::tuple<Index<AxesType>...> index;
197  getIndex(coords, axes, index);
198  return index;
199  }
200 
201  template <typename IndexTuple, typename... AxesType>
202  static void getIndex(const std::tuple<AxesType...>& coords, const std::tuple<GridAxis<AxesType>...>& axes,
203  IndexTuple& index) {
204  auto& axn = std::get<I>(axes);
205  std::get<I>(index) = axn.infimum(std::get<I>(coords)) - axn.begin();
206  InfimumHelper<I - 1>::getIndex(coords, axes, index);
207  }
208 };
209 
210 template <>
211 struct InfimumHelper<0> {
212  template <typename>
214 
215  template <typename... AxesType>
217  const std::tuple<GridAxis<AxesType>...>& axes) {
218  auto i0 = std::get<0>(axes).infimum(std::get<0>(coords));
219  return std::make_tuple(i0);
220  }
221 
222  template <typename IndexTuple, typename... AxesType>
223  static void getIndex(const std::tuple<AxesType...>& coords, const std::tuple<GridAxis<AxesType>...>& axes,
224  IndexTuple& index) {
225  auto& ax0 = std::get<0>(axes);
226  std::get<0>(index) = ax0.infimum(std::get<0>(coords)) - ax0.begin();
227  }
228 };
229 
230 template <typename GridCellManager, typename... AxesTypes>
231 auto GridContainer<GridCellManager, AxesTypes...>::infimum(const AxesTypes... coordinates) const
232  -> std::tuple<decltype(std::declval<GridAxis<AxesTypes>>().size())...> {
233  return infimum(std::make_tuple(coordinates...));
234 }
235 
236 template <typename GridCellManager, typename... AxesTypes>
239  return InfimumHelper<sizeof...(AxesTypes) - 1>::getIndex(coords, m_axes);
240 }
241 
242 template <typename GridCellManager, typename... AxesTypes>
243 template <int I>
244 GridContainer<GridCellManager, AxesTypes...>
246  if (index >= getOriginalAxis<I>().size()) {
247  throw Elements::Exception() << "Index (" << index << ") out of axis " << getOriginalAxis<I>().name() << " size ("
248  << getOriginalAxis<I>().size() << ")";
249  }
250  return GridContainer<GridCellManager, AxesTypes...>(*this, I, index);
251 }
252 
253 template <typename GridCellManager, typename... AxesTypes>
254 template <int I>
255 const GridContainer<GridCellManager, AxesTypes...>
257  return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByIndex<I>(index);
258 }
259 
260 template <typename GridCellManager, typename... AxesTypes>
261 template <int I>
262 GridContainer<GridCellManager, AxesTypes...>
264  auto& axis = getOriginalAxis<I>();
265  auto found_axis = std::find(axis.begin(), axis.end(), value);
266  if (found_axis == axis.end()) {
267  throw Elements::Exception() << "Failed to fix axis " << getOriginalAxis<I>().name() << " (given value not found)";
268  }
269  return GridContainer<GridCellManager, AxesTypes...>(*this, I, found_axis - axis.begin());
270 }
271 
272 template <typename GridCellManager, typename... AxesTypes>
273 template <int I>
274 const GridContainer<GridCellManager, AxesTypes...>
276  return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByValue<I>(value);
277 }
278 
279 } // end of namespace GridContainer
280 } // end of namespace Euclid
size_t size() const
Returns the total number of cells of the grid.
std::tuple< GridAxis< AxesTypes >...> m_axes
A tuple containing the axes of the grid.
static void getIndex(const std::tuple< AxesType...> &coords, const std::tuple< GridAxis< AxesType >...> &axes, IndexTuple &index)
const reference_type at(decltype(std::declval< GridAxis< AxesTypes >>().size())...indices) const
const_iterator cbegin()
Returns a constant iterator to the first cell of the grid.
const_iterator cend()
Returns a constant iterator to the cell after the last of the grid.
T make_tuple(T...args)
Representation of a multi-dimensional grid which contains axis information.
Definition: GridContainer.h:97
const GridAxis< axis_type< I > > & getOriginalAxis() const
const reference_type operator()(decltype(std::declval< GridAxis< AxesTypes >>().size())...indices) const
static std::unique_ptr< GridCellManager > factory(size_t size)
Provides information related with an axis of a GridContainer.
Definition: GridAxis.h:49
T declval(T...args)
T move(T...args)
T find(T...args)
GridContainer construction helper class.
typename std::tuple_element< I, std::tuple< AxesTypes...>>::type axis_type
static constexpr size_t axisNumber()
Returns the number of axes of the grid (dimensionality)
iterator end()
Returns an iterator to the cell after the last of the grid.
iterator begin()
Returns an iterator to the first cell of the grid.
static std::tuple< std::size_t > getIndex(const std::tuple< AxesType...> &coords, const std::tuple< GridAxis< AxesType >...> &axes)
std::tuple< GridAxis< AxesTypes >...> fixAxis(const std::tuple< GridAxis< AxesTypes >...> &original, size_t axis, size_t index)
const std::tuple< GridAxis< AxesTypes >...> & getAxesTuple() const
Returns a tuple containing the information of all the grid axes.