16 #ifndef OPENKALMAN_TILE_HPP 17 #define OPENKALMAN_TILE_HPP 27 template<std::size_t direction,
typename...Index, std::size_t...dims,
typename Arg>
28 constexpr
void tile_impl(std::tuple<Index...>& current_position, std::tuple<Index...>& current_block_size,
29 std::index_sequence<dims...>, Arg& arg) {}
32 template<std::size_t direction,
typename...Index, std::size_t...dims,
typename Arg,
typename Block,
typename...Blocks>
33 constexpr
void tile_impl(std::tuple<Index...>& current_position, std::tuple<Index...>& current_block_size,
34 std::index_sequence<dims...> seq, Arg& arg, Block&& block, Blocks&&...blocks)
37 if constexpr (direction == 0) ((std::get<dims>(current_block_size) = get_index_dimension_of<dims>(block)),...);
39 auto& cur_pos = std::get<direction>(current_position);
40 auto dim_direction = get_index_dimension_of<direction>(arg);
42 if constexpr (direction ==
sizeof...(dims) - 1)
44 set_slice(arg, std::forward<Block>(block), std::get<dims>(current_position)...);
46 if (cur_pos > 0 and ((dims != direction and get_index_dimension_of<dims>(block) != std::get<dims>(current_block_size)) or ...))
47 throw std::length_error {
"Block argument to tile function is not the right tile size."};
49 cur_pos += get_index_dimension_of<direction>(block);
51 if (cur_pos < dim_direction)
53 tile_impl<direction>(current_position, current_block_size, seq, arg, std::forward<Blocks>(blocks)...);
55 else if (cur_pos == dim_direction)
57 constexpr std::size_t new_direction = direction - 1;
59 std::get<new_direction>(current_position) += get_index_dimension_of<new_direction>(block);
60 tile_impl<new_direction>(current_position, current_block_size, seq, arg, std::forward<Blocks>(blocks)...);
64 throw std::length_error {
"Block argument to tile function is too large in dimension " + std::to_string(direction) +
"."};
69 static_assert((direction <
sizeof...(dims) - 1));
70 std::get<direction>(current_block_size) = get_index_dimension_of<direction>(block);
72 if (cur_pos < dim_direction)
74 tile_impl<direction + 1>(current_position, current_block_size, seq, arg, std::forward<Block>(block), std::forward<Blocks>(blocks)...);
78 if constexpr (direction > 0)
80 if (cur_pos > dim_direction)
throw std::length_error {
81 "Block argument to tile function is too large in dimension " + std::to_string(direction) +
"."};
82 constexpr std::size_t new_direction = direction - 1;
84 std::get<new_direction>(current_position) += get_index_dimension_of<new_direction>(block);
85 tile_impl<new_direction>(current_position, current_block_size, seq, arg, std::forward<Block>(block), std::forward<Blocks>(blocks)...);
89 throw std::length_error {
"Tile function has too many blocks to fit within specified vector space descriptors."};
103 #ifdef __cpp_concepts 105 requires (
sizeof...(Ds) >= std::max({index_count_v<Block>, index_count_v<Blocks>...}))
107 template<
typename...Ds,
typename Block,
typename...Blocks, std::enable_if_t<
108 (coordinates::pattern<Ds> and ...) and (
indexible<Block> and ... and
indexible<Blocks>) and
111 constexpr decltype(
auto)
tile(const
std::tuple<Ds...>& ds_tuple, Block&& block, Blocks&&...blocks)
113 if constexpr (
sizeof...(Blocks) == 0)
115 return std::forward<Block>(block);
119 auto m = make_dense_object<Block>(ds_tuple);
120 auto current_position = std::tuple{(coordinates::pattern<Ds> ? std::size_t(0) : std::size_t(-1))...};
121 decltype(current_position) current_block_size;
123 detail::tile_impl<0>(current_position, current_block_size, std::index_sequence_for<Ds...> {}, m, block, blocks...);
131 #endif //OPENKALMAN_TILE_HPP 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
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr Arg && set_slice(Arg &&arg, Block &&block, const Begin &...begin)
Assign an object to a particular slice of a matrix or tensor.
Definition: set_slice.hpp:56