1 #ifdef COMPILATION_INSTRUCTIONS
2 $CXXX $CXXFLAGS $0 -o $0$X&&$0$X&&rm $0$X;exit
3 #endif
4 // © Alfredo A. Correa 2018-2020
5
6 #ifndef MULTI_DETAIL_TYPES_HPP
7 #define MULTI_DETAIL_TYPES_HPP
8
9 //#include "detail.hpp"
10 #include "index_range.hpp"
11
12 #include<tuple> // make_tuple
13 #include<array>
14 #include<cassert>
15 #include<cstddef>
16 #include<type_traits> // make_signed_t
17
18 namespace boost{
19 namespace multi{
20
21 using size_type = std::make_signed_t<std::size_t>;
22
23 using index = std::make_signed_t<size_type>;
24 using difference_type = std::make_signed_t<index>;
25 using index_range = range<index>;
26 using index_extension = extension_t<index>;
27 using dimensionality_type = index;
28
29 using iextension = index_extension;
30 using irange = index_range;
31
32 namespace detail{
33
34 template<typename, typename>
35 struct append_to_type_seq{};
36
37 template<typename T, typename... Ts, template<typename...> class TT>
38 struct append_to_type_seq<T, TT<Ts...>>{
39 using type = TT<Ts..., T>;
40 };
41
42 template<typename T, dimensionality_type N, template<typename...> class TT = std::tuple>
43 struct repeat{
44 using type = typename
45 append_to_type_seq<
46 T,
47 typename repeat<T, N-1, TT>::type
48 >::type;
49 };
50
51 template<typename T, template<typename...> class TT>
52 struct repeat<T, 0, TT>{
53 using type = TT<>;
54 };
55
56 template<class T, std::size_t N>
57 constexpr auto array_size_impl(const std::array<T, N>&)
58 -> std::integral_constant<std::size_t, N>;
59
60 template<class... T>
array_size_impl(const std::tuple<T...> &)61 constexpr auto array_size_impl(const std::tuple<T...>&)
62 -> std::integral_constant<std::size_t, std::tuple_size<std::tuple<T...>>{}>;
63
64 template<class Array>
65 using array_size = decltype(array_size_impl(std::declval<const Array&>()));
66
67 template<class Array>
static_size()68 constexpr auto static_size() -> decltype(array_size<Array>::value){
69 return array_size<Array>::value;
70 }
71 template<class Array>
static_size(Array const &)72 constexpr auto static_size(Array const&) -> decltype(static_size<Array>()){
73 return static_size<Array>();
74 }
75
76 //TODO consolidate with tuple_tail defined somewhere else
77 template<class Tuple>
head(Tuple && t)78 constexpr auto head(Tuple&& t)
79 ->decltype(std::get<0>(std::forward<Tuple>(t))){
80 return std::get<0>(std::forward<Tuple>(t));}
81
82 template<typename Tuple, std::size_t... Ns>
tail_impl(std::index_sequence<Ns...>,Tuple && t)83 constexpr auto tail_impl(std::index_sequence<Ns...> , Tuple&& t){
84 return std::make_tuple(std::get<Ns+1u>(std::forward<Tuple>(t))...);
85 }
86 template<class Tuple>
tail(Tuple const & t)87 constexpr auto tail(Tuple const& t)
88 //->decltype(tail_impl(std::make_index_sequence<(static_size<Tuple>())-1>(), t)){
89 { return tail_impl(std::make_index_sequence<(static_size<Tuple>())-1>(), t);}
90 //->decltype(tail_impl(std::make_index_sequence<(std::tuple_size<Tuple>{})-1>(), t)){
91 // return tail_impl(std::make_index_sequence<(std::tuple_size<Tuple>{})-1>(), t);}
92
93 template<typename T, std::size_t N>
tail(std::array<T,N> const & a)94 constexpr std::array<T, N-1> tail(std::array<T, N> const& a){
95 std::array<T, N-1> ret;
96 std::copy(a.begin() + 1, a.end(), ret.begin());
97 return ret;
98 }
99
100 }
101
102 template<typename T, dimensionality_type D>
103 struct initializer_list{
104 using type = std::initializer_list<typename initializer_list<T, D-1>::type>;
105 };
106 template<typename T>
107 struct initializer_list<T, 1>{using type = std::initializer_list<T>;};
108
109 template<typename T, dimensionality_type D>
110 using initializer_list_t = typename initializer_list<T, D>::type;
111
112 template<dimensionality_type D> using index_extensions = typename detail::repeat<index_extension, D>::type;
113 //template<dimensionality_type D> using iextensions = index_extensions<D>;
114
115 template<dimensionality_type D>
116 struct iextensions : detail::repeat<index_extension, D>::type{
117 using base_ = typename detail::repeat<index_extension, D>::type;
118 static constexpr dimensionality_type dimensionality = D;
119 using base_::base_;
baseboost::multi::iextensions120 constexpr base_ const& base() const{return *this;}
base(iextensions const & s)121 friend constexpr decltype(auto) base(iextensions const& s){return s.base();}
122 private:
123 template <class T, size_t... Is>
iextensionsboost::multi::iextensions124 constexpr iextensions(std::array<T, static_cast<std::size_t>(D)> const& arr, std::index_sequence<Is...>) : iextensions{arr[Is]...}{}
125 };
126
127 #if defined(__cpp_deduction_guides) and __cpp_deduction_guides >= 201703
128 template<class... Args> iextensions(Args...) -> iextensions<sizeof...(Args)>;
129 #endif
130
131 template<dimensionality_type D, class Tuple>
contains(index_extensions<D> const & ie,Tuple const & tp)132 constexpr auto contains(index_extensions<D> const& ie, Tuple const& tp){
133 // using detail::head;
134 // using detail::tail;
135 return contains(head(ie), head(tp)) and contains(tail(ie), tail(tp));
136 }
137
138 }}
139
140 #if defined(__cpp_structured_bindings) and __cpp_structured_bindings>=201606
141 namespace std{ // this is for structured binding
142 template<boost::multi::dimensionality_type D> struct tuple_size<boost::multi::iextensions<D>> : std::integral_constant<size_t, D> { };
143 template<size_t N, boost::multi::dimensionality_type D> struct tuple_element<N, boost::multi::iextensions<D>> : tuple_element<N, typename boost::multi::iextensions<D>::base_>{};
144 }
145 #endif
146
147 #if defined(__INCLUDE_LEVEL__) and not __INCLUDE_LEVEL__
148
149 //#include<range/v3/begin_end.hpp>
150 //#include<range/v3/utility/concepts.hpp>
151
152 #include<cassert>
153 #include<iostream>
154 #include<numeric> // accumulate
155 #include<vector>
156
157
158 using std::cout;
159 namespace multi = boost::multi;
160
161
162 template<class T> T what(T&&) = delete;
163
main()164 int main(){
165
166 multi::index_extension x(10);
167
168 assert( *begin(x) == 0 );
169 assert( size(x) == 10 );
170 assert( x[0] == 0 );
171 assert( x[1] == 1 );
172 assert( x[9] == 9 );
173
174 auto b = begin(x);
175 assert( b[0] == x[0] );
176 assert( b[1] == x[1] );
177
178 // static_assert( ranges::forward_iterator< std::decay_t<decltype(b)> > , "!");
179
180 assert( std::accumulate( begin(x), end(x), 0) == 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 );
181
182 std::iterator_traits<std::decay_t<decltype(begin(x))>>::difference_type d; (void)d;
183 // for(auto i : x) std::cout << i << std::endl;
184
185 {
186 multi::iextensions<3> ies({{0, 3}, {0, 4}, {0, 5}});
187 assert( std::get<1>(ies).size() == 4 );
188 auto [is, js, ks] = ies;
189 assert( is.size() == 3 );
190 }
191
192 }
193
194
195 #endif
196 #endif
197
198