2 * Copyright (C) 2012-2021 Euclid Science Ground Segment
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)
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
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
20 * @file GridContainer/_impl/GridContainer.icpp
22 * @author Nikolaos Apostolakos
25 #include "ElementsKernel/Exception.h"
26 #include "GridConstructionHelper.h"
29 namespace GridContainer {
31 template <typename GridCellManager, typename... AxesTypes>
32 GridContainer<GridCellManager, AxesTypes...>::GridContainer(GridAxis<AxesTypes>... axes) : m_axes{std::move(axes)...} {}
34 template <typename GridCellManager, typename... AxesTypes>
35 GridContainer<GridCellManager, AxesTypes...>::GridContainer(std::tuple<GridAxis<AxesTypes>...> axes_tuple)
36 : m_axes{std::move(axes_tuple)} {}
38 template <typename... AxesTypes>
39 std::tuple<GridAxis<AxesTypes>...> fixAxis(const std::tuple<GridAxis<AxesTypes>...>& original, size_t axis, size_t index) {
40 std::tuple<GridAxis<AxesTypes>...> result{original};
41 GridConstructionHelper<AxesTypes...>::template findAndFixAxis(result, axis, index, TemplateLoopCounter<0>{});
45 template <typename GridCellManager, typename... AxesTypes>
46 GridContainer<GridCellManager, AxesTypes...>::GridContainer(const GridContainer<GridCellManager, AxesTypes...>& other, size_t axis,
48 : m_axes{other.m_axes}
49 , m_axes_fixed{fixAxis(other.m_axes, axis, index)}
50 , m_fixed_indices{other.m_fixed_indices}
51 , m_cell_manager{other.m_cell_manager} {
52 // Update the fixed indices
53 if (m_fixed_indices.find(axis) != m_fixed_indices.end()) {
54 throw Elements::Exception() << "Axis " << axis << " is already fixed";
56 m_fixed_indices[axis] = index;
59 template <typename GridCellManager, typename... AxesTypes>
61 auto GridContainer<GridCellManager, AxesTypes...>::getOriginalAxis() const -> const GridAxis<axis_type<I>>& {
62 return std::get<I>(m_axes);
65 template <typename GridCellManager, typename... AxesTypes>
66 constexpr size_t GridContainer<GridCellManager, AxesTypes...>::axisNumber() {
67 return std::tuple_size<decltype(m_axes_fixed)>::value;
70 template <typename GridCellManager, typename... AxesTypes>
72 auto GridContainer<GridCellManager, AxesTypes...>::getAxis() const -> const GridAxis<axis_type<I>>& {
73 return std::get<I>(m_axes_fixed);
76 template <typename GridCellManager, typename... AxesTypes>
77 const std::tuple<GridAxis<AxesTypes>...>& GridContainer<GridCellManager, AxesTypes...>::getAxesTuple() const {
81 template <typename GridCellManager, typename... AxesTypes>
82 auto GridContainer<GridCellManager, AxesTypes...>::begin() -> iterator {
83 iterator result{*this, GridCellManagerTraits<GridCellManager>::begin(*m_cell_manager)};
84 GridConstructionHelper<AxesTypes...>::fixIteratorAxes(result, m_fixed_indices, TemplateLoopCounter<0>{});
88 template <typename GridCellManager, typename... AxesTypes>
89 auto GridContainer<GridCellManager, AxesTypes...>::begin() const -> const_iterator {
90 const_iterator result{*this, GridCellManagerTraits<GridCellManager>::begin(*m_cell_manager)};
91 GridConstructionHelper<AxesTypes...>::fixIteratorAxes(result, m_fixed_indices, TemplateLoopCounter<0>{});
95 template <typename GridCellManager, typename... AxesTypes>
96 auto GridContainer<GridCellManager, AxesTypes...>::cbegin() -> const_iterator {
97 const_iterator result{*this, GridCellManagerTraits<GridCellManager>::begin(*m_cell_manager)};
98 GridConstructionHelper<AxesTypes...>::fixIteratorAxes(result, m_fixed_indices, TemplateLoopCounter<0>{});
102 template <typename GridCellManager, typename... AxesTypes>
103 auto GridContainer<GridCellManager, AxesTypes...>::end() -> iterator {
104 return iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
107 template <typename GridCellManager, typename... AxesTypes>
108 auto GridContainer<GridCellManager, AxesTypes...>::end() const -> const_iterator {
109 return const_iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
112 template <typename GridCellManager, typename... AxesTypes>
113 auto GridContainer<GridCellManager, AxesTypes...>::cend() -> const_iterator {
114 return const_iterator{*this, GridCellManagerTraits<GridCellManager>::end(*m_cell_manager)};
117 template <typename GridCellManager, typename... AxesTypes>
118 size_t GridContainer<GridCellManager, AxesTypes...>::size() const {
119 return m_index_helper_fixed.m_axes_index_factors.back();
122 template <typename GridCellManager, typename... AxesTypes>
123 auto GridContainer<GridCellManager, AxesTypes...>::operator()(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) const
124 -> const cell_type& {
125 size_t total_index = m_index_helper.totalIndex(indices...);
126 // If we have fixed axes we need to move the index accordingly
127 for (auto& pair : m_fixed_indices) {
128 total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
130 return (*m_cell_manager)[total_index];
133 template <typename GridCellManager, typename... AxesTypes>
134 auto GridContainer<GridCellManager, AxesTypes...>::operator()(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices)
136 return const_cast<cell_type&>(static_cast<const GridContainer&>(*this)(indices...));
139 template <typename GridCellManager, typename... AxesTypes>
140 auto GridContainer<GridCellManager, AxesTypes...>::at(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) const
141 -> const cell_type& {
142 // First make a check that all the fixed axes are zero
143 m_index_helper.checkAllFixedAreZero(m_fixed_indices, indices...);
144 size_t total_index = m_index_helper.totalIndexChecked(indices...);
145 // If we have fixed axes we need to move the index accordingly
146 for (auto& pair : m_fixed_indices) {
147 total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
149 return (*m_cell_manager)[total_index];
152 template <typename GridCellManager, typename... AxesTypes>
153 auto GridContainer<GridCellManager, AxesTypes...>::at(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices)
155 return const_cast<cell_type&>(static_cast<const GridContainer&>(*this).at(indices...));
158 template <std::size_t I>
159 struct InfimumHelper {
161 using Index = std::size_t;
163 template <typename... AxesType>
164 static std::tuple<Index<AxesType>...> getIndex(const std::tuple<AxesType...>& coords,
165 const std::tuple<GridAxis<AxesType>...>& axes) {
166 std::tuple<Index<AxesType>...> index;
167 getIndex(coords, axes, index);
171 template <typename IndexTuple, typename... AxesType>
172 static void getIndex(const std::tuple<AxesType...>& coords, const std::tuple<GridAxis<AxesType>...>& axes,
174 auto& axn = std::get<I>(axes);
175 std::get<I>(index) = axn.infimum(std::get<I>(coords)) - axn.begin();
176 InfimumHelper<I - 1>::getIndex(coords, axes, index);
181 struct InfimumHelper<0> {
183 using Index = std::size_t;
185 template <typename... AxesType>
186 static std::tuple<std::size_t> getIndex(const std::tuple<AxesType...>& coords, const std::tuple<GridAxis<AxesType>...>& axes) {
187 auto i0 = std::get<0>(axes).infimum(std::get<0>(coords));
188 return std::make_tuple(i0);
191 template <typename IndexTuple, typename... AxesType>
192 static void getIndex(const std::tuple<AxesType...>& coords, const std::tuple<GridAxis<AxesType>...>& axes,
194 auto& ax0 = std::get<0>(axes);
195 std::get<0>(index) = ax0.infimum(std::get<0>(coords)) - ax0.begin();
199 template <typename GridCellManager, typename... AxesTypes>
200 auto GridContainer<GridCellManager, AxesTypes...>::infimum(const AxesTypes... coordinates) const
201 -> std::tuple<decltype(std::declval<GridAxis<AxesTypes>>().size())...> {
202 return infimum(std::make_tuple(coordinates...));
205 template <typename GridCellManager, typename... AxesTypes>
206 auto GridContainer<GridCellManager, AxesTypes...>::infimum(const std::tuple<AxesTypes...>& coords) const
207 -> std::tuple<decltype(std::declval<GridAxis<AxesTypes>>().size())...> {
208 return InfimumHelper<sizeof...(AxesTypes) - 1>::getIndex(coords, m_axes);
211 template <typename GridCellManager, typename... AxesTypes>
213 GridContainer<GridCellManager, AxesTypes...> GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) {
214 if (index >= getOriginalAxis<I>().size()) {
215 throw Elements::Exception() << "Index (" << index << ") out of axis " << getOriginalAxis<I>().name() << " size ("
216 << getOriginalAxis<I>().size() << ")";
218 return GridContainer<GridCellManager, AxesTypes...>(*this, I, index);
221 template <typename GridCellManager, typename... AxesTypes>
223 const GridContainer<GridCellManager, AxesTypes...>
224 GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) const {
225 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByIndex<I>(index);
228 template <typename GridCellManager, typename... AxesTypes>
230 GridContainer<GridCellManager, AxesTypes...>
231 GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) {
232 auto& axis = getOriginalAxis<I>();
233 auto found_axis = std::find(axis.begin(), axis.end(), value);
234 if (found_axis == axis.end()) {
235 throw Elements::Exception() << "Failed to fix axis " << getOriginalAxis<I>().name() << " (given value not found)";
237 return GridContainer<GridCellManager, AxesTypes...>(*this, I, found_axis - axis.begin());
240 template <typename GridCellManager, typename... AxesTypes>
242 const GridContainer<GridCellManager, AxesTypes...>
243 GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) const {
244 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByValue<I>(value);
247 } // end of namespace GridContainer
248 } // end of namespace Euclid