29concept HasNormalize =
requires(S
const & space, Eigen::MatrixXd &
block) { space.normalize(
block.middleRows(0, 0)); };
35concept HasPlus =
requires(S
const & space, Eigen::MatrixXd &
block) {
36 space.plus(
block.middleRows(0, 0),
block.middleRows(0, 0),
block.middleRows(0, 0));
43concept HasMinus =
requires(S
const & space, Eigen::MatrixXd &
block) {
44 space.minus(
block.middleRows(0, 0),
block.middleRows(0, 0),
block.middleRows(0, 0));
52concept NearMissNormalize =
53 !HasNormalize<S> &&
requires(S & space, Eigen::MatrixXd &
block) { space.normalize(
block); };
59concept NearMissPlus = !HasPlus<S> &&
requires(S & space, Eigen::MatrixXd &
block) { space.plus(
block,
block,
block); };
65concept NearMissMinus =
66 !HasMinus<S> &&
requires(S & space, Eigen::MatrixXd &
block) { space.minus(
block,
block,
block); };
76concept NormalizeTakesBlocks = HasNormalize<S> || (!
requires { &S::normalize; } && !NearMissNormalize<S>);
80concept PlusTakesBlocks = HasPlus<S> || (!
requires { &S::plus; } && !NearMissPlus<S>);
84concept MinusTakesBlocks = HasMinus<S> || (!
requires { &S::minus; } && !NearMissMinus<S>);
88concept HasDifference =
requires(S
const & space) { space.difference(); };
92struct DifferenceSpaceOf
99template <HasDifference S>
100struct DifferenceSpaceOf<S>
103 using type = std::remove_cvref_t<decltype(std::declval<S const &>().difference())>;
110template <
typename D,
typename S>
111concept DifferenceSpaceFor = std::regular<D> &&
requires(D
const & d) {
112 { d.valueDimension() } -> std::convertible_to<Eigen::Index>;
113 typename std::integral_constant<int, D::FixedValueDimension>;
114 typename std::integral_constant<int, D::ValueDimensionStep>;
115 typename std::integral_constant<int, D::MaxValueDimension>;
116 requires(D::ValueDimensionStep == 0) == (S::ValueDimensionStep == 0);
117 requires(D::MaxValueDimension == Eigen::Dynamic) == (S::MaxValueDimension == Eigen::Dynamic);
122inline constexpr bool hasEqualSizes = DifferenceSpaceOf<S>::type::FixedValueDimension == S::FixedValueDimension
123 && DifferenceSpaceOf<S>::type::ValueDimensionStep == S::ValueDimensionStep
124 && DifferenceSpaceOf<S>::type::MaxValueDimension == S::MaxValueDimension;
131inline constexpr int resizableBlockCount = S::ValueDimensionStep == 0 ? 0 : 1;
186concept Space =
requires(S
const & space) {
187 typename std::integral_constant<int, S::FixedValueDimension>;
188 typename std::integral_constant<int, S::ValueDimensionStep>;
189 typename std::integral_constant<int, S::MaxValueDimension>;
190 requires S::FixedValueDimension >= 0 && S::ValueDimensionStep >= 0;
192 S::ValueDimensionStep == 0
193 ? S::MaxValueDimension == S::FixedValueDimension
194 : (S::MaxValueDimension == Eigen::Dynamic || S::MaxValueDimension >= S::FixedValueDimension)
196 requires std::regular<S>;
197 { space.valueDimension() } -> std::convertible_to<Eigen::Index>;
198 requires internal::NormalizeTakesBlocks<S> && internal::PlusTakesBlocks<S> && internal::MinusTakesBlocks<S>;
199 requires internal::NormalizeTakesBlocks<typename internal::DifferenceSpaceOf<S>::type>;
200 requires internal::HasDifference<S>
201 || (!internal::HasNormalize<S> && !internal::HasPlus<S> && !internal::HasMinus<S>);
202 requires internal::DifferenceSpaceFor<typename internal::DifferenceSpaceOf<S>::type, S>;
203 requires internal::HasPlus<S> == internal::HasMinus<S>;
204 requires internal::hasEqualSizes<S> || internal::HasPlus<S>;
205 requires S::ValueDimensionStep == 0 || internal::resizableBlockCount<S> > 1
206 ||
requires(S & resizable, Eigen::Index n) { resizable.resize(n); };
237 if constexpr (internal::HasDifference<S>)
239 return space.difference();
250template <
typename Space>
252 Space::ValueDimensionStep == 0 ? Space::FixedValueDimension : Eigen::Dynamic;
257template <
typename Space>
259 Space::ValueDimensionStep == 0 ? Space::FixedValueDimension : Space::MaxValueDimension;
271[[nodiscard]] Eigen::Index
274 return space.valueDimension();
283[[nodiscard]] Eigen::Index
286 if constexpr (internal::HasDifference<S>)
288 return space.difference().valueDimension();
292 return space.valueDimension();
302inline constexpr bool hasPlainValues = !internal::HasNormalize<S> && !internal::HasPlus<S>;
312 !internal::HasNormalize<DifferenceSpace<S>> && !internal::HasPlus<S> && !internal::HasMinus<S>;
329template <Space S,
typename Derived>
333 if constexpr (internal::HasNormalize<S>)
335 space.normalize(
block);
344template <Space S,
typename Derived>
348 if constexpr (internal::HasNormalize<DifferenceSpace<S>>)
358template <FixedSizeSpace S,
typename Derived>
370template <FixedSizeSpace S,
typename Derived>
387template <
typename Derived>
388[[nodiscard]] Eigen::MatrixBase<Derived> &
391 return const_cast<Eigen::MatrixBase<Derived> &
>(
block);
402template <
double Lower,
double Period,
typename Scalar>
403[[nodiscard]]
constexpr Scalar
406 constexpr double upper = Lower + Period;
407 if (x >= Scalar(Lower) && x < Scalar(upper)) [[likely]]
412 if (x >= Scalar(Lower - Period) && x < Scalar(upper + Period)) [[likely]]
416 if (x < Scalar(Lower))
418 y = x + Scalar(Period);
422 y = x - Scalar(Period);
427 y = x - Scalar(Period) *
floorOf<Scalar>((x - Scalar(Lower)) / Scalar(Period));
433 if (y < Scalar(Lower))
437 return y >= Scalar(upper) ? Scalar(Lower) : y;
441template <
typename Scalar,
int Rows,
int Cols,
int MaxRows,
int MaxCols>
442using MatrixOf = Eigen::
443 Matrix<Scalar, Rows, Cols, (MaxRows == 1 && MaxCols != 1 ? Eigen::RowMajor : Eigen::ColMajor), MaxRows, MaxCols>;
448template <
typename L,
typename R>
452 static constexpr bool broadcastLeft = L::ColsAtCompileTime == 1 && R::ColsAtCompileTime != 1;
455 static constexpr bool broadcastRight = R::ColsAtCompileTime == 1 && L::ColsAtCompileTime != 1;
458 static constexpr int cols = broadcastLeft ? int(R::ColsAtCompileTime) : int(L::ColsAtCompileTime);
461 static constexpr int maxCols = broadcastLeft ? int(R::MaxColsAtCompileTime) : int(L::MaxColsAtCompileTime);
464 template <
typename Left,
typename Right>
465 [[nodiscard]]
static Eigen::Index
466 count(Left
const & left, Right
const & right)
469 (broadcastLeft || broadcastRight || left.cols() == right.cols())
470 &&
"the operands have different numbers of columns"
472 return broadcastLeft ? right.cols() : left.cols();
477template <
bool Broadcast,
typename Derived>
478[[nodiscard]]
decltype(
auto)
479withColumns(Eigen::MatrixBase<Derived>
const & m, Eigen::Index cols)
481 if constexpr (Broadcast)
483 return m.derived().replicate(1, cols);
495template <
typename Derived>
496[[nodiscard]]
decltype(
auto)
497inMemory(Eigen::MatrixBase<Derived>
const & m)
499 if constexpr ((Eigen::internal::traits<Derived>::Flags & Eigen::DirectAccessBit) != 0)
512template <
typename S,
typename X,
typename D,
typename Out>
516 Eigen::MatrixBase<X>
const & x,
517 Eigen::MatrixBase<D>
const & d,
518 Eigen::MatrixBase<Out>
const & out
521 if constexpr (HasPlus<S>)
523 space.plus(x, d, out);
535template <
typename S,
typename A,
typename B,
typename Out>
539 Eigen::MatrixBase<A>
const & a,
540 Eigen::MatrixBase<B>
const & b,
541 Eigen::MatrixBase<Out>
const & out
544 if constexpr (HasMinus<S>)
546 space.minus(a, b, out);
558template <
bool Difference,
typename S>
559[[nodiscard]] Eigen::Index
560rowsOf(S
const & space)
562 if constexpr (Difference)
568 return space.valueDimension();
575template <
bool Difference,
typename S>
576inline constexpr int rowsAtCompileTime =
583template <
int Rows,
typename M>
585middleRowsOf(M & m, Eigen::Index offset, Eigen::Index rows)
587 if constexpr (Rows == Eigen::Dynamic)
589 return m.middleRows(offset, rows);
593 EMRYS_FILTER_ASSERT(rows == Rows &&
"the block's rows must be its compile-time size");
594 return m.template middleRows<Rows>(offset);
601template <
int Cols,
typename M>
603middleColsOf(M & m, Eigen::Index offset, Eigen::Index cols)
605 if constexpr (Cols == Eigen::Dynamic)
607 return m.middleCols(offset, cols);
611 EMRYS_FILTER_ASSERT(cols == Cols &&
"the block's columns must be its compile-time size");
612 return m.template middleCols<Cols>(offset);
619template <
int Rows,
int Cols,
typename M>
621blockOf(M & m, Eigen::Index row, Eigen::Index col, Eigen::Index rows, Eigen::Index cols)
624 (Rows == Eigen::Dynamic || rows == Rows) && (Cols == Eigen::Dynamic || cols == Cols)
625 &&
"the block's sizes must be its compile-time sizes"
639template <Space S,
typename Scalar =
double>
649template <Space S,
typename Scalar =
double>
658template <Space Rows, Space Cols = Rows,
typename Scalar =
double>
673template <Space S,
typename XDerived,
typename DDerived>
675plus(S
const & space, Eigen::MatrixBase<XDerived>
const & x, Eigen::MatrixBase<DDerived>
const & d)
677 using Columns = internal::PairedColumns<XDerived, DDerived>;
681 : int(XDerived::RowsAtCompileTime);
683 : int(XDerived::MaxRowsAtCompileTime);
684 using Result = internal::MatrixOf<typename XDerived::Scalar, rows, Columns::cols, maxRows, Columns::maxCols>;
685 Eigen::Index
const cols = Columns::count(x, d);
686 auto result = Result{};
687 result.resize(x.rows(), cols);
690 auto const & xInMemory = internal::inMemory(x);
691 auto const & dInMemory = internal::inMemory(d);
692 auto const & paired = internal::withColumns<Columns::broadcastLeft>(xInMemory, cols);
693 auto const & offsets = internal::withColumns<Columns::broadcastRight>(dInMemory, cols);
694 if constexpr (internal::HasPlus<S>)
696 space.plus(paired, offsets, result);
700 result = paired + offsets;
713template <Space S,
typename ADerived,
typename BDerived>
715minus(S
const & space, Eigen::MatrixBase<ADerived>
const & a, Eigen::MatrixBase<BDerived>
const & b)
717 using Columns = internal::PairedColumns<ADerived, BDerived>;
721 constexpr bool sameRows = internal::hasEqualSizes<S>;
724 constexpr int rows = spaceRows != Eigen::Dynamic ? spaceRows
725 : sameRows ? int(ADerived::RowsAtCompileTime)
727 constexpr int maxRows = spaceMaxRows != Eigen::Dynamic ? spaceMaxRows
728 : sameRows ? int(ADerived::MaxRowsAtCompileTime)
730 using Result = internal::MatrixOf<typename ADerived::Scalar, rows, Columns::cols, maxRows, Columns::maxCols>;
731 Eigen::Index
const cols = Columns::count(a, b);
732 auto result = Result{};
734 auto const & aInMemory = internal::inMemory(a);
735 auto const & bInMemory = internal::inMemory(b);
736 auto const & left = internal::withColumns<Columns::broadcastLeft>(aInMemory, cols);
737 auto const & right = internal::withColumns<Columns::broadcastRight>(bInMemory, cols);
738 if constexpr (internal::HasMinus<S>)
740 space.minus(left, right, result);
744 result = left - right;
765template <Space S,
typename XDerived,
typename DDerived>
767less(S
const & space, Eigen::MatrixBase<XDerived>
const & x, Eigen::MatrixBase<DDerived>
const & d)
776template <FixedSizeSpace S,
typename XDerived,
typename DDerived>
779plus(Eigen::MatrixBase<XDerived>
const & x, Eigen::MatrixBase<DDerived>
const & d)
788template <FixedSizeSpace S,
typename ADerived,
typename BDerived>
791minus(Eigen::MatrixBase<ADerived>
const & a, Eigen::MatrixBase<BDerived>
const & b)
800template <FixedSizeSpace S,
typename XDerived,
typename DDerived>
803less(Eigen::MatrixBase<XDerived>
const & x, Eigen::MatrixBase<DDerived>
const & d)
817template <
typename Space>
818[[nodiscard]]
constexpr bool
821 if constexpr (Space::ValueDimensionStep == 0)
823 return n == Space::FixedValueDimension;
827 return n >= Space::FixedValueDimension && (n - Space::FixedValueDimension) % Space::ValueDimensionStep == 0
828 && (Space::MaxValueDimension == Eigen::Dynamic || n <= Space::MaxValueDimension);
839template <
typename Space>
841fitValueDimension(Space & space, Eigen::Index n)
844 if constexpr (
requires { space.resize(n); })
846 if (space.valueDimension() != n)
850 EMRYS_FILTER_ASSERT(space.valueDimension() == n &&
"the space's resize() did not give it this dimension");
854 EMRYS_FILTER_ASSERT(space.valueDimension() == n &&
"the dimension does not fit the space");
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
The matrix of a linear measurement model by its columns: a matrix per block of the state read,...
Definition MeasurementModel.h:396
A space whose instance holds nothing, so that S{} is the only one there is: a space of fixed size,...
Definition Space.h:217
A type usable as the space of a distribution.
Definition Space.h:186
Scalar floorOf(std::type_identity_t< Scalar > const &x)
Definition Math.h:277
auto less(S const &space, Eigen::MatrixBase< XDerived > const &x, Eigen::MatrixBase< DDerived > const &d)
Definition Space.h:767
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
auto plus(S const &space, Eigen::MatrixBase< XDerived > const &x, Eigen::MatrixBase< DDerived > const &d)
Definition Space.h:675
constexpr bool allowsValueDimension(Eigen::Index n)
Definition Space.h:819
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
auto minus(S const &space, Eigen::MatrixBase< ADerived > const &a, Eigen::MatrixBase< BDerived > const &b)
Definition Space.h:715
ValueVector< DifferenceSpace< S >, Scalar > DifferenceVector
A difference in S as an Eigen column vector of Scalar, the type of minus() and of the offset plus() t...
Definition Space.h:650
Eigen::Index differenceDimension(S const &space)
Definition Space.h:284
typename internal::DifferenceSpaceOf< S >::type DifferenceSpace
The space that differences of values in S live in: the type of its difference(), or S itself if it ha...
Definition Space.h:227
void normalizeDifferences(S const &space, Eigen::MatrixBase< Derived > const &block)
Brings the differences in block into canonical form: normalizeValues() in the difference space of spa...
Definition Space.h:346
constexpr bool isLinear
Whether S is linear: its values and its differences are both plain vectors.
Definition Space.h:321
constexpr bool hasPlainValues
Whether the values of S are plain: it has neither normalize() nor plus(), so is x + δ.
Definition Space.h:302
constexpr int valueDimensionAtCompileTime
The value dimension of Space at compile time, or Eigen::Dynamic if it is resizable.
Definition Space.h:251
constexpr int maxValueDimensionAtCompileTime
The largest valid value dimension of Space, or Eigen::Dynamic if it is unbounded.
Definition Space.h:258
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
internal::MatrixOf< Scalar, valueDimensionAtCompileTime< DifferenceSpace< Rows > >, valueDimensionAtCompileTime< DifferenceSpace< Cols > >, maxValueDimensionAtCompileTime< DifferenceSpace< Rows > >, maxValueDimensionAtCompileTime< DifferenceSpace< Cols > > > DifferenceMatrix
An Eigen matrix of Scalar over the differences of Rows and Cols: a covariance, with one space for bot...
Definition Space.h:659
constexpr bool hasPlainDifferences
Whether the differences of S are plain: its difference space has no normalize(), and it has neither p...
Definition Space.h:311
Eigen::Matrix< Scalar, valueDimensionAtCompileTime< S >, 1, Eigen::ColMajor, maxValueDimensionAtCompileTime< S >, 1 > ValueVector
A value in S as an Eigen column vector of Scalar: a mean, a sample, or a true state.
Definition Space.h:640