2 * Copyright (C) 2012-2020 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)
33 : m_axes{std::move(axes)...} { }
35 template<typename GridCellManager, typename... AxesTypes>
36 GridContainer<GridCellManager, AxesTypes...>::GridContainer(std::tuple<GridAxis<AxesTypes>...> axes_tuple)
37 : m_axes{std::move(axes_tuple)} { }
39 template<typename... AxesTypes>
40 std::tuple<GridAxis<AxesTypes>...> fixAxis(const std::tuple<GridAxis<AxesTypes>...>& original, size_t axis, size_t index) {
41 std::tuple<GridAxis<AxesTypes>...> result {original};
42 GridConstructionHelper<AxesTypes...>::template findAndFixAxis(result, axis, index, TemplateLoopCounter<0>{});
46 template<typename GridCellManager, typename... AxesTypes>
47 GridContainer<GridCellManager, AxesTypes...>::GridContainer(
48 const GridContainer<GridCellManager, AxesTypes...>& other,
49 size_t axis, size_t index)
50 : m_axes{other.m_axes}, m_axes_fixed{fixAxis(other.m_axes, axis, index)},
51 m_fixed_indices{other.m_fixed_indices}, 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 -> const cell_type& {
124 size_t total_index = m_index_helper.totalIndex(indices...);
125 // If we have fixed axes we need to move the index accordingly
126 for (auto& pair : m_fixed_indices) {
127 total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
129 return (*m_cell_manager)[total_index];
132 template<typename GridCellManager, typename... AxesTypes>
133 auto GridContainer<GridCellManager, AxesTypes...>::operator()(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) -> cell_type& {
134 return const_cast<cell_type&>(static_cast<const GridContainer&>(*this)(indices...));
137 template<typename GridCellManager, typename... AxesTypes>
138 auto GridContainer<GridCellManager, AxesTypes...>::at(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) const -> const cell_type& {
139 // First make a check that all the fixed axes are zero
140 m_index_helper.checkAllFixedAreZero(m_fixed_indices, indices...);
141 size_t total_index = m_index_helper.totalIndexChecked(indices...);
142 // If we have fixed axes we need to move the index accordingly
143 for (auto& pair : m_fixed_indices) {
144 total_index += pair.second * m_index_helper.m_axes_index_factors[pair.first];
146 return (*m_cell_manager)[total_index];
149 template<typename GridCellManager, typename... AxesTypes>
150 auto GridContainer<GridCellManager, AxesTypes...>::at(decltype(std::declval<GridAxis<AxesTypes>>().size())... indices) -> cell_type& {
151 return const_cast<cell_type&>(static_cast<const GridContainer&>(*this).at(indices...));
154 template<typename GridCellManager, typename... AxesTypes>
156 GridContainer<GridCellManager, AxesTypes...> GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) {
157 if (index >= getOriginalAxis<I>().size()) {
158 throw Elements::Exception() << "Index (" << index << ") out of axis "
159 << getOriginalAxis<I>().name() << " size ("
160 << getOriginalAxis<I>().size() << ")";
162 return GridContainer<GridCellManager, AxesTypes...>(*this, I, index);
165 template<typename GridCellManager, typename... AxesTypes>
167 const GridContainer<GridCellManager, AxesTypes...> GridContainer<GridCellManager, AxesTypes...>::fixAxisByIndex(size_t index) const {
168 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByIndex<I>(index);
171 template<typename GridCellManager, typename... AxesTypes>
173 GridContainer<GridCellManager, AxesTypes...> GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) {
174 auto& axis = getOriginalAxis<I>();
175 auto iter = std::find(axis.begin(), axis.end(), value);
176 if (iter == axis.end()) {
177 throw Elements::Exception() << "Failed to fix axis " << getOriginalAxis<I>().name()
178 << " (given value not found)";
180 return GridContainer<GridCellManager, AxesTypes...>(*this, I, iter-axis.begin());
183 template<typename GridCellManager, typename... AxesTypes>
185 const GridContainer<GridCellManager, AxesTypes...> GridContainer<GridCellManager, AxesTypes...>::fixAxisByValue(const axis_type<I>& value) const {
186 return const_cast<GridContainer<GridCellManager, AxesTypes...>*>(this)->fixAxisByValue<I>(value);
189 } // end of namespace GridContainer
190 } // end of namespace Euclid