16 #ifndef OPENKALMAN_SPLIT_HPP 17 #define OPENKALMAN_SPLIT_HPP 27 template<std::size_t
index,
typename Arg,
typename...Ds>
28 constexpr
void check_split_vector_space_descriptor(Arg&& arg, Ds&&...ds)
30 if constexpr ((dynamic_pattern<Ds> or ... or dynamic_dimension<Arg, index>))
32 if (not ((
get_dimension(ds) + ... + std::size_t{0}) <= get_vector_space_descriptor<index>(arg)))
33 throw std::logic_error {
"When concatenated, the vector space descriptors provided to split function are not a " 34 "prefix of the argument's vector space descriptor along at least index " + std::to_string(index)};
38 static_assert(coordinates::compares_with<std::tuple<std::decay_t<Ds>...>, vector_space_descriptor_of_t<Arg, index>, less_equal<>>,
39 "Concatenated vector space descriptors provided to split function must be a prefix of the argument's vector space descriptor");
44 template<std::
size_t index>
45 constexpr
auto split_dummy(std::size_t x) {
return x; };
47 template<std::size_t...indices,
typename Arg,
typename Blocks_tup>
48 auto split_symmetric(Arg&& arg, std::size_t begin, Blocks_tup&& blocks_tup)
50 return std::forward<Blocks_tup>(blocks_tup);
53 template<std::size_t...indices,
typename Arg,
typename Blocks_tup,
typename D,
typename...Ds>
54 auto split_symmetric(Arg&& arg, std::size_t begin, Blocks_tup&& blocks_tup, D&& d, Ds&&...ds)
57 auto begin_tup = std::tuple{split_dummy<indices>(begin)...};
58 auto size_tup = std::tuple{split_dummy<indices>(block_size)...};
59 auto block =
get_slice<indices...>(std::forward<Arg>(arg), begin_tup, size_tup);
60 auto new_blocks_tup = std::tuple_cat(blocks_tup, std::tuple {std::move(block)});
61 return split_symmetric<indices...>(std::forward<Arg>(arg), begin + block_size, std::move(new_blocks_tup), std::forward<Ds>(ds)...);
79 template<std::size_t...indices,
indexible Arg, coordinates::pattern...Ds> requires (
sizeof...(indices) > 0)
81 template<std::size_t...indices,
typename Arg,
typename...Ds, std::enable_if_t<indexible<Arg> and
82 (coordinates::pattern<Ds> and ...) and (
sizeof...(indices) > 0),
int> = 0>
87 (detail::check_split_vector_space_descriptor<indices>(arg, ds...),...);
88 return detail::split_symmetric<indices...>(arg, 0, std::tuple{}, std::forward<Ds>(ds)...);
94 template<std::size_t
index, std::size_t index_ix,
typename Arg,
typename...Ds_tups>
95 constexpr
void check_split_vector_space_descriptor_tup_impl(Arg&& arg, Ds_tups&&...ds_tups)
97 check_split_vector_space_descriptor<index>(arg, std::get<index_ix>(ds_tups)...);
100 template<std::size_t...indices,
typename Arg,
typename...Ds_tups, std::size_t...indices_ix>
101 constexpr
void check_split_vector_space_descriptor_tup(Arg&& arg, std::index_sequence<indices_ix...>, Ds_tups&&...ds_tups)
103 (check_split_vector_space_descriptor_tup_impl<indices, indices_ix>(arg, ds_tups...),...);
107 template<std::size_t...indices,
typename Arg,
typename Begin_tup,
typename Blocks_tup, std::size_t...indices_ix>
108 auto split_impl(Arg&& arg, Begin_tup begin_tup, Blocks_tup&& blocks_tup, std::index_sequence<indices_ix...>)
110 return std::forward<Blocks_tup>(blocks_tup);
113 template<std::size_t...indices,
typename Arg,
typename Begin_tup,
typename Blocks_tup, std::size_t...indices_ix,
114 typename Ds_tup,
typename...Ds_tups>
115 auto split_impl(Arg&& arg, Begin_tup begin_tup, Blocks_tup&& blocks_tup, std::index_sequence<indices_ix...> seq,
116 Ds_tup&& ds_tup, Ds_tups&&...ds_tups)
118 auto size_tup = std::tuple{get_dimension(std::get<indices_ix>(ds_tup))...};
119 auto block =
get_slice<indices...>(std::forward<Arg>(arg), begin_tup, size_tup);
120 auto new_blocks_tup = std::tuple_cat(blocks_tup, std::tuple {std::move(block)});
121 auto new_begin_tup = std::tuple{std::get<indices_ix>(begin_tup) + std::get<indices_ix>(size_tup)...};
122 return split_impl<indices...>(std::forward<Arg>(arg), new_begin_tup, std::move(new_blocks_tup), seq, std::forward<Ds_tups>(ds_tups)...);
140 #ifdef __cpp_concepts 141 template<std::size_t...indices,
indexible Arg,
typename...Ds_tups> requires
142 (
sizeof...(indices) > 0) and (
sizeof...(Ds_tups) > 0) and
145 template<std::size_t...indices,
typename Arg,
typename...Ds_tups, std::enable_if_t<indexible<Arg> and
146 (
sizeof...(indices) > 0) and (
sizeof...(Ds_tups) > 0) and
150 split(Arg&& arg,
const Ds_tups&...ds_tups)
152 std::make_index_sequence<
sizeof...(indices)> seq;
153 detail::check_split_vector_space_descriptor_tup<indices...>(arg, seq, ds_tups...);
155 if constexpr (
sizeof...(indices) == 1)
157 return detail::split_symmetric<indices...>(arg, 0, std::tuple{}, std::get<0>(ds_tups)...);
161 auto init_begin = std::tuple {detail::split_dummy<indices>(0)...};
162 return detail::split_impl<indices...>(arg, init_begin, std::tuple{}, seq, ds_tups...);
169 #endif //OPENKALMAN_SPLIT_HPP decltype(auto) constexpr get_slice(Arg &&arg, const std::tuple< Offset... > &offsets, const std::tuple< Extent... > &extents)
Extract a slice from a matrix or tensor.
Definition: get_slice.hpp:101
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
constexpr auto get_dimension(const Arg &arg)
Get the vector dimension of coordinates::pattern Arg.
Definition: get_dimension.hpp:55
The root namespace for OpenKalman.
Definition: basics.hpp:34
auto split(D &&d)
Split distribution.
Definition: GaussianDistribution.hpp:918
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:75