36template <
typename... Tags>
37struct PathTagOf<TagPath<Tags...>>
40 using type = std::tuple_element_t<
sizeof...(Tags) - 1, std::tuple<Tags...>>;
45using PathTag =
typename PathTagOf<P>::type;
52inline constexpr bool RunsThroughRepeated =
false;
54template <
typename... Tags>
55inline constexpr bool RunsThroughRepeated<TagPath<Tags...>> = [] {
56 constexpr bool repeated[] = {IsRepeated<Tags>...};
57 for (std::size_t i = 0; i + 1 <
sizeof...(Tags); ++i)
70template <
typename P,
typename Space>
71[[nodiscard]] PathTag<P>
const &
72pathBlock(Space
const & space)
74 return withPathTags<P>([&]<
typename... Tags>() -> PathTag<P>
const & {
75 auto const *
block = locatePath<Tags...>(space).second;
81template <
typename Tag,
typename Space>
82[[nodiscard]] Tag
const &
83findTag(Space
const & space)
85 Tag
const *
block = locate<Tag>(space).second;
93template <
typename Space,
typename Tag,
typename... Rest>
95subspace(Space
const & space)
97 Tag
const & tag = findTag<Tag>(space);
98 if constexpr (
sizeof...(Rest) == 0)
102 else if constexpr (IsRepeated<Tag>)
104 auto inner = subspace<RepeatedBlock<Tag>, Rest...>(tag.block());
105 return Repeated<
decltype(inner), Tag::MaxCount>{std::move(inner), tag.count()};
109 return subspace<Tag, Rest...>(tag);
114template <
typename Space,
typename... Path>
115using SubspaceType =
decltype(subspace<Space, Path...>(std::declval<Space const &>()));
120template <
typename RepeatedTag,
typename... Inner,
typename Space>
122elementSubspace(Space
const & space)
124 static_assert(IsRepeated<RepeatedTag>,
"this takes a repeated block");
125 auto const &
block = findTag<RepeatedTag>(space).block();
126 if constexpr (
sizeof...(Inner) == 0)
132 return subspace<RepeatedBlock<RepeatedTag>, Inner...>(
block);
139template <
typename... Blocks>
141joinBlocks(std::tuple<Blocks...> blocks)
143 if constexpr (
sizeof...(Blocks) == 0)
147 else if constexpr (
sizeof...(Blocks) == 1)
149 return std::get<0>(std::move(blocks));
155 return Composite<Blocks...>{std::move(b)...};
162template <
typename Tag,
typename... Rest,
typename Space>
164blocksWithout(Space
const & space);
169template <
typename Tag,
typename... Rest,
typename Block>
171blockWithout(Block
const &
block)
173 if constexpr (countTag<Tag, Block>() > 0)
175 return blocksWithout<Tag, Rest...>(
block);
179 return std::tuple<Block>{
block};
190template <
typename Tag,
typename... Rest,
typename Space>
192blocksWithout(Space
const & space)
194 if constexpr (std::is_same_v<Tag, Space>)
196 if constexpr (
sizeof...(Rest) == 0)
198 return std::tuple<>{};
200 else if constexpr (IsRepeated<Tag>)
202 auto rest = blocksWithout<Rest...>(space.block());
203 if constexpr (std::tuple_size_v<
decltype(rest)> == 0)
205 return std::tuple<>{};
209 auto block = joinBlocks(std::move(rest));
210 return std::tuple<Repeated<
decltype(
block), Tag::MaxCount>>{
211 Repeated<
decltype(
block), Tag::MaxCount>{std::move(
block), space.count()}
217 return blocksWithout<Rest...>(space);
224 "a path names blocks by tag; derive one, such as struct Heading : RadiansPi<> {}"
226 static_assert(IsComposite<Space>,
"the space does not contain this tag");
227 return [&]<std::size_t... I>(std::index_sequence<I...>) {
228 return std::tuple_cat(blockWithout<Tag, Rest...>(space.template
block<I>())...);
229 }(std::make_index_sequence<std::tuple_size_v<CompositeBlocks<Space>>>{});
236template <
typename... Given,
typename Space>
238complementSubspace(Space
const & space)
240 return joinBlocks(blocksWithout<Given...>(space));
244template <
typename P,
typename Space>
246pathSubspace(Space
const & space)
248 return withPathTags<P>([&]<
typename... Tags>() {
249 return subspace<Space, Tags...>(space);
254template <
typename Space,
typename P>
255using PathSubspaceType =
decltype(pathSubspace<P>(std::declval<Space const &>()));
258template <
typename P,
typename Space>
260pathElementSubspace(Space
const & space)
262 return withPathTags<P>([&]<
typename... Tags>() {
263 return elementSubspace<Tags...>(space);
268template <
typename P,
typename Space>
270pathComplement(Space
const & space)
272 return withPathTags<P>([&]<
typename... Tags>() {
273 return complementSubspace<Tags...>(space);
281template <
typename Block>
282concept IsElementwise = IsRepeated<Block> || (IsUniformLeaf<Block> && Block::ValueDimensionStep != 0);
285template <IsElementwise Block>
286[[nodiscard]] Eigen::Index
287elementCount(Block
const &
block)
289 if constexpr (IsRepeated<Block>)
291 return block.count();
295 return block.valueDimension();
300template <IsElementwise Block>
302setElementCount(Block &
block, Eigen::Index count)
304 if constexpr (IsRepeated<Block>)
306 block.setCount(count);
319 Eigen::Index differenceStart;
320 Eigen::Index differenceCount;
326template <
typename Path,
typename Space>
328locateElementwise(Space & space)
330 auto [offset,
block] = withPathTags<Path>([&]<
typename... Tags>() {
331 return locatePathIn<
false, Tags...>(space);
333 Eigen::Index
const differenceOffset = withPathTags<Path>([&]<
typename... Tags>() {
334 return locatePathIn<
true, Tags...>(space).first;
336 using Block = std::remove_pointer_t<
decltype(
block)>;
338 IsElementwise<Block>,
339 "insert() and erase() take a Repeated block or a resizable Linear or Periodic block"
341 return std::tuple{offset, differenceOffset,
block};
347template <
typename Path,
typename Space>
348[[nodiscard]] ElementRows
349growBlock(Space & space, Eigen::Index element, Eigen::Index rows)
351 auto [offset, differenceOffset,
block] = locateElementwise<Path>(space);
352 using Block = std::remove_pointer_t<
decltype(
block)>;
353 constexpr Eigen::Index elementSize = Block::ValueDimensionStep;
354 constexpr Eigen::Index differenceElementSize = SizedAs<true, Block>::ValueDimensionStep;
355 Eigen::Index
const count = elementCount(*
block);
356 EMRYS_FILTER_ASSERT(element >= 0 && element <= count &&
"insertion point out of range");
357 EMRYS_FILTER_ASSERT(rows % elementSize == 0 &&
"insert whole elements");
358 setElementCount(*
block, count + rows / elementSize);
360 offset + element * elementSize,
362 differenceOffset + element * differenceElementSize,
363 rows / elementSize * differenceElementSize
370template <
typename Path,
typename Space>
371[[nodiscard]] ElementRows
372shrinkBlock(Space & space, Eigen::Index element, Eigen::Index elements)
374 auto [offset, differenceOffset,
block] = locateElementwise<Path>(space);
375 using Block = std::remove_pointer_t<
decltype(
block)>;
376 constexpr Eigen::Index elementSize = Block::ValueDimensionStep;
377 constexpr Eigen::Index differenceElementSize = SizedAs<true, Block>::ValueDimensionStep;
378 Eigen::Index
const count = elementCount(*
block);
379 EMRYS_FILTER_ASSERT(element >= 0 && elements >= 0 && element + elements <= count &&
"erased elements out of range");
380 setElementCount(*
block, count - elements);
382 offset + element * elementSize,
383 elements * elementSize,
384 differenceOffset + element * differenceElementSize,
385 elements * differenceElementSize
390template <
typename Indices>
392asIndexSet(Indices
const & indices)
394 if constexpr (std::is_integral_v<Indices>)
396 return std::array<Eigen::Index, 1>{indices};
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
The macros every header includes first.
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Tag paths and the index utilities (decisions.md [tag-addressing], [index-names]): TagPath and TagPath...
auto block(Space auto const &space, X &&x)
Definition TagPath.h:979