30template <
typename Part>
31using StoredPart = std::conditional_t<std::is_empty_v<Part>, std::tuple<>, std::tuple<Part>>;
34template <
typename Stored>
41 operator==(StoredParts
const &, StoredParts
const &) =
default;
46struct StoredParts<std::tuple<>>
48 StoredParts() =
default;
51 constexpr explicit StoredParts(std::tuple<>) {}
55 operator==(StoredParts
const &, StoredParts
const &) =
default;
64template <
typename... Parts>
65class PartStorage :
private StoredParts<decltype(std::tuple_cat(std::declval<StoredPart<Parts>>()...))>
68 using Stored =
decltype(std::tuple_cat(std::declval<StoredPart<Parts>>()...));
71 using Base = StoredParts<Stored>;
74 template <std::
size_t I>
75 using Part = std::tuple_element_t<I, std::tuple<Parts...>>;
78 static consteval std::size_t
79 storedIndex(std::size_t i)
81 constexpr auto empty = std::array<bool,
sizeof...(Parts)>{std::is_empty_v<Parts>...};
82 std::size_t result = 0;
83 for (std::size_t j = 0; j < i; ++j)
85 result += empty[j] ? 0 : 1;
92 static constexpr StoredPart<P>
95 if constexpr (std::is_empty_v<P>)
101 return StoredPart<P>{std::move(part)};
106 template <std::
size_t I>
107 static inline Part<I> instance{};
111 PartStorage() =
default;
114 constexpr explicit PartStorage(Parts... parts)
115 : Base{std::tuple_cat(keep(parts)...)}
119 template <std::
size_t I>
120 [[nodiscard]]
constexpr Part<I>
const &
123 if constexpr (std::is_empty_v<Part<I>>)
129 return std::get<storedIndex(I)>(Base::parts);
134 template <std::
size_t I>
135 [[nodiscard]] Part<I> &
138 if constexpr (std::is_empty_v<Part<I>>)
144 return std::get<storedIndex(I)>(Base::parts);
150 operator==(PartStorage
const &, PartStorage
const &) =
default;
168template <
Space... Blocks>
169class Composite :
private internal::PartStorage<Blocks...>
172 using Storage = internal::PartStorage<Blocks...>;
174 static_assert(
sizeof...(Blocks) > 0,
"a composite needs at least one block");
175 static constexpr std::size_t BlockCount =
sizeof...(Blocks);
176 static constexpr std::array<bool, BlockCount> Resizable{
177 (Blocks::ValueDimensionStep != 0)...
187 ((result = std::gcd(result, Blocks::ValueDimensionStep)), ...);
192 static consteval std::size_t
195 for (std::size_t i = 0; i < BlockCount; ++i)
208 (Blocks::FixedValueDimension + ...);
217 ((Blocks::MaxValueDimension == Eigen::Dynamic) || ...) ? Eigen::Dynamic : (Blocks::MaxValueDimension + ...);
219 Composite() =
default;
223 : Storage{std::move(blocks)...}
227 template <std::
size_t I>
228 [[nodiscard]]
auto const &
231 return Storage::template part<I>();
235 template <std::
size_t I>
239 return Storage::template part<I>();
243 [[nodiscard]] Eigen::Index
250 template <std::
size_t I>
251 [[nodiscard]] Eigen::Index
254 return [&]<std::size_t... J>(std::index_sequence<J...>) {
255 return (Eigen::Index{0} + ... +
block<J>().valueDimension());
256 }(std::make_index_sequence<I>{});
264 requires((internal::resizableBlockCount<Blocks> + ...) == 1)
267 Eigen::Index
const rest =
valueDimension() - resizable.valueDimension();
268 EMRYS_FILTER_ASSERT(n >= rest &&
"the dimension does not fit the space");
269 resizable.resize(n - rest);
273 template <
typename Derived>
275 normalize(Eigen::MatrixBase<Derived>
const & rows)
const
276 requires((internal::HasNormalize<Blocks> || ...))
278 forEachBlock(rows, [](
auto const &
block,
auto && sub) {
286 template <
typename X,
typename D,
typename Out>
288 plus(Eigen::MatrixBase<X>
const & x, Eigen::MatrixBase<D>
const & d, Eigen::MatrixBase<Out>
const & out)
const
289 requires((internal::HasPlus<Blocks> || ...))
291 forEachBlockOf<false, true, false>(
295 [](
auto const &
block,
auto const & xs,
auto const & ds,
auto const & os) {
296 internal::plusInto(
block, xs, ds, os);
304 template <
typename A,
typename B,
typename Out>
306 minus(Eigen::MatrixBase<A>
const & a, Eigen::MatrixBase<B>
const & b, Eigen::MatrixBase<Out>
const & out)
const
307 requires((internal::HasMinus<Blocks> || ...))
309 forEachBlockOf<false, false, true>(
313 [](
auto const &
block,
auto const & as,
auto const & bs,
auto const & os) {
314 internal::minusInto(
block, as, bs, os);
325 return [&]<std::size_t... I>(std::index_sequence<I...>) {
327 }(std::make_index_sequence<BlockCount>{});
337 template <
typename Derived,
typename F>
339 forEachBlock(Eigen::MatrixBase<Derived>
const & rows, F f)
const
342 EMRYS_FILTER_ASSERT(m.rows() ==
valueDimension() &&
"the rows do not match the space");
344 [&]<std::size_t... I>(std::index_sequence<I...>) {
353 }(std::make_index_sequence<BlockCount>{});
360 bool FirstDifference,
361 bool SecondDifference,
369 Eigen::MatrixBase<First>
const & first,
370 Eigen::MatrixBase<Second>
const & second,
371 Eigen::MatrixBase<Out>
const & out,
376 Eigen::Index firstOffset = 0;
377 Eigen::Index secondOffset = 0;
378 Eigen::Index outOffset = 0;
379 auto const step = [&]<
typename B>(B
const & b) {
380 Eigen::Index
const firstRows = internal::rowsOf<FirstDifference>(b);
381 Eigen::Index
const secondRows = internal::rowsOf<SecondDifference>(b);
382 Eigen::Index
const outRows = internal::rowsOf<OutDifference>(b);
384 internal::middleRowsOf<internal::rowsAtCompileTime<FirstDifference, B>>(first, firstOffset, firstRows),
385 internal::middleRowsOf<internal::rowsAtCompileTime<SecondDifference, B>>(
390 internal::middleRowsOf<internal::rowsAtCompileTime<OutDifference, B>>(o, outOffset, outRows));
391 firstOffset += firstRows;
392 secondOffset += secondRows;
393 outOffset += outRows;
395 [&]<std::size_t... I>(std::index_sequence<I...>) {
397 }(std::make_index_sequence<BlockCount>{});
399 firstOffset == first.rows() && secondOffset == second.rows() && outOffset == o.rows()
400 &&
"the rows do not match the space"
414template <Space Block,
int MaxCount_ = Eigen::Dynamic>
418 Block::ValueDimensionStep == 0 && Block::FixedValueDimension > 0,
419 "a repeated block must have a fixed, nonzero size"
421 static_assert(MaxCount_ == Eigen::Dynamic || MaxCount_ >= 0);
436 MaxCount == Eigen::Dynamic ? Eigen::Dynamic :
MaxCount * Block::FixedValueDimension;
438 Repeated() =
default;
442 : m_block{std::move(
block)}
448 [[nodiscard]] Block
const &
455 [[nodiscard]] Eigen::Index
462 [[nodiscard]] Eigen::Index
482 EMRYS_FILTER_ASSERT(n >= 0 && n %
ValueDimensionStep == 0 &&
"the dimension does not fit the space");
487 template <
typename Derived>
489 normalize(Eigen::MatrixBase<Derived>
const & rows)
const
490 requires(internal::HasNormalize<Block>)
492 forEachRepetition(rows, [
this](
auto && sub) {
498 template <
typename X,
typename D,
typename Out>
500 plus(Eigen::MatrixBase<X>
const & x, Eigen::MatrixBase<D>
const & d, Eigen::MatrixBase<Out>
const & out)
const
501 requires(internal::HasPlus<Block>)
503 forEachRepetitionOf<false, true, false>(x, d, out, [
this](
auto const & xs,
auto const & ds,
auto const & os) {
504 internal::plusInto(m_block, xs, ds, os);
509 template <
typename A,
typename B,
typename Out>
511 minus(Eigen::MatrixBase<A>
const & a, Eigen::MatrixBase<B>
const & b, Eigen::MatrixBase<Out>
const & out)
const
512 requires(internal::HasMinus<Block>)
514 forEachRepetitionOf<false, false, true>(a, b, out, [
this](
auto const & as,
auto const & bs,
auto const & os) {
515 internal::minusInto(m_block, as, bs, os);
523 return Repeated<DifferenceSpace<Block>, MaxCount_>{
differenceSpace(m_block), m_count};
533 template <
typename Derived,
typename F>
535 forEachRepetition(Eigen::MatrixBase<Derived>
const & rows, F f)
const
538 EMRYS_FILTER_ASSERT(m.rows() ==
valueDimension() &&
"the rows do not match the space");
539 for (Eigen::Index k = 0; k < m_count; ++k)
549 bool FirstDifference,
550 bool SecondDifference,
558 Eigen::MatrixBase<First>
const & first,
559 Eigen::MatrixBase<Second>
const & second,
560 Eigen::MatrixBase<Out>
const & out,
565 Eigen::Index
const firstRows = internal::rowsOf<FirstDifference>(m_block);
566 Eigen::Index
const secondRows = internal::rowsOf<SecondDifference>(m_block);
567 Eigen::Index
const outRows = internal::rowsOf<OutDifference>(m_block);
569 first.rows() == m_count * firstRows && second.rows() == m_count * secondRows
570 && o.rows() == m_count * outRows &&
"the rows do not match the space"
572 for (Eigen::Index k = 0; k < m_count; ++k)
574 f(internal::middleRowsOf<internal::rowsAtCompileTime<FirstDifference, Block>>(
579 internal::middleRowsOf<internal::rowsAtCompileTime<SecondDifference, Block>>(
584 internal::middleRowsOf<internal::rowsAtCompileTime<OutDifference, Block>>(o, k * outRows, outRows));
589 Eigen::Index m_count = 0;
598template <
typename... Blocks>
599std::tuple<Blocks...> *
600compositeBlocks(Composite<Blocks...>
const *);
604concept IsComposite =
requires(T
const * t) { compositeBlocks(t); };
608using CompositeBlocks = std::remove_pointer_t<decltype(compositeBlocks(std::declval<T const *>()))>;
611template <
typename Blocks>
612inline constexpr int resizableBlockCountIn = 0;
615template <
typename... Blocks>
616inline constexpr int resizableBlockCountIn<std::tuple<Blocks...>> = (0 + ... + resizableBlockCount<Blocks>);
619template <IsComposite S>
620inline constexpr int resizableBlockCount<S> = resizableBlockCountIn<CompositeBlocks<S>>;
629concept SizedByLength = resizableBlockCount<S> <= 1;
632template <
typename Block,
int MaxCount>
634repeatedBlock(Repeated<Block, MaxCount>
const *);
638concept IsRepeated =
requires(T
const * t) { repeatedBlock(t); };
642using RepeatedBlock = std::remove_pointer_t<decltype(repeatedBlock(std::declval<T const *>()))>;
645template <
int Dimension,
int MaxDimension>
647leafExtent(LeafExtent<Dimension, MaxDimension>
const *);
651leafExtent(
void const *);
655concept IsUniformLeaf =
decltype(leafExtent(std::declval<T const *>()))::value;
658template <PeriodicInterval Interval,
int Dimension,
int MaxDimension>
660periodicLeaf(Periodic<Interval, Dimension, MaxDimension>
const *);
664periodicLeaf(
void const *);
668concept IsPeriodic =
decltype(periodicLeaf(std::declval<T const *>()))::value;
675 double lower = -std::numeric_limits<double>::infinity();
676 double upper = std::numeric_limits<double>::infinity();
677 bool periodic =
false;
685template <
typename Leaf>
686[[nodiscard]]
constexpr std::optional<LeafSupport>
689 if constexpr (IsPeriodic<Leaf>)
691 return LeafSupport{.lower = Leaf::lower(), .upper = Leaf::upper(), .periodic =
true};
695 return LeafSupport{};
707template <
typename Space,
typename F>
709forEachLeaf(Space
const & space, F && f, Eigen::Index offset = 0)
711 if constexpr (IsComposite<Space>)
713 [&]<std::size_t... I>(std::index_sequence<I...>) {
714 ((forEachLeaf(space.template
block<I>(), f, offset), offset += space.template
block<I>().valueDimension()),
716 }(std::make_index_sequence<std::tuple_size_v<CompositeBlocks<Space>>>{});
718 else if constexpr (IsRepeated<Space>)
720 for (Eigen::Index k = 0; k < space.count(); ++k)
722 forEachLeaf(space.block(), f, offset + k * Space::ValueDimensionStep);
The coordinate types (decisions.md [no-bounded-coordinates]): Linear, plain coordinates,...
The macros every header includes first.
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
The concatenation of Blocks, any number of them resizable.
Definition Composite.h:170
friend bool operator==(Composite const &, Composite const &)=default
Equal when every stored parameter and size is; a fixed-size Composite is always equal.
auto const & block() const
Definition Composite.h:229
void minus(Eigen::MatrixBase< A > const &a, Eigen::MatrixBase< B > const &b, Eigen::MatrixBase< Out > const &out) const
block by block, for a composite with a block that has its own minus(); see Emrys::minus().
Definition Composite.h:306
void resize(Eigen::Index n)
Resizes the composite's only resizable block, at any depth, so the composite has n coordinates.
Definition Composite.h:263
static constexpr int MaxValueDimension
Definition Composite.h:216
Eigen::Index offset() const
Definition Composite.h:252
Composite< DifferenceSpace< Blocks >... > difference() const
The composite of the blocks' difference spaces, with their sizes.
Definition Composite.h:323
Composite(Blocks... blocks)
The concatenation of blocks, with their parameters and sizes.
Definition Composite.h:222
void normalize(Eigen::MatrixBase< Derived > const &rows) const
Normalizes each block's rows; a composite of blocks without normalize() has none.
Definition Composite.h:275
Eigen::Index valueDimension() const
Definition Composite.h:244
void plus(Eigen::MatrixBase< X > const &x, Eigen::MatrixBase< D > const &d, Eigen::MatrixBase< Out > const &out) const
block by block, for a composite with a block that has its own plus(); see Emrys::plus().
Definition Composite.h:288
static constexpr int ValueDimensionStep
Definition Composite.h:213
static constexpr int FixedValueDimension
Definition Composite.h:207
auto & block()
Definition Composite.h:237
A fixed-size Block repeated count() times, up to MaxCount_, such as one block per vehicle.
Definition Composite.h:416
void plus(Eigen::MatrixBase< X > const &x, Eigen::MatrixBase< D > const &d, Eigen::MatrixBase< Out > const &out) const
for each repetition, for a block with its own plus().
Definition Composite.h:500
void setCount(Eigen::Index count)
Sets the number of repetitions to count, at most MaxCount.
Definition Composite.h:470
Block const & block() const
Definition Composite.h:449
static constexpr int ValueDimensionStep
the coordinates of one repetition
Definition Composite.h:432
friend bool operator==(Repeated const &, Repeated const &)=default
Equal when every stored parameter and size is; a fixed-size Repeated is always equal.
static constexpr int MaxCount
Maximum number of repetitions, or Eigen::Dynamic if unbounded.
Definition Composite.h:429
Eigen::Index valueDimension() const
Definition Composite.h:463
void resize(Eigen::Index n)
Resizes to n coordinates, a whole number of repetitions.
Definition Composite.h:480
Block BlockType
The repeated block's type.
Definition Composite.h:426
static constexpr int MaxValueDimension
MaxCount repetitions' worth of coordinates, or Eigen::Dynamic if unbounded.
Definition Composite.h:435
Eigen::Index count() const
Definition Composite.h:456
static constexpr int FixedValueDimension
nothing is fixed: every coordinate belongs to a repetition
Definition Composite.h:431
Repeated(Block block, Eigen::Index count=0)
count repetitions of block.
Definition Composite.h:441
Repeated< DifferenceSpace< Block >, MaxCount_ > difference() const
The block's difference space, repeated as many times.
Definition Composite.h:521
void normalize(Eigen::MatrixBase< Derived > const &rows) const
Normalizes each repetition; a repeated block without normalize() has none.
Definition Composite.h:489
void minus(Eigen::MatrixBase< A > const &a, Eigen::MatrixBase< B > const &b, Eigen::MatrixBase< Out > const &out) const
for each repetition, for a block with its own minus().
Definition Composite.h:511
A type usable as the space of a distribution.
Definition Space.h:186
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
Eigen::MatrixBase< Derived > & writable(Eigen::MatrixBase< Derived > const &block)
block, writable: Eigen's idiom for a function that writes through an expression passed as const&.
Definition Space.h:389
DifferenceSpace< S > differenceSpace(S const &space)
Definition Space.h:235
auto block(Space auto const &space, X &&x)
Definition TagPath.h:979
constexpr bool isLinear
Whether S is linear: its values and its differences are both plain vectors.
Definition Space.h:321
constexpr int valueDimensionAtCompileTime
The value dimension of Space at compile time, or Eigen::Dynamic if it is resizable.
Definition Space.h:251
void normalizeValues(S const &space, Eigen::MatrixBase< Derived > const &block)
Brings the values in block (rows are space's coordinates, columns samples) into canonical form,...
Definition Space.h:331