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