74 typename std::integral_constant<int, S::Cardinality>;
75 typename std::integral_constant<int, S::MaxCardinality>;
76 } && (S::Cardinality == Eigen::Dynamic || (S::Cardinality >= 1 && S::MaxCardinality == S::Cardinality))
77 && std::regular<S> &&
requires(S
const & space) {
78 { space.cardinality() } -> std::convertible_to<Eigen::Index>;
85template <
int Cardinality,
int MaxCardinality>
91 [[nodiscard]]
static constexpr Eigen::Index
99 operator==(FiniteExtent
const &, FiniteExtent
const &) =
default;
104template <
int MaxCardinality>
105class FiniteExtent<Eigen::Dynamic, MaxCardinality>
110 FiniteExtent() =
default;
113 constexpr explicit FiniteExtent(Eigen::Index n)
117 n >= 1 && (MaxCardinality == Eigen::Dynamic || n <= MaxCardinality)
118 &&
"the cardinality does not fit the space"
123 [[nodiscard]]
constexpr Eigen::Index
126 return m_cardinality;
131 operator==(FiniteExtent
const &, FiniteExtent
const &) =
default;
135 Eigen::Index m_cardinality = 1;
139template <
int... Cardinalities>
144 ((result = result == Eigen::Dynamic || Cardinalities == Eigen::Dynamic ? Eigen::Dynamic : result * Cardinalities),
160template <
int Cardinality_,
int MaxCardinality_ = Cardinality_>
161struct Finite : internal::FiniteExtent<Cardinality_, MaxCardinality_>
163 static_assert(Cardinality_ == Eigen::Dynamic || Cardinality_ >= 1,
"a discrete space has at least one value");
166 Cardinality_ == Eigen::Dynamic || MaxCardinality_ == Cardinality_,
167 "a fixed cardinality is its own maximum"
170 static_assert(MaxCardinality_ == Eigen::Dynamic || MaxCardinality_ >= 1);
177 constexpr explicit Finite(Eigen::Index n)
178 requires(Cardinality_ == Eigen::Dynamic)
179 : internal::FiniteExtent<Cardinality_, MaxCardinality_>(n)
193template <
typename... Values>
196 static_assert(
sizeof...(Values) >= 1,
"a discrete space has at least one value");
201 template <
typename Value>
202 static constexpr bool contains = (std::is_same_v<Value, Values> || ...);
207 template <
typename Value>
208 static constexpr std::size_t occurrences = (std::size_t{0} + ... + std::size_t{std::is_same_v<Value, Values>});
210 static_assert(((occurrences<Values> == 1) && ...),
"the values of a Named space must be distinct");
215 [[nodiscard]]
static constexpr Eigen::Index
222 template <
typename Value>
223 [[nodiscard]]
static constexpr Eigen::Index
226 static_assert(
contains<Value>,
"the space has no value with this name");
227 Eigen::Index result = 0;
229 ((found = found || std::is_same_v<Value, Values>, result += found ? 0 : 1), ...);
246class DiscreteProduct :
private internal::PartStorage<Axes...>
248 static_assert(
sizeof...(Axes) > 0,
"a product needs at least one axis");
251 using Storage = internal::PartStorage<
Axes...>;
255 static constexpr std::size_t
AxisCount =
sizeof...(Axes);
258 static constexpr int Cardinality = internal::productCardinality<Axes::Cardinality...>();
261 static constexpr int MaxCardinality = internal::productCardinality<Axes::MaxCardinality...>();
263 DiscreteProduct() =
default;
267 : Storage{std::move(axes)...}
271 template <std::
size_t I>
272 [[nodiscard]]
constexpr auto const &
275 return Storage::template part<I>();
279 [[nodiscard]]
constexpr Eigen::Index
282 return [&]<std::size_t... I>(std::index_sequence<I...>) {
283 return (Eigen::Index{1} * ... *
axis<I>().cardinality());
284 }(std::make_index_sequence<AxisCount>{});
288 template <std::
size_t I>
289 [[nodiscard]]
constexpr Eigen::Index
292 return [&]<std::size_t... J>(std::index_sequence<J...>) {
294 }(std::make_index_sequence<
AxisCount - 1 - I>{});
298 [[nodiscard]]
constexpr Eigen::Index
301 auto const cardinalities = [&]<std::size_t... I>(std::index_sequence<I...>) {
302 return std::array<Eigen::Index, AxisCount>{
axis<I>().cardinality()...};
303 }(std::make_index_sequence<AxisCount>{});
304 Eigen::Index result = 0;
305 for (std::size_t i = 0; i <
AxisCount; ++i)
310 result = result * cardinalities[i] +
coordinates[i];
316 [[nodiscard]]
constexpr std::array<Eigen::Index, AxisCount>
320 auto result = std::array<Eigen::Index, AxisCount>{};
321 [&]<std::size_t... I>(std::index_sequence<I...>) {
323 }(std::make_index_sequence<AxisCount>{});
329 operator==(DiscreteProduct
const &, DiscreteProduct
const &) =
default;
336template <
typename...
Axes>
342concept IsDiscreteProduct =
requires(T
const * t) { discreteProductAxes(t); };
346using DiscreteProductAxes = std::remove_pointer_t<decltype(discreteProductAxes(std::declval<T const *>()))>;
349template <
typename... Values>
351namedValues(Named<Values...>
const *);
355namedValues(
void const *);
359concept IsNamed =
decltype(namedValues(std::declval<T const *>()))::value;
363inline constexpr bool IsUntaggedAxis =
false;
365template <
int Cardinality,
int MaxCardinality>
366inline constexpr bool IsUntaggedAxis<Finite<Cardinality, MaxCardinality>>{
true};
368template <
typename... Values>
369inline constexpr bool IsUntaggedAxis<Named<Values...>>{
true};
371template <
typename... Axes>
372inline constexpr bool IsUntaggedAxis<DiscreteProduct<Axes...>>{
true};
377template <
typename Tag,
typename S>
381 if constexpr (std::is_same_v<Tag, S>)
385 else if constexpr (IsDiscreteProduct<S>)
387 return []<
typename... Axes>(std::tuple<Axes...> *) {
388 return (countAxis<Tag, Axes>() + ... + 0);
389 }(
static_cast<DiscreteProductAxes<S> *
>(
nullptr));
398template <
typename Value,
typename S>
402 if constexpr (IsNamed<S>)
404 return S::template contains<Value> ? 1 : 0;
406 else if constexpr (IsDiscreteProduct<S>)
408 return []<
typename... Axes>(std::tuple<Axes...> *) {
409 return (countValue<Value, Axes>() + ... + 0);
410 }(
static_cast<DiscreteProductAxes<S> *
>(
nullptr));
419template <
typename S,
typename F>
421forEachAxis(S
const & space, F && f)
423 [&]<std::size_t... I>(std::index_sequence<I...>) {
424 (f(space.template axis<I>(), space.template stride<I>()), ...);
425 }(std::make_index_sequence<std::tuple_size_v<DiscreteProductAxes<S>>>{});
429template <
typename Tag,
typename S>
430[[nodiscard]]
constexpr std::pair<Eigen::Index, Tag const *>
431locateAxis(S
const & space)
433 if constexpr (std::is_same_v<Tag, S>)
440 !IsUntaggedAxis<Tag>,
441 "a path names axes by tag; derive one, such as struct Maneuver : Named<Cruise, Turn> {}"
443 static_assert(countAxis<Tag, S>() > 0,
"the space does not have this axis");
444 static_assert(countAxis<Tag, S>() < 2,
"the axis appears more than once; qualify it with an enclosing tag");
445 auto found = std::pair<Eigen::Index, Tag const *>{0,
nullptr};
446 forEachAxis(space, [&]<
typename Axis>(Axis
const & axis, Eigen::Index stride) {
447 if constexpr (countAxis<Tag, Axis>() > 0)
449 auto const inner = locateAxis<Tag>(axis);
450 found = {inner.first * stride, inner.second};
458template <
typename Tag,
typename... Rest,
typename S>
459[[nodiscard]]
constexpr auto
460locateAxisPath(S
const & space)
462 auto const [stride, tag] = locateAxis<Tag>(space);
463 if constexpr (
sizeof...(Rest) == 0)
465 return std::pair{stride, tag};
469 auto const [innerStride, inner] = locateAxisPath<Rest...>(*tag);
470 return std::pair{stride * innerStride, inner};
480 Eigen::Index cardinality;
484 [[nodiscard]]
constexpr bool
485 matches(Eigen::Index value)
const
487 return (value / stride) % cardinality == index;
492template <
typename Value,
typename S>
493[[nodiscard]]
constexpr ValueLocation
494locateValue(S
const & space)
496 static_assert(countValue<Value, S>() > 0,
"the space has no value with this name");
498 countValue<Value, S>() < 2,
499 "the value names a value of more than one axis; qualify it with a TagPath to its axis"
501 if constexpr (IsNamed<S>)
503 return {1, space.cardinality(), S::template index<Value>()};
507 auto found = ValueLocation{};
508 forEachAxis(space, [&]<
typename Axis>(Axis
const & axis, Eigen::Index stride) {
509 if constexpr (countValue<Value, Axis>() > 0)
511 ValueLocation
const inner = locateValue<Value>(axis);
512 found = {inner.stride * stride, inner.cardinality, inner.index};
520template <
typename P,
typename S>
521[[nodiscard]]
constexpr ValueLocation
522locateValuePath(S
const & space)
524 return withPathTags<P>([&]<
typename... Tags>() {
525 constexpr std::size_t count =
sizeof...(Tags);
526 using Value = std::tuple_element_t<count - 1, std::tuple<Tags...>>;
527 if constexpr (count == 1)
529 return locateValue<Value>(space);
533 return [&]<std::size_t... I>(std::index_sequence<I...>) {
534 auto const [stride, axis] = locateAxisPath<std::tuple_element_t<I, std::tuple<Tags...>>...>(space);
535 ValueLocation inner = locateValue<Value>(*axis);
536 inner.stride *= stride;
538 }(std::make_index_sequence<count - 1>{});
544template <
typename P,
typename S>
545[[nodiscard]]
constexpr auto
546locateAxisByPath(S
const & space)
548 return withPathTags<P>([&]<
typename... Tags>() {
549 return locateAxisPath<Tags...>(space);
554template <
typename... Axes>
556joinAxes(std::tuple<Axes...> axes)
558 static_assert(
sizeof...(Axes) > 0,
"nothing is left of the space");
559 if constexpr (
sizeof...(Axes) == 1)
561 return std::get<0>(std::move(axes));
567 return DiscreteProduct<Axes...>{std::move(d)...};
574template <
typename Tag,
typename... Rest,
typename S>
576axesWithout(S
const & space);
579template <
typename Tag,
typename... Rest,
typename Axis>
581axisWithout(Axis
const & axis)
583 if constexpr (countAxis<Tag, Axis>() > 0)
585 return axesWithout<Tag, Rest...>(axis);
589 return std::tuple<Axis>{axis};
597template <
typename Tag,
typename... Rest,
typename S>
599axesWithout(S
const & space)
601 if constexpr (std::is_same_v<Tag, S>)
603 if constexpr (
sizeof...(Rest) == 0)
605 return std::tuple<>{};
609 return axesWithout<Rest...>(space);
615 !IsUntaggedAxis<Tag>,
616 "a path names axes by tag; derive one, such as struct Maneuver : Named<Cruise, Turn> {}"
618 static_assert(IsDiscreteProduct<S>,
"the space does not have this axis");
619 return [&]<std::size_t... I>(std::index_sequence<I...>) {
620 return std::tuple_cat(axisWithout<Tag, Rest...>(space.template axis<I>())...);
621 }(std::make_index_sequence<std::tuple_size_v<DiscreteProductAxes<S>>>{});
626template <
typename P,
typename S>
628complementAxes(S
const & space)
630 return withPathTags<P>([&]<
typename... Tags>() {
631 return joinAxes(axesWithout<Tags...>(space));
635template <
typename Value,
typename S>
639template <
typename Value,
typename Axes>
647template <
typename Value,
typename Axis,
typename... Rest>
648struct ValueAxisIn<Value, std::tuple<Axis, Rest...>>
651 using type =
typename std::conditional_t<
652 (countValue<Value, Axis>() > 0),
653 ValueAxisOf<Value, Axis>,
654 ValueAxisIn<Value, std::tuple<Rest...>>>::type;
658template <
typename Value,
typename S>
662 using type =
typename ValueAxisIn<Value, DiscreteProductAxes<S>>::type;
666template <
typename Value,
typename S>
668struct ValueAxisOf<Value, S>
675template <
typename Value,
typename S>
676using ValueAxis =
typename ValueAxisOf<Value, S>::type;
679template <
typename P,
typename S>
680struct ValueAxisPathOf
683 using type = TagPath<ValueAxis<P, S>>;
689template <
typename... Tags,
typename S>
690struct ValueAxisPathOf<TagPath<Tags...>, S>
692 static constexpr std::size_t Count =
sizeof...(Tags);
695 using Value = std::tuple_element_t<Count - 1, std::tuple<Tags...>>;
698 template <std::size_t... I>
699 static consteval auto
700 make(std::index_sequence<I...>)
702 if constexpr (Count == 1)
704 return TagPath<ValueAxis<Value, S>>{};
708 using Last = std::tuple_element_t<Count - 2, std::tuple<Tags...>>;
709 return TagPath<std::tuple_element_t<I, std::tuple<Tags...>>..., ValueAxis<Value, Last>>{};
714 using type =
decltype(make(std::make_index_sequence<Count - 1>{}));
720template <
typename P,
typename S>
721using ValueAxisPath =
typename ValueAxisPathOf<P, S>::type;
728 if constexpr (IsDiscreteProduct<S>)
730 return []<
typename... Axes>(std::tuple<Axes...> *) {
731 return (leafAxisCount<Axes>() + ... + 0);
732 }(
static_cast<DiscreteProductAxes<S> *
>(
nullptr));
748template <
typename Tag,
typename S>
752 if constexpr (std::is_same_v<Tag, S>)
754 return {0, leafAxisCount<S>()};
756 else if constexpr (IsDiscreteProduct<S>)
758 return []<
typename... Axes>(std::tuple<Axes...> *) {
761 auto const visit = [&]<
typename Axis>() {
762 if constexpr (countAxis<Tag, Axis>() > 0)
764 LeafRange
const inner = leafRangeOfAxis<Tag, Axis>();
765 result = {offset + inner.first, inner.count};
767 offset += leafAxisCount<Axis>();
769 (visit.template operator()<Axes>(), ...);
771 }(
static_cast<DiscreteProductAxes<S> *
>(
nullptr));
780template <
typename S,
typename Tag,
typename... Rest>
784 LeafRange
const outer = leafRangeOfAxis<Tag, S>();
785 if constexpr (
sizeof...(Rest) == 0)
791 LeafRange
const inner = leafRangeOfAxisPath<Tag, Rest...>();
792 return {outer.first + inner.first, inner.count};
797template <
typename P,
typename S>
801 return []<
typename... Tags>(TagPath<Tags...> *) {
802 return leafRangeOfAxisPath<S, Tags...>();
803 }(
static_cast<AsTagPath<P> *
>(
nullptr));
807template <
typename Value,
typename S>
811 if constexpr (IsDiscreteProduct<S>)
813 return []<
typename... Axes>(std::tuple<Axes...> *) {
816 auto const visit = [&]<
typename Axis>() {
817 if constexpr (countValue<Value, Axis>() > 0)
819 result = offset + leafOfValue<Value, Axis>();
821 offset += leafAxisCount<Axis>();
823 (visit.template operator()<Axes>(), ...);
825 }(
static_cast<DiscreteProductAxes<S> *
>(
nullptr));
834template <
typename P,
typename S>
838 return []<
typename... Tags>(TagPath<Tags...> *) {
839 constexpr std::size_t count =
sizeof...(Tags);
840 using Value = std::tuple_element_t<count - 1, std::tuple<Tags...>>;
841 if constexpr (count == 1)
843 return leafOfValue<Value, S>();
847 return []<std::size_t... I>(std::index_sequence<I...>) {
848 using Axis = std::tuple_element_t<count - 2, std::tuple<Tags...>>;
849 return leafRangeOfAxisPath<S, std::tuple_element_t<I, std::tuple<Tags...>>...>().first
850 + leafOfValue<Value, Axis>();
851 }(std::make_index_sequence<count - 1>{});
853 }(
static_cast<AsTagPath<P> *
>(
nullptr));
857template <
typename S,
typename Tag,
typename... Rest>
861 if constexpr (!std::is_same_v<Tag, S> && (IsUntaggedAxis<Tag> || countAxis<Tag, S>() != 1))
865 else if constexpr (
sizeof...(Rest) == 0)
871 return axisPathResolves<Tag, Rest...>();
876template <
typename P,
typename S>
880 return []<
typename... Tags>(TagPath<Tags...> *) {
881 return axisPathResolves<S, Tags...>();
882 }(
static_cast<AsTagPath<P> *
>(
nullptr));
886template <
typename P,
typename S>
890 return []<
typename... Tags>(TagPath<Tags...> *) {
891 constexpr std::size_t count =
sizeof...(Tags);
892 using Value = std::tuple_element_t<count - 1, std::tuple<Tags...>>;
893 if constexpr (count == 1)
895 return countValue<Value, S>() == 1;
899 return []<std::size_t... I>(std::index_sequence<I...>) {
900 using Axis = std::tuple_element_t<count - 2, std::tuple<Tags...>>;
901 if constexpr (!axisPathResolves<S, std::tuple_element_t<I, std::tuple<Tags...>>...>())
907 return countValue<Value, Axis>() == 1;
909 }(std::make_index_sequence<count - 1>{});
911 }(
static_cast<AsTagPath<P> *
>(
nullptr));
916consteval std::array<bool, std::size_t(leafAxisCount<S>())>
919 auto result = std::array<bool, std::size_t(leafAxisCount<S>())>{};
920 if constexpr (IsDiscreteProduct<S>)
922 [&]<
typename... Axes>(std::tuple<Axes...> *) {
923 std::size_t offset = 0;
924 auto const append = [&]<
typename Axis>() {
925 for (
bool const named : namedLeaves<Axis>())
927 result[offset++] = named;
930 (append.template operator()<Axes>(), ...);
931 }(
static_cast<DiscreteProductAxes<S> *
>(
nullptr));
935 result[0] = IsNamed<S>;
951template <std::
size_t N>
953countLeaves(std::array<int, N> & times, LeafRange range)
955 for (
int k = range.first; k < range.first + range.count; ++k)
957 ++times[std::size_t(k)];
964template <
typename S,
typename... Values,
typename... Paths>
966namingOf(std::tuple<Values...> *, std::tuple<Paths...> *)
968 if constexpr (!((valuePathResolves<Values, S>() && ...) && (pathResolves<Paths, S>() && ...)))
970 return Naming::unresolved;
974 auto times = std::array<int, std::size_t(leafAxisCount<S>())>{};
975 (countLeaves(times, LeafRange{leafOfValuePath<Values, S>(), 1}), ...);
976 (countLeaves(times, leafRangeOfPath<Paths, S>()), ...);
977 constexpr auto named = namedLeaves<S>();
978 for (
int const n : times)
982 return Naming::repeated;
985 for (std::size_t k = 0; k < times.size(); ++k)
987 if (times[k] == 0 && named[k])
989 return Naming::missingNamed;
992 for (
int const n : times)
996 return Naming::missingUnnamed;
999 return Naming::complete;
1004template <
typename P>
1008template <
typename... Tags>
1009struct LastTagOf<TagPath<Tags...>>
1012 using type = std::tuple_element_t<
sizeof...(Tags) - 1, std::tuple<Tags...>>;
1016template <
typename P>
1017using LastTag =
typename LastTagOf<AsTagPath<P>>::type;
1020template <
typename S>
1021[[nodiscard]]
constexpr std::array<Eigen::Index, std::size_t(leafAxisCount<S>())>
1022leafCardinalities(S
const & space)
1024 auto result = std::array<Eigen::Index, std::size_t(leafAxisCount<S>())>{};
1025 if constexpr (IsDiscreteProduct<S>)
1027 std::size_t offset = 0;
1028 forEachAxis(space, [&]<
typename Axis>(Axis
const & axis, Eigen::Index) {
1029 for (Eigen::Index
const cardinality : leafCardinalities(axis))
1031 result[offset++] = cardinality;
1037 result[0] = space.cardinality();
1043template <
typename P,
typename S>
1044[[nodiscard]]
constexpr Eigen::Index
1045namedOffset(S
const & space)
1047 ValueLocation
const location = locateValuePath<P>(space);
1048 return location.index * location.stride;
1057template <
typename Path, std::
size_t N>
1069template <
typename Path, std::integral... I>
1070[[nodiscard]]
constexpr AxisIndex<Path,
sizeof...(I)>
1073 using Axis = internal::LastTag<Path>;
1076 sizeof...(I) == std::size_t(internal::leafAxisCount<Axis>()),
1077 "give one index for each leaf axis of the axis named"
1079 return {{Eigen::Index(indices)...}};
1086template <
typename Path, std::
size_t N,
typename S>
1087[[nodiscard]]
constexpr Eigen::Index
1088indexedOffset(S
const & space, AxisIndex<Path, N>
const & index)
1090 auto const [stride, axis] = locateAxisByPath<Path>(space);
1091 auto const cardinalities = leafCardinalities(*axis);
1092 Eigen::Index flat = 0;
1093 for (std::size_t k = 0; k < N; ++k)
1095 EMRYS_FILTER_ASSERT(index.indices[k] >= 0 && index.indices[k] < cardinalities[k] &&
"an index is out of range");
1096 flat = flat * cardinalities[k] + index.indices[k];
1098 return flat * stride;
1110template <
typename... Values,
DiscreteSpace S,
typename... Paths, std::size_t... N>
1111[[nodiscard]]
constexpr Eigen::Index
1114 constexpr bool named =
sizeof...(Values) +
sizeof...(Paths) > 0;
1115 static_assert(named,
"name a value");
1116 constexpr internal::Naming naming = !named ? internal::Naming::unresolved
1117 : internal::namingOf<S>(
1118 static_cast<std::tuple<Values...
> *>(
nullptr),
1119 static_cast<std::tuple<Paths...
> *>(
nullptr)
1121 static_assert(naming != internal::Naming::repeated,
"an axis is named more than once");
1122 static_assert(naming != internal::Naming::missingNamed,
"name one value in each axis");
1123 static_assert(naming != internal::Naming::missingUnnamed,
"an axis without names takes its index from at<Axis>(i)");
1124 return (Eigen::Index{0} + ... + internal::namedOffset<Values>(space))
1125 + (Eigen::Index{0} + ... + internal::indexedOffset(space, indices));
1132template <DiscreteSpace S,
typename... Values,
typename... Paths, std::size_t... N>
1133 requires FixedSizeSpace<S>
1134[[nodiscard]]
constexpr Eigen::Index
1137 return valueOf<Values...>(S{}, 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...
The product of the discrete spaces Axes: a value has one value in each axis.
Definition Discrete.h:247
static constexpr std::size_t AxisCount
the number of axes
Definition Discrete.h:255
constexpr std::array< Eigen::Index, AxisCount > coordinates(Eigen::Index value) const
Definition Discrete.h:317
constexpr Eigen::Index cardinality() const
Definition Discrete.h:280
constexpr Eigen::Index stride() const
Definition Discrete.h:290
static constexpr int MaxCardinality
the product of the axes' bounds, or Eigen::Dynamic if any is unbounded
Definition Discrete.h:261
constexpr Eigen::Index value(std::array< Eigen::Index, AxisCount > const &coordinates) const
Definition Discrete.h:299
constexpr DiscreteProduct(Axes... axes)
The product of axes, with their cardinalities.
Definition Discrete.h:266
constexpr auto const & axis() const
Definition Discrete.h:273
static constexpr int Cardinality
the product of the axes' cardinalities, or Eigen::Dynamic if any is
Definition Discrete.h:258
friend bool operator==(DiscreteProduct const &, DiscreteProduct const &)=default
Equal when every axis is.
Axes: a way of taking a root of a covariance , , whose columns carry a sigma-point rule's unit point...
Definition Roots.h:300
A type usable as a discrete space: a finite set of values.
Definition Discrete.h:72
constexpr AxisIndex< Path, sizeof...(I)> at(I... indices)
Definition Discrete.h:1071
constexpr Eigen::Index valueOf(S const &space, AxisIndex< Paths, N > const &... indices)
Definition Discrete.h:1112
An index in each leaf axis of the axis named by the path Path (a tag or a TagPath),...
Definition Discrete.h:1059
std::array< Eigen::Index, N > indices
one per leaf axis of the one named, in flat-index order
Definition Discrete.h:1060
constexpr Finite(Eigen::Index n)
n values of a run-time Finite.
Definition Discrete.h:177
friend bool operator==(Finite const &, Finite const &)=default
Equal when the cardinalities are; a fixed Finite is always equal.
static constexpr int MaxCardinality
a bound on it, or Eigen::Dynamic
Definition Discrete.h:172
static constexpr int Cardinality
the number of values, or Eigen::Dynamic
Definition Discrete.h:171
Finite()=default
A GridAxis is made like a Finite, with its number of cells.
Values named by the tag types Values, in order: struct Maneuver : Named<Cruise, Turn> {}...
Definition Discrete.h:195
static constexpr Eigen::Index index()
Definition Discrete.h:224
friend bool operator==(Named const &, Named const &)=default
Always equal: a Named has no state.
static constexpr int MaxCardinality
the same: a Named is fixed
Definition Discrete.h:198
static constexpr int Cardinality
the number of names
Definition Discrete.h:197
static constexpr bool contains
Whether Value names one of the values.
Definition Discrete.h:202
static constexpr Eigen::Index cardinality()
Definition Discrete.h:216