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 <typename GridCellManager, typename... AxesTypes>
160 GridContainer<GridCellManager, AxesTypes...> GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) {
161 if (index >= getOriginalAxis<I>().size()) {
162 throw Elements::Exception() << "Index (" << index << ") out of axis " << getOriginalAxis<I>().name() << " size ("
163 << getOriginalAxis<I>().size() << ")";
165 return GridContainer<GridCellManager, AxesTypes...>(*this, I, index);
168 template <typename GridCellManager, typename... AxesTypes>
170 const GridContainer<GridCellManager, AxesTypes...>
171 GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) const {
172 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByIndex<I>(index);
175 template <typename GridCellManager, typename... AxesTypes>
177 GridContainer<GridCellManager, AxesTypes...>
178 GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) {
179 auto& axis = getOriginalAxis<I>();
180 auto found_axis = std::find(axis.begin(), axis.end(), value);
181 if (found_axis == axis.end()) {
182 throw Elements::Exception() << "Failed to fix axis " << getOriginalAxis<I>().name() << " (given value not found)";
184 return GridContainer<GridCellManager, AxesTypes...>(*this, I, found_axis - axis.begin());
187 template <typename GridCellManager, typename... AxesTypes>
189 const GridContainer<GridCellManager, AxesTypes...>
190 GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) const {
191 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByValue<I>(value);
194 } // end of namespace GridContainer
195 } // end of namespace Euclid