16 #ifndef OPENKALMAN_CONCATENATE_HPP 17 #define OPENKALMAN_CONCATENATE_HPP 24 template<
typename T,
typename U, std::size_t...indices, std::size_t...I>
27 return (([](std::size_t i){
return ((i != indices) and ...); }(I) or
32 template<
typename T,
typename U, std::size_t...indices>
34 concept concatenate_dimensions_match =
36 constexpr
bool concatenate_dimensions_match =
38 (concatenate_dimensions_match_impl<T, U, indices...>(std::make_index_sequence<index_count_v<T>> {}));
41 template<std::size_t I, std::size_t...indices,
typename DTup,
typename...DTups>
42 constexpr decltype(
auto) concatenate_vector_space_descriptor_impl(DTup&& d_tup, DTups&&...d_tups)
44 if constexpr (((I == indices) or ...))
46 auto f = [](
auto&& dtup){
48 else return std::get<I>(std::forward<decltype(dtup)>(dtup));
50 return (f(std::forward<DTup>(d_tup)) + ... + f(std::forward<DTups>(d_tups)));
54 if constexpr (not (
compares_with<collections::collection_element_t<I, DTup>, collections::collection_element_t<I, DTups>>and ...))
56 if (((std::get<I>(std::forward<DTup>(d_tup)) != std::get<I>(std::forward<DTups>(d_tups))) or ...))
57 throw std::invalid_argument {
"Arguments to concatenate do not match in at least index " + std::to_string(I)};
59 return std::get<I>(std::forward<DTup>(d_tup));
64 template<std::size_t...indices, std::size_t...I,
typename...DTups>
65 constexpr decltype(
auto) concatenate_vector_space_descriptor(
std::index_sequence<I...>, DTups&&...d_tups)
67 return std::tuple {concatenate_vector_space_descriptor_impl<I, indices...>(std::forward<DTups>(d_tups)...)...};
72 template<
typename T,
typename...Ts>
73 concept constant_concatenate_arguments =
74 (values::fixed<constant_value<T>> and ... and values::fixed<constant_value<Ts>>) and
77 template<
typename T,
typename = void,
typename...Ts>
80 template<
typename T,
typename...Ts>
82 std::enable_if_t<(values::internal::near(constant_value<T>::value, constant_value<Ts>::value) and ...)>, Ts...>
85 template<
typename T,
typename...Ts>
90 template<std::size_t
index, std::size_t...indices,
typename Args_tup, std::size_t...all_indices, std::size_t...pos>
93 constexpr
auto p_index = std::get<index>(std::tuple{pos...});
94 if constexpr (((p_index == std::get<indices>(std::tuple{pos...})) and ...))
96 return std::get<p_index>(args_tup);
101 return make_zero<Pattern>(get_pattern_collection<all_indices>(std::get<pos>(args_tup))...);
106 template<std::size_t...indices,
typename Ds_tup,
typename Args_tup, std::size_t...all_indices,
typename...Pos_seq>
109 return tile(ds_tup, concatenate_diag_impl<indices...>(std::forward<Args_tup>(args_tup), all_indices_seq, pos_seq)...);
114 template<std::size_t...args_ix, std::size_t...pos>
115 constexpr
auto get_cat_indices(
121 return std::tuple {pos_seq};
126 template<std::size_t ix, std::size_t...ixs, std::size_t...args_ix, std::size_t...pos>
127 constexpr
auto get_cat_indices(
133 return get_cat_indices(
142 template<std::size_t ix, std::size_t...ixs, std::size_t
index, std::size_t...indices, std::size_t...args_ix, std::size_t...pos>
143 constexpr
auto get_cat_indices(
149 if constexpr (ix == index)
151 static_assert (((index != indices) and ...),
"No duplicate indices for concatenate function.");
152 return std::tuple_cat(get_cat_indices(
158 else if constexpr (((ix == indices) or ...))
160 return get_cat_indices(
168 return get_cat_indices(
190 #ifdef __cpp_concepts 191 template<std::size_t...indices,
indexible Arg, detail::concatenate_dimensions_match<Arg>...Args>
192 requires (
sizeof...(indices) > 0)
194 template<std::size_t...indices,
typename Arg,
typename...Args, std::enable_if_t<(
sizeof...(indices) > 0) and
195 (indexible<Arg> and ... and detail::concatenate_dimensions_match<Arg, Args>),
int> = 0>
197 constexpr decltype(
auto)
198 concatenate(Arg&& arg, Args&&...args)
200 auto seq = std::make_index_sequence<std::max({index_count_v<Arg>, index_count_v<Args>..., indices...})> {};
201 auto d_tup = detail::concatenate_vector_space_descriptor<indices...>(
202 seq, all_vector_space_descriptors(arg), all_vector_space_descriptors(args)...);
204 if constexpr (
sizeof...(Args) == 0)
206 return std::forward<Arg>(arg);
208 else if constexpr ((zero<Arg> and ... and zero<Args>))
210 return std::apply([](
auto&&...ds){
return make_zero<Arg>(std::forward<decltype(ds)>(ds)...); }, d_tup);
212 else if constexpr (
sizeof...(indices) == 1 and detail::constant_concatenate_arguments<Arg, Args...>)
215 return make_constant<Arg>(constant_value<Arg>{}, std::forward<decltype(ds)>(ds)...);
218 else if constexpr (
sizeof...(indices) == 2 and ((indices == 0) or ...) and ((indices == 1) or ...) and
219 (diagonal_matrix<Args> and ...))
223 else if constexpr (
sizeof...(indices) == 2 and ((indices == 0) or ...) and ((indices == 1) or ...) and
224 (triangle_type_of_v<Arg, Args...> !=
triangle_type::any) and (square_shaped<Arg> and ... and square_shaped<Args>))
226 return make_triangular_matrix<triangle_type_of_v<Arg>>(
229 else if constexpr (
sizeof...(indices) == 2 and ((indices == 0) or ...) and ((indices == 1) or ...) and
230 (hermitian_matrix<Arg> and ... and hermitian_matrix<Args>))
232 constexpr
auto t = hermitian_adapter_type_of_v<Arg>;
233 auto maybe_transpose = [](
auto&& m) {
234 using M = decltype(m);
235 if constexpr(t == hermitian_adapter_type_of_v<M>)
return nested_object(std::forward<M>(m));
238 return make_hermitian_matrix<t>(
241 else if constexpr (
sizeof...(indices) == 1)
243 return tile(d_tup, std::forward<Arg>(arg), std::forward<Args>(args)...);
251 return detail::concatenate_diag<indices...>(d_tup,
252 std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...), seq, pos_seq...);
decltype(auto) constexpr tile(const std::tuple< Ds... > &ds_tuple, Block &&block, Blocks &&...blocks)
Create a matrix or tensor by tiling individual blocks.
Definition: tile.hpp:111
The concept, trait, or restraint is permitted, but whether it applies is not necessarily known at com...
constexpr bool indexible
T is a multidimensional array type.
Definition: indexible.hpp:32
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
decltype(auto) constexpr to_diagonal(Arg &&arg)
Convert an indexible object into a diagonal matrix.
Definition: to_diagonal.hpp:33
decltype(auto) constexpr apply(F &&f, T &&t)
A generalization of std::apply.
Definition: apply.hpp:49
Lower, upper, or diagonal matrix.
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr bool dimension_size_of_index_is
Specifies that a given index of T has a specified size.
Definition: dimension_size_of_index_is.hpp:35
constexpr auto near(const Arg1 &arg1, const Arg2 &arg2)
Determine whether two numbers are within a rounding tolerance.
Definition: near.hpp:46
decltype(auto) constexpr transpose(Arg &&arg)
Swap any two indices of an indexible_object.
Definition: transpose.hpp:163
decltype(auto) constexpr diagonal_of(Arg &&arg)
Extract a column vector (or column slice for rank>2 tensors) comprising the diagonal elements...
Definition: diagonal_of.hpp:36
Dimensions< 1 > Axis
Alias for a 1D Euclidean coordinates::pattern object.
Definition: Dimensions.hpp:171
Definition: trait_backports.hpp:64
typename collection_element< i, T >::type collection_element_t
Helper template for collection_element.
Definition: collection_element.hpp:116
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:35
decltype(auto) constexpr concatenate_diagonal(V &&v, Vs &&... vs)
Concatenate one or more typed matrices diagonally.
Definition: typed-matrix-overloads.hpp:340
constexpr bool compares_with
Compares two coordinates::pattern objects.
Definition: compares_with.hpp:475
Definition: concatenate.hpp:78
constexpr std::size_t size_of_v
Helper for collections::size_of.
Definition: size_of.hpp:60
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:77