Alexandria 2.25.0
SDC-CH common library for the Euclid project
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
19/**
20 * @file GridContainer/_impl/GridContainer.icpp
21 * @date May 13, 2014
22 * @author Nikolaos Apostolakos
23 */
24
25#include "ElementsKernel/Exception.h"
26#include "GridConstructionHelper.h"
27
28namespace Euclid {
29namespace GridContainer {
30
31template <typename GridCellManager, typename... AxesTypes>
32GridContainer<GridCellManager, AxesTypes...>::GridContainer(GridAxis<AxesTypes>... axes) : m_axes{std::move(axes)...} {
33 m_cell_manager =
34 GridCellManagerTraits<GridCellManager>::factory(GridConstructionHelper<AxesTypes...>::getAxisIndexFactor(
35 m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}));
36}
37
38template <typename GridCellManager, typename... AxesTypes>
39GridContainer<GridCellManager, AxesTypes...>::GridContainer(std::tuple<GridAxis<AxesTypes>...> axes_tuple)
40 : m_axes{std::move(axes_tuple)} {
41 m_cell_manager =
42 GridCellManagerTraits<GridCellManager>::factory(GridConstructionHelper<AxesTypes...>::getAxisIndexFactor(
43 m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}));
44}
45
46template <typename GridCellManager, typename... AxesTypes>
47template <typename... Args>
48GridContainer<GridCellManager, AxesTypes...>::GridContainer(std::tuple<GridAxis<AxesTypes>...> axes_tuple,
49 Args&&... args)
50 : m_axes{std::move(axes_tuple)} {
51 m_cell_manager = GridCellManagerTraits<GridCellManager>::factory(
52 GridConstructionHelper<AxesTypes...>::getAxisIndexFactor(m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}),
53 std::forward<Args>(args)...);
54}
55
56template <typename... AxesTypes>
57std::tuple<GridAxis<AxesTypes>...> fixAxis(const std::tuple<GridAxis<AxesTypes>...>& original, size_t axis,
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
64template <typename GridCellManager, typename... AxesTypes>
65GridContainer<GridCellManager, AxesTypes...>::GridContainer()
66 : m_cell_manager{
67 GridCellManagerTraits<GridCellManager>::factory(GridConstructionHelper<AxesTypes...>::getAxisIndexFactor(
68 m_axes, TemplateLoopCounter<sizeof...(AxesTypes) - 1>{}))} {}
69
70template <typename GridCellManager, typename... AxesTypes>
71GridContainer<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
84template <typename GridCellManager, typename... AxesTypes>
85template <int I>
86auto GridContainer<GridCellManager, AxesTypes...>::getOriginalAxis() const -> const GridAxis<axis_type<I>>& {
87 return std::get<I>(m_axes);
88}
89
90template <typename GridCellManager, typename... AxesTypes>
91constexpr size_t GridContainer<GridCellManager, AxesTypes...>::axisNumber() {
92 return std::tuple_size<decltype(m_axes_fixed)>::value;
93}
94
95template <typename GridCellManager, typename... AxesTypes>
96template <int I>
97auto GridContainer<GridCellManager, AxesTypes...>::getAxis() const -> const GridAxis<axis_type<I>>& {
98 return std::get<I>(m_axes_fixed);
99}
100
101template <typename GridCellManager, typename... AxesTypes>
102const std::tuple<GridAxis<AxesTypes>...>& GridContainer<GridCellManager, AxesTypes...>::getAxesTuple() const {
103 return m_axes_fixed;
104}
105
106template <typename GridCellManager, typename... AxesTypes>
107auto GridContainer<GridCellManager, AxesTypes...>::begin() -> iterator {
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
113template <typename GridCellManager, typename... AxesTypes>
114auto 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
120template <typename GridCellManager, typename... AxesTypes>
121auto GridContainer<GridCellManager, AxesTypes...>::cbegin() -> const_iterator {
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
127template <typename GridCellManager, typename... AxesTypes>
128auto GridContainer<GridCellManager, AxesTypes...>::end() -> iterator {
129 return iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
130}
131
132template <typename GridCellManager, typename... AxesTypes>
133auto GridContainer<GridCellManager, AxesTypes...>::end() const -> const_iterator {
134 return const_iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
135}
136
137template <typename GridCellManager, typename... AxesTypes>
138auto GridContainer<GridCellManager, AxesTypes...>::cend() -> const_iterator {
139 return const_iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
140}
141
142template <typename GridCellManager, typename... AxesTypes>
143size_t GridContainer<GridCellManager, AxesTypes...>::size() const {
144 return m_index_helper_fixed.m_axes_index_factors.back();
145}
146
147template <typename GridCellManager, typename... AxesTypes>
148auto GridContainer<GridCellManager, AxesTypes...>::operator()(
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
158template <typename GridCellManager, typename... AxesTypes>
159auto GridContainer<GridCellManager, AxesTypes...>::operator()(
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
169template <typename GridCellManager, typename... AxesTypes>
170auto GridContainer<GridCellManager, AxesTypes...>::at(
171 decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) const -> const reference_type {
172 return const_cast<GridContainer*>(this)->at(indices...);
173}
174
175template <typename GridCellManager, typename... AxesTypes>
176auto 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
188template <std::size_t I>
189struct 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
210template <>
211struct InfimumHelper<0> {
212 template <typename>
213 using Index = std::size_t;
214
215 template <typename... AxesType>
216 static std::tuple<std::size_t> getIndex(const std::tuple<AxesType...>& coords,
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
230template <typename GridCellManager, typename... AxesTypes>
231auto 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
236template <typename GridCellManager, typename... AxesTypes>
237auto GridContainer<GridCellManager, AxesTypes...>::infimum(const std::tuple<AxesTypes...>& coords) const
238 -> std::tuple<decltype(std::declval<GridAxis<AxesTypes>>().size())...> {
239 return InfimumHelper<sizeof...(AxesTypes) - 1>::getIndex(coords, m_axes);
240}
241
242template <typename GridCellManager, typename... AxesTypes>
243template <int I>
244GridContainer<GridCellManager, AxesTypes...>
245GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) {
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
253template <typename GridCellManager, typename... AxesTypes>
254template <int I>
255const GridContainer<GridCellManager, AxesTypes...>
256GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) const {
257 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByIndex<I>(index);
258}
259
260template <typename GridCellManager, typename... AxesTypes>
261template <int I>
262GridContainer<GridCellManager, AxesTypes...>
263GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) {
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
272template <typename GridCellManager, typename... AxesTypes>
273template <int I>
274const GridContainer<GridCellManager, AxesTypes...>
275GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) const {
276 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByValue<I>(value);
277}
278
279} // end of namespace GridContainer
280} // end of namespace Euclid