File indexing completed on 2025-01-18 09:43:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP
0013 #define BOOST_UBLAS_TENSOR_MULTI_INDEX_UTILITY_HPP
0014
0015
0016 #include <tuple>
0017 #include <type_traits>
0018
0019
0020 namespace boost {
0021 namespace numeric {
0022 namespace ublas {
0023 namespace detail {
0024
0025
0026 template<class ... index_types>
0027 struct has_index_impl;
0028
0029 template<class itype_left, class itype_right>
0030 struct has_index_impl<itype_left, itype_right>
0031 {
0032 static constexpr bool value = itype_left::value == itype_right::value;
0033 };
0034
0035 template<class itype_left>
0036 struct has_index_impl <itype_left, std::tuple<> >
0037 {
0038 static constexpr bool value = false;
0039 };
0040
0041 template<class itype_left, class itype_right>
0042 struct has_index_impl <itype_left, std::tuple<itype_right> >
0043 {
0044 static constexpr bool value = has_index_impl<itype_left,itype_right>::value;
0045 };
0046
0047 template<class itype_left, class itype_right, class ... index_types>
0048 struct has_index_impl <itype_left, std::tuple<itype_right, index_types...> >
0049 {
0050 using next_type = has_index_impl<itype_left, std::tuple<index_types...>>;
0051 static constexpr bool value = has_index_impl<itype_left,itype_right>::value || next_type::value;
0052 };
0053 }
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 template<class index_type, class tuple_type>
0067 struct has_index
0068 {
0069 static constexpr bool value = detail::has_index_impl<std::decay_t<index_type>,std::decay_t<tuple_type>>::value;
0070 };
0071
0072 }
0073 }
0074 }
0075
0076
0077
0078
0079 namespace boost {
0080 namespace numeric {
0081 namespace ublas {
0082 namespace detail {
0083
0084
0085 template<class ... index_types>
0086 struct valid_multi_index_impl;
0087
0088 template<>
0089 struct valid_multi_index_impl<std::tuple<>>
0090 {
0091 static constexpr bool value = true;
0092 };
0093
0094 template<class itype>
0095 struct valid_multi_index_impl<std::tuple<itype>>
0096 {
0097 static constexpr bool value = true;
0098 };
0099
0100
0101 template<class itype, class ... index_types>
0102 struct valid_multi_index_impl<std::tuple<itype,index_types...>>
0103 {
0104 using ttype = std::tuple<index_types...>;
0105 using has_index_type = has_index<itype, ttype>;
0106
0107 static constexpr bool is_index_zero = itype::value==0ul;
0108 static constexpr bool has_index_value = has_index_type::value && !is_index_zero;
0109 static constexpr bool value = !has_index_value && valid_multi_index_impl<ttype>::value;
0110 };
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 template<class tupe_type>
0123 struct valid_multi_index
0124 {
0125 static constexpr bool value = detail::valid_multi_index_impl<std::decay_t<tupe_type>>::value;
0126 };
0127
0128 }
0129 }
0130 }
0131
0132
0133
0134
0135 namespace boost {
0136 namespace numeric {
0137 namespace ublas {
0138 namespace detail {
0139
0140 template<class ... index_types >
0141 struct number_equal_indexes_impl;
0142
0143 template<class ... itypes_right >
0144 struct number_equal_indexes_impl < std::tuple<>, std::tuple<itypes_right...>>
0145 {
0146 static constexpr unsigned value = 0;
0147 };
0148
0149 template<class itype, class ... itypes_left, class ... itypes_right>
0150 struct number_equal_indexes_impl < std::tuple<itype,itypes_left...>, std::tuple<itypes_right...>>
0151 {
0152 using tuple_right = std::tuple<itypes_right...>;
0153 using has_index_type = has_index<itype, tuple_right>;
0154
0155 static constexpr bool is_index_zero = itype::value==0ul;
0156 static constexpr bool has_index_value = has_index_type::value && !is_index_zero;
0157
0158 using next_type = number_equal_indexes_impl< std::tuple<itypes_left...>, tuple_right >;
0159 static constexpr unsigned v = has_index_value ? 1 : 0;
0160 static constexpr unsigned value = v + next_type::value;
0161 };
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 template<class tuple_left, class tuple_right>
0179 struct number_equal_indexes
0180 {
0181 static constexpr unsigned value =
0182 detail::number_equal_indexes_impl< std::decay_t<tuple_left>, std::decay_t<tuple_right>>::value;
0183 };
0184
0185 }
0186 }
0187 }
0188
0189
0190
0191
0192
0193 namespace boost {
0194 namespace numeric {
0195 namespace ublas {
0196 namespace detail {
0197
0198
0199 template<std::size_t r, std::size_t m, class itype, class ttype>
0200 struct index_position_impl
0201 {
0202 static constexpr auto is_same = std::is_same< std::decay_t<itype>, std::decay_t<std::tuple_element_t<r,ttype>> >::value;
0203 static constexpr auto value = is_same ? r : index_position_impl<r+1,m,itype,ttype>::value;
0204 };
0205
0206
0207
0208 template<std::size_t m, class itype, class ttype>
0209 struct index_position_impl < m, m, itype, ttype>
0210 {
0211 static constexpr auto value = std::tuple_size<ttype>::value;
0212 };
0213
0214 }
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 template<class index_type, class tuple_type>
0233 struct index_position
0234 {
0235 static constexpr auto value = detail::index_position_impl<0ul,std::tuple_size<tuple_type>::value,std::decay_t<index_type>,std::decay_t<tuple_type>>::value;
0236 };
0237
0238 }
0239 }
0240 }
0241
0242
0243
0244
0245
0246 namespace boost {
0247 namespace numeric {
0248 namespace ublas {
0249 namespace detail {
0250
0251 template<std::size_t r, std::size_t m>
0252 struct index_position_pairs_impl
0253 {
0254 template<class array_type, class tuple_left, class tuple_right>
0255 static constexpr void run(array_type& out, tuple_left const& lhs, tuple_right const& rhs, std::size_t p)
0256 {
0257 using index_type = std::tuple_element_t<r-1,tuple_left>;
0258 using has_index_type = has_index<index_type, tuple_right>;
0259 using get_index_type = index_position<index_type,tuple_right>;
0260 using next_type = index_position_pairs_impl<r+1,m>;
0261 if constexpr ( has_index_type::value && index_type::value != 0)
0262 out[p++] = std::make_pair(r-1,get_index_type::value);
0263 next_type::run( out, lhs, rhs, p );
0264 }
0265 };
0266
0267 template<std::size_t m>
0268 struct index_position_pairs_impl<m,m>
0269 {
0270 template<class array_type, class tuple_left, class tuple_right>
0271 static constexpr void run(array_type& out, tuple_left const& , tuple_right const& , std::size_t p)
0272 {
0273 using index_type = std::tuple_element_t<m-1,tuple_left>;
0274 using has_index_type = has_index<index_type, tuple_right>;
0275 using get_index_type = index_position<index_type, tuple_right>;
0276 if constexpr ( has_index_type::value && index_type::value != 0 )
0277 out[p] = std::make_pair(m-1,get_index_type::value);
0278 }
0279 };
0280
0281 template<std::size_t r>
0282 struct index_position_pairs_impl<r,0>
0283 {
0284 template<class array_type, class tuple_left, class tuple_right>
0285 static constexpr void run(array_type&, tuple_left const& , tuple_right const& , std::size_t)
0286 {}
0287 };
0288
0289
0290 }
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 template<class tuple_left, class tuple_right>
0306 auto index_position_pairs(tuple_left const& lhs, tuple_right const& rhs)
0307 {
0308 using pair_type = std::pair<std::size_t,std::size_t>;
0309 constexpr auto m = std::tuple_size<tuple_left >::value;
0310 constexpr auto p = number_equal_indexes<tuple_left, tuple_right>::value;
0311 auto array = std::array<pair_type,p>{};
0312 detail::index_position_pairs_impl<1,m>::run(array, lhs, rhs,0);
0313 return array;
0314 }
0315
0316 }
0317 }
0318 }
0319
0320
0321
0322
0323
0324
0325
0326 namespace boost {
0327 namespace numeric {
0328 namespace ublas {
0329 namespace detail {
0330
0331 template<class array_type, std::size_t ... R>
0332 constexpr auto array_to_vector_impl( array_type const& array, std::index_sequence<R...> )
0333 {
0334 return std::make_pair(
0335 std::vector<std::size_t>{std::get<0>( std::get<R>(array) )+1 ...} ,
0336 std::vector<std::size_t>{std::get<1>( std::get<R>(array) )+1 ...} );
0337 }
0338
0339 }
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 template<class pair_type, std::size_t N>
0352 constexpr auto array_to_vector( std::array<pair_type,N> const& array)
0353 {
0354 constexpr auto sequence = std::make_index_sequence<N>{};
0355 return detail::array_to_vector_impl( array, sequence );
0356 }
0357
0358
0359 }
0360 }
0361 }
0362
0363
0364 #endif