15 #ifndef OPENKALMAN_MEAN_HPP 16 #define OPENKALMAN_MEAN_HPP 28 template<fixed_pattern RowCoefficients, typed_matrix_nestable NestedMatrix> requires
29 (coordinates::dimension_of_v<RowCoefficients> == index_dimension_of_v<NestedMatrix, 0>) and
30 (not std::is_rvalue_reference_v<NestedMatrix>)
32 template<
typename RowCoefficients,
typename NestedMatrix>
34 struct Mean : oin::TypedMatrixBase<
35 Mean<RowCoefficients, NestedMatrix>, NestedMatrix, RowCoefficients, Dimensions<index_dimension_of_v<NestedMatrix, 1>>>
38 #ifndef __cpp_concepts 39 static_assert(fixed_pattern<RowCoefficients>);
40 static_assert(typed_matrix_nestable<NestedMatrix>);
41 static_assert(coordinates::dimension_of_v<RowCoefficients> == index_dimension_of_v<NestedMatrix, 0>);
42 static_assert(not std::is_rvalue_reference_v<NestedMatrix>);
45 using Scalar = scalar_type_of_t<NestedMatrix>;
49 using ColumnCoefficients = Dimensions<index_dimension_of_v<NestedMatrix, 1>>;
53 using Base = oin::TypedMatrixBase<Mean, NestedMatrix, RowCoefficients, ColumnCoefficients>;
62 template<mean Arg> requires
63 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
64 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
66 std::constructible_from<NestedMatrix, decltype(nested_object(std::declval<Arg&&>()))>
68 template<
typename Arg, std::enable_if_t<mean<Arg> and
69 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
70 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
71 stdex::constructible_from<NestedMatrix, decltype(
nested_object(std::declval<Arg&&>()))>,
int> = 0>
78 template<eucl
idean_transformed Arg> requires
79 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
80 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
81 requires(Arg&& arg) { NestedMatrix{from_euclidean<RowCoefficients>(
nested_object(std::forward<Arg>(arg)))}; }
83 template<
typename Arg, std::enable_if_t<eucl
idean_transformed<Arg> and
84 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
85 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
86 stdex::constructible_from<NestedMatrix,
87 decltype(from_eucl
idean<RowCoefficients>(nested_
object(std::declval<Arg&&>())))>,
int> = 0>
89 Mean(Arg&& arg) : Base {from_euclidean<RowCoefficients>(
nested_object(std::forward<Arg>(arg)))} {}
94 template<typed_matrix Arg> requires (not euclidean_transformed<Arg>) and (not mean<Arg>) and
95 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
96 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
97 requires(Arg&& arg) { NestedMatrix {wrap_angles<RowCoefficients>(
nested_object(std::forward<Arg>(arg)))}; }
99 template<
typename Arg, std::enable_if_t<typed_matrix<Arg> and not eucl
idean_transformed<Arg> and not mean<Arg> and
100 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
101 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>,
int> = 0>
107 #ifdef __cpp_concepts 108 template<typed_matrix_nestable Arg> requires (index_dimension_of_v<Arg, 0> == index_dimension_of_v<NestedMatrix, 0>) and
109 (index_dimension_of_v<Arg, 1> == index_dimension_of_v<NestedMatrix, 1>) and
110 requires(Arg&& arg) { NestedMatrix {wrap_angles<RowCoefficients>(std::declval<Arg>())}; }
112 template<
typename Arg, std::enable_if_t<typed_matrix_nestable<Arg> and
113 (index_dimension_of<Arg, 0>::value == index_dimension_of<NestedMatrix, 0>::value) and
114 (index_dimension_of<Arg, 1>::value == index_dimension_of<NestedMatrix, 1>::value) and
115 stdex::constructible_from<NestedMatrix, decltype(wrap_angles<RowCoefficients>(std::declval<Arg>()))>,
int> = 0>
117 explicit Mean(Arg&& arg) : Base {wrap_angles<RowCoefficients>(std::forward<Arg>(arg))} {}
121 #ifdef __cpp_concepts 122 template<std::convertible_to<const Scalar> ... Args> requires (
sizeof...(Args) > 0) and
123 requires(Args ... args) { NestedMatrix {wrap_angles<RowCoefficients>(
124 make_dense_object_from<NestedMatrix>(
static_cast<const Scalar>(args)...))}; }
126 template<
typename ... Args, std::enable_if_t<std::conjunction_v<std::is_convertible<Args, const Scalar>...> and
129 stdex::constructible_from<NestedMatrix, decltype(wrap_angles<RowCoefficients>(std::declval<NestedMatrix>()))>,
133 : Base {wrap_angles<RowCoefficients>(make_dense_object_from<NestedMatrix>(
static_cast<const Scalar>(args)...))} {}
139 #ifdef __cpp_concepts 140 template<mean Arg> requires (not std::derived_from<std::decay_t<Arg>,
Mean>) and
141 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
144 template<
typename Arg, std::enable_if_t<mean<Arg> and (not std::is_base_of_v<Mean, std::decay_t<Arg>>) and
145 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
146 std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, nested_
object_of_t<Arg&&>>,
int> = 0>
150 if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
161 #ifdef __cpp_concepts 162 template<eucl
idean_transformed Arg> requires
163 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
164 std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, decltype(from_euclidean<RowCoefficients>(std::declval<
nested_object_of_t<Arg>>()))>
166 template<
typename Arg, std::enable_if_t<eucl
idean_transformed<Arg> and
167 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
168 std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, decltype(from_eucl
idean<RowCoefficients>(std::declval<nested_
object_of_t<Arg>>()))>,
int> = 0>
172 if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
174 Base::operator=(from_euclidean<RowCoefficients>(
nested_object(std::forward<Arg>(other))));
184 #ifdef __cpp_concepts 185 template<typed_matrix Arg> requires (not mean<Arg>) and (not euclidean_transformed<Arg>) and
186 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and has_untyped_index<Arg, 1> and
187 std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, decltype(wrap_angles<RowCoefficients>(std::declval<
nested_object_of_t<Arg>>()))>
189 template<
typename Arg, std::enable_if_t<typed_matrix<Arg> and
190 (not mean<Arg>) and (not eucl
idean_transformed<Arg>) and
191 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and has_untyped_index<Arg, 1> and
192 std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, decltype(wrap_angles<RowCoefficients>(std::declval<nested_
object_of_t<Arg>>()))>,
int> = 0>
196 if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
198 Base::operator=(wrap_angles<RowCoefficients>(
nested_object(std::forward<Arg>(other))));
205 #ifdef __cpp_concepts 206 template<typed_matrix_nestable Arg> requires std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, Arg&&>
208 template<
typename Arg, std::enable_if_t<typed_matrix_nestable<Arg> and
209 std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, Arg&&>,
int> = 0>
213 if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
215 Base::operator=(wrap_angles<RowCoefficients>(std::forward<Arg>(arg)));
224 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
233 #ifdef __cpp_concepts 234 template<typed_matrix Arg> requires
235 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
236 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
237 (not euclidean_transformed<Arg>)
239 template<
typename Arg, std::enable_if_t<typed_matrix<Arg> and
240 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
241 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
242 (not eucl
idean_transformed<Arg>),
int> = 0>
246 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
256 #ifdef __cpp_concepts 257 template<distribution Arg> requires (
compares_with<
typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>)
259 template<
typename Arg, std::enable_if_t<distribution<Arg> and
260 (compares_with<
typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>),
int> = 0>
264 apply_columnwise([&arg](
auto& col){
265 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
266 col += arg().nested_object();
268 col = wrap_angles<RowCoefficients>(col + arg().nested_object());
277 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
286 #ifdef __cpp_concepts 287 template<typed_matrix Arg> requires
288 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>and
289 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>and
290 (not euclidean_transformed<Arg>)
292 template<
typename Arg, std::enable_if_t<typed_matrix<Arg> and
293 compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>and
294 compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>and
295 (not eucl
idean_transformed<Arg>),
int> = 0>
299 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
309 #ifdef __cpp_concepts 310 template<distribution Arg> requires (
compares_with<
typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>)
312 template<
typename Arg, std::enable_if_t<distribution<Arg> and
313 (compares_with<
typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>),
int> = 0>
317 apply_columnwise([&arg](
auto& col){
318 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
319 col -= arg().nested_object();
321 col = wrap_angles<RowCoefficients>(col - arg().nested_object());
328 #ifdef __cpp_concepts 329 template<std::convertible_to<Scalar> S>
331 template<
typename S, std::enable_if_t<stdex::convertible_to<S, Scalar>,
int> = 0>
335 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
344 #ifdef __cpp_concepts 345 template<std::convertible_to<Scalar> S>
347 template<
typename S, std::enable_if_t<stdex::convertible_to<S, Scalar>,
int> = 0>
351 if constexpr(coordinates::euclidean_pattern<RowCoefficients>)
360 template<
typename C = RowCoefficients,
typename Arg>
361 static auto make(Arg&& arg)
374 #ifdef __cpp_concepts 375 template<typed_matrix_nestable V>
377 template<
typename V, std::enable_if_t<typed_matrix_nestable<V>,
int> = 0>
383 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2 385 template<typed_matrix V> requires (not euclidean_transformed<V>)
387 template<
typename V, std::enable_if_t<typed_matrix<V> and not eucl
idean_transformed<V>,
int> = 0>
390 wrap_angles<vector_space_descriptor_of_t<V, 0>>(
nested_object(std::forward<V>(std::declval<V>()))))>>;
394 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2 396 template<eucl
idean_transformed V>
398 template<
typename V, std::enable_if_t<eucl
idean_transformed<V>,
int> = 0>
413 #ifdef __cpp_concepts 414 template<fixed_pattern StaticDescriptor, typed_matrix_nestable M> requires
415 (coordinates::dimension_of_v<StaticDescriptor> == index_dimension_of_v<M, 0>)
417 template<
typename StaticDescriptor,
typename M, std::enable_if_t<fixed_pattern<StaticDescriptor> and
418 typed_matrix_nestable<M> and (coordinates::dimension_of_v<StaticDescriptor> == index_dimension_of<M, 0>::value),
int> = 0>
422 constexpr
auto rows = index_dimension_of_v<M, 0>;
423 using Coeffs = std::conditional_t<std::is_void_v<StaticDescriptor>, Dimensions<rows>, StaticDescriptor>;
424 auto&& b = wrap_angles<Coeffs>(std::forward<M>(m));
using B = decltype(b);
433 #ifdef __cpp_concepts 434 template<typed_matrix_nestable M>
436 template<
typename M, std::enable_if_t<typed_matrix_nestable<M>,
int> = 0>
440 using Coeffs = Dimensions<index_dimension_of_v<M, 0>>;
441 return make_mean<Coeffs>(std::forward<M>(m));
450 #ifdef __cpp_concepts 451 template<typed_matrix Arg> requires has_untyped_index<Arg, 1>
453 template<
typename Arg, std::enable_if_t<typed_matrix<Arg> and has_untyped_index<Arg, 1>,
int> = 0>
457 using C = vector_space_descriptor_of_t<Arg, 0>;
458 if constexpr(euclidean_transformed<Arg>)
459 return make_mean<C>(
nested_object(from_euclidean<C>(std::forward<Arg>(arg))));
472 #ifdef __cpp_concepts 473 template<fixed_pattern StaticDescriptor, typed_matrix_nestable M> requires
474 (index_dimension_of_v<M, 0> == coordinates::dimension_of_v<StaticDescriptor>)
476 template<
typename StaticDescriptor,
typename M, std::enable_if_t<
477 fixed_pattern<StaticDescriptor> and typed_matrix_nestable<M> and
492 #ifdef __cpp_concepts 493 template<typed_matrix_nestable M>
495 template<
typename M, std::enable_if_t<typed_matrix_nestable<M>,
int> = 0>
499 return make_mean<Dimensions<index_dimension_of_v<M, 0>>, M>();
509 template<
typename Coeffs,
typename NestedMatrix>
512 using scalar_type = scalar_type_of_t<NestedMatrix>;
514 template<
typename Arg>
517 template<
typename Arg,
typename N>
520 if constexpr (values::fixed<N>)
522 if constexpr (n == 0_uz)
return arg.my_dimension;
525 else if constexpr (coordinates::uniform_pattern<Coeffs>)
527 return coordinates::uniform_pattern_component_of_t<Coeffs>;
531 if (n == 0)
return DynamicDescriptor<scalar_type> {arg.my_dimension};
537 template<
typename Arg>
544 template<
typename Arg>
545 static constexpr
auto get_constant(
const Arg& arg)
551 template<
typename Arg>
552 static constexpr
auto get_constant_diagonal(
const Arg& arg)
554 if constexpr (coordinates::euclidean_pattern<Coeffs>)
555 return constant_diagonal_value {arg.nestedExpression()};
557 return std::monostate {};
561 template<applicability b>
562 static constexpr
bool one_dimensional = OpenKalman::one_dimensional<NestedMatrix, b>;
565 template<applicability b>
566 static constexpr
bool is_square = OpenKalman::square_shaped<NestedMatrix, b>;
569 template<triangle_type t>
570 static constexpr
bool triangle_type_value = coordinates::euclidean_pattern<Coeffs> and triangular_matrix<NestedMatrix, t>;
573 static constexpr
bool is_triangular_adapter =
false;
576 static constexpr
bool is_hermitian = coordinates::euclidean_pattern<Coeffs> and hermitian_matrix<NestedMatrix>;
579 #ifdef __cpp_lib_concepts 580 template<
typename Arg,
typename...I> requires element_gettable<nested_object_of_t<Arg&&>,
sizeof...(I)>
584 static constexpr decltype(
auto)
get(Arg&& arg, I...i)
590 #ifdef __cpp_lib_concepts 591 template<
typename Arg,
typename I,
typename...Is> requires writable_by_component<nested_object_of_t<Arg&>, 1 +
sizeof...(Is)>
593 template<
typename Arg,
typename I,
typename...Is, std::enable_if_t<writable_by_component<
typename nested_object_of<Arg&>::type, 1 +
sizeof...(Is)>,
int> = 0>
595 static constexpr
void set(Arg& arg,
const scalar_type_of_t<Arg>& s, I i, Is...is)
597 if constexpr(wrapped_mean<Arg>)
599 const auto get_coeff = [&arg, is...] (
const std::size_t row) {
602 const auto set_coeff = [&arg, is...](
const std::size_t row,
const scalar_type_of_t<Arg>
value) {
605 coordinates::set_wrapped_component<Coeffs>(Coeffs{}, i, s, set_coeff, get_coeff);
617 #ifdef __cpp_lib_concepts 618 template<
typename Arg> requires raw_data_defined_for<NestedMatrix>
620 template<
typename Arg, std::enable_if_t<raw_data_defined_for<NestedMatrix>,
int> = 0>
622 static constexpr
auto *
const 626 static constexpr data_layout layout = layout_of_v<NestedMatrix>;
decltype(auto) constexpr from_euclidean(Arg &&arg, const V &v)
Project the Euclidean vector space associated with index 0 to coordinates::pattern v after applying d...
Definition: from_euclidean.hpp:35
typename nested_object_of< T >::type nested_object_of_t
Helper type for nested_object_of.
Definition: nested_object_of.hpp:58
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:56
Mean(Args ... args)
Construct from a list of coefficients.
Definition: Mean.hpp:132
A set of one or more column vectors, each representing a statistical mean.
Definition: forward-class-declarations.hpp:321
auto & operator+=(const Mean &other)
Increment from another mean.
Definition: Mean.hpp:222
constexpr auto count_indices(const T &)
Get the number of indices necessary to address all the components of an indexible object...
Definition: count_indices.hpp:51
auto make_mean(M &&m)
Make a Mean from a typed_matrix_nestable, specifying the row fixed_pattern.
Definition: Mean.hpp:420
decltype(auto) constexpr get_pattern_collection(T &&t)
Get the coordinates::pattern_collection associated with indexible object T.
Definition: get_pattern_collection.hpp:59
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
auto & operator=(Arg &&arg)
Assign from a compatible typed_matrix_nestable.
Definition: Mean.hpp:211
A wrapper type's nested object type, if it exists.
Definition: nested_object_of.hpp:34
Mean(Arg &&arg)
Construct from a compatible mean.
Definition: Mean.hpp:73
auto & operator+=(Arg &&other)
Increment from another typed matrix.
Definition: Mean.hpp:244
The root namespace for OpenKalman.
Definition: basics.hpp:34
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
Definition: object_traits.hpp:38
auto & operator*=(const S s)
Multiply by a scale factor.
Definition: Mean.hpp:333
auto & operator-=(const Mean &other)
Decrement from another mean and wrap result.
Definition: Mean.hpp:275
auto & operator-=(Arg &&other)
Decrement from another typed matrix and wrap result.
Definition: Mean.hpp:297
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
auto & operator/=(const S s)
Divide by a scale factor.
Definition: Mean.hpp:349
auto & operator+=(const Arg &arg)
Add a stochastic value to each column of the mean, based on a distribution.
Definition: Mean.hpp:262
The dimension of an index for a matrix, expression, or array.
Definition: index_dimension_of.hpp:35
Mean(V &&) -> Mean< Dimensions< index_dimension_of_v< V, 0 >>, passable_t< V >>
Deduce template parameters from a typed_matrix_nestable, assuming untyped coordinates::pattern.
scalar_type_of_t< MeanNestedMatrix > Scalar
Scalar type for this matrix.
Definition: Mean.hpp:45
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:35
constexpr bool compares_with
Compares two coordinates::pattern objects.
Definition: compares_with.hpp:475
Definition: basics.hpp:48
auto & operator=(Arg &&other)
Assign from a compatible mean.
Definition: Mean.hpp:148
auto & operator-=(const Arg &arg)
Subtract a stochastic value to each column of the mean, based on a distribution.
Definition: Mean.hpp:315