flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
multiindex.hpp
Go to the documentation of this file.
1// ====================================================================
2// This file is part of FlexibleSUSY.
3//
4// FlexibleSUSY is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published
6// by the Free Software Foundation, either version 3 of the License,
7// or (at your option) any later version.
8//
9// FlexibleSUSY is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with FlexibleSUSY. If not, see
16// <http://www.gnu.org/licenses/>.
17// ====================================================================
18
19#ifndef FS_MULTIINDEX_H
20#define FS_MULTIINDEX_H
21
22#include "find_if.hpp"
23
24#include <array>
25#include <iterator>
26
27#include <boost/array.hpp>
28
29#include <boost/mpl/at.hpp>
30#include <boost/mpl/range_c.hpp>
31#include <boost/mpl/size.hpp>
32
33#include <boost/range/iterator_range.hpp>
34
35#include <boost/fusion/adapted/boost_array.hpp>
36#include <boost/fusion/adapted/mpl.hpp>
37#include <boost/fusion/include/copy.hpp>
38
39namespace flexiblesusy
40{
41namespace detail
42{
43template <class End, class Location>
45 template <class Indices>
46 bool operator()(const Indices& indices)
47 {
48 return (indices[Location::value] !=
49 boost::mpl::at<End, Location>::type::value - 1);
50 }
51};
52
53template <class End>
55 template <class Location>
57};
58
59template <class Begin>
61 template <class Location>
62 struct type {
63 template <class Indices>
64 void operator()(Indices& indices)
65 {
66 boost::array<int, std::tuple_size<Indices>::value> boost_temp;
67 boost::fusion::copy(Begin(), boost_temp);
68 std::copy(boost_temp.begin(), boost_temp.begin() + Location::value,
69 indices.begin());
70
71 ++(indices[Location::value]);
72 }
73 };
74};
75
76template <class Begin, class End, bool>
78
79/* FIXME: This copying back and forth
80 using boost::array<> between
81 boost::mpl and std::array<>
82 is stupid...
83 Using boost::hana would be the
84 way to go! */
85template <class Begin, class End>
86class multiindex_impl<Begin, End, false>
87{
88 static constexpr auto NumIndices = boost::mpl::size<Begin>::value;
89 using data_type = std::array<int, NumIndices>;
90
92
93 multiindex_impl(data_type&& d) : data(std::move(d)) {}
94
95public:
97 {
98 boost::array<int, NumIndices> boost_temp;
99 std::array<int, NumIndices> std_temp;
100
101 boost::fusion::copy(Begin(), boost_temp);
102 std::copy(boost_temp.begin(), boost_temp.end(), std_temp.begin());
103
104 return multiindex_impl{std::move(std_temp)};
105 }
106
108 {
109 boost::array<int, NumIndices> boost_temp;
110 std::array<int, NumIndices> std_temp;
111
112 boost::fusion::copy(End(), boost_temp);
113 std::copy(boost_temp.begin(), boost_temp.end(), std_temp.begin());
114
115 return multiindex_impl{std::move(std_temp)};
116 }
117
119 {
120 using locations = boost::mpl::range_c<int, 0, NumIndices>;
121
122 if (meta::find_if<locations,
125 data) == false) {
126 boost::array<int, NumIndices> boost_temp;
127 boost::fusion::copy(End(), boost_temp);
128
129 std::copy(boost_temp.begin(), boost_temp.end(), data.begin());
130 }
131
132 return *this;
133 }
134
136 {
137 multiindex_impl copy(*this);
138 operator++();
139 return copy;
140 }
141
142 const data_type& operator*() const { return data; }
143
144 const data_type* operator->() const { return &data; }
145
146 bool operator==(const multiindex_impl& other) const
147 {
148 return data == other.data;
149 }
150
151 bool operator!=(const multiindex_impl& other) const
152 {
153 return !(*this == other);
154 }
155};
156
157template <class Begin, class End>
158class multiindex_impl<Begin, End, true>
159{
160 using data_type = std::array<int, 0>;
162
164
165 multiindex_impl(bool is_inc) : is_incremented(is_inc) {}
166
167public:
168 static multiindex_impl begin() { return multiindex_impl{false}; }
169
170 static multiindex_impl end() { return multiindex_impl{true}; }
171
173 {
174 is_incremented = true;
175 return *this;
176 }
177
179 {
180 multiindex_impl copy(*this);
181 operator++();
182 return copy;
183 }
184
185 const data_type& operator*() const { return data; }
186
187 const data_type* operator->() const { return &data; }
188
189 bool operator==(const multiindex_impl& other) const
190 {
191 return is_incremented == other.is_incremented;
192 }
193
194 bool operator!=(const multiindex_impl& other) const
195 {
196 return !(*this == other);
197 }
198};
199} // namespace detail
200
201template <class Begin, class End>
203 : public detail::multiindex_impl<Begin, End,
204 std::is_same<Begin, End>::type::value>
205{
206 using impl = detail::multiindex_impl<Begin, End,
207 std::is_same<Begin, End>::type::value>;
208
209 multiindex(impl&& index) : impl(std::move(index)) {}
210
211public:
212 static multiindex begin() { return impl::begin(); }
213
214 static multiindex end() { return impl::end(); }
215};
216} // namespace flexiblesusy
217
218namespace std
219{
220template <class Begin, class End>
221struct iterator_traits<flexiblesusy::multiindex<Begin, End>> {
222 using difference_type = std::ptrdiff_t;
223 using value_type = typename std::decay<decltype(
224 *std::declval<flexiblesusy::multiindex<Begin, End>>())>::type;
225 using pointer = const value_type*;
226 using reference = const value_type&;
227 using iterator_category = std::forward_iterator_tag;
228};
229} // namespace std
230
231namespace flexiblesusy
232{
233namespace meta
234{
235template <class ObjectWithIndexBounds>
237 using type = typename ObjectWithIndexBounds::index_bounds;
238};
239} // namespace meta
240
241template <class ObjectWithIndexBounds>
242static decltype(boost::make_iterator_range(
244 typename meta::index_bounds<
245 ObjectWithIndexBounds>::type::second>::begin(),
250{
251 return boost::make_iterator_range(
255 begin(),
259 end());
260}
261} // namespace flexiblesusy
262
263#endif
bool operator!=(const multiindex_impl &other) const
Definition: multiindex.hpp:151
bool operator==(const multiindex_impl &other) const
Definition: multiindex.hpp:146
bool operator==(const multiindex_impl &other) const
Definition: multiindex.hpp:189
bool operator!=(const multiindex_impl &other) const
Definition: multiindex.hpp:194
static multiindex end()
Definition: multiindex.hpp:214
static multiindex begin()
Definition: multiindex.hpp:212
multiindex(impl &&index)
Definition: multiindex.hpp:209
bool find_if(State &&state)
Definition: find_if.hpp:61
static decltype(boost::make_iterator_range(multiindex< typename meta::index_bounds< ObjectWithIndexBounds >::type::first, typename meta::index_bounds< ObjectWithIndexBounds >::type::second >::begin(), multiindex< typename meta::index_bounds< ObjectWithIndexBounds >::type::first, typename meta::index_bounds< ObjectWithIndexBounds >::type::second >::end())) index_range()
Definition: multiindex.hpp:249
double * end(GSL_vector &v)
iterator to end of GSL_vector
Definition: gsl_vector.cpp:254
double * begin(GSL_vector &v)
iterator to begin of GSL_vector
Definition: gsl_vector.cpp:245
data
Definition: scan_HSSUSY.m:46
bool operator()(const Indices &indices)
Definition: multiindex.hpp:46
typename ObjectWithIndexBounds::index_bounds type
Definition: multiindex.hpp:237
typename std::decay< decltype(*std::declval< flexiblesusy::multiindex< Begin, End > >())>::type value_type
Definition: multiindex.hpp:224