OpenKalman
EuclideanMean.hpp
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2019-2021 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
11 #ifndef OPENKALMAN_EUCLIDEANMEAN_HPP
12 #define OPENKALMAN_EUCLIDEANMEAN_HPP
13 
14 namespace OpenKalman
15 {
16  namespace oin = OpenKalman::internal;
17 
18  // --------------- //
19  // EuclideanMean //
20  // --------------- //
21 
22 #ifdef __cpp_concepts
23  template<fixed_pattern RowCoefficients, typed_matrix_nestable NestedMatrix> requires
24  (coordinates::stat_dimension_of_v<RowCoefficients> == index_dimension_of_v<NestedMatrix, 0>) and
25  (not std::is_rvalue_reference_v<NestedMatrix>)
26 #else
27  template<typename RowCoefficients, typename NestedMatrix>
28 #endif
29  struct EuclideanMean : oin::TypedMatrixBase<EuclideanMean<RowCoefficients, NestedMatrix>, NestedMatrix,
30  RowCoefficients, Dimensions<index_dimension_of_v<NestedMatrix, 1>>>
31  {
32 
33 #ifndef __cpp_concepts
34  static_assert(fixed_pattern<RowCoefficients>);
35  static_assert(typed_matrix_nestable<NestedMatrix>);
36  static_assert(coordinates::stat_dimension_of_v<RowCoefficients> == index_dimension_of_v<NestedMatrix, 0>);
37  static_assert(not std::is_rvalue_reference_v<NestedMatrix>);
38 #endif
39 
40  using Scalar = scalar_type_of_t<NestedMatrix>;
41 
42  protected:
43 
44  using ColumnCoefficients = Dimensions<index_dimension_of_v<NestedMatrix, 1>>;
45 
46  private:
47 
48  using Base = oin::TypedMatrixBase<EuclideanMean, NestedMatrix, RowCoefficients, ColumnCoefficients>;
49 
50  public:
51 
52  using Base::Base;
53 
54 
56 #ifdef __cpp_concepts
57  template<euclidean_transformed Arg> requires
58  (compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>) and
59  (compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>) and
60  //requires(Arg&& arg) { NestedMatrix {nested_object(std::forward<Arg>(arg))}; } // \todo doesn't work in GCC 10
61  std::constructible_from<NestedMatrix, decltype(nested_object(std::declval<Arg&&>()))>
62 #else
63  template<typename Arg, std::enable_if_t<euclidean_transformed<Arg> and
64  (compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>) and
65  (compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>) and
66  stdex::constructible_from<NestedMatrix, decltype(nested_object(std::declval<Arg&&>()))>, int> = 0>
67 #endif
68  EuclideanMean(Arg&& arg) : Base {nested_object(std::forward<Arg>(arg))} {}
69 
70 
72 #ifdef __cpp_concepts
73  template<typed_matrix Arg> requires (not euclidean_transformed<Arg>) and
74  (compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>) and
75  (compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>) and
76  requires(Arg&& arg) { NestedMatrix {to_euclidean<RowCoefficients>(nested_object(std::forward<Arg>(arg)))}; }
77 #else
78  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and (not euclidean_transformed<Arg>) and
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  stdex::constructible_from<NestedMatrix,
82  decltype(to_euclidean<RowCoefficients>(nested_object(std::declval<Arg&&>())))>, int> = 0>
83 #endif
84  EuclideanMean(Arg&& arg)
85  : Base {to_euclidean<RowCoefficients>(nested_object(std::forward<Arg>(arg)))} {}
86 
87 
89 #ifdef __cpp_concepts
90  template<typed_matrix_nestable Arg> requires (index_dimension_of_v<Arg, 0> == index_dimension_of_v<NestedMatrix, 0>) and
91  (index_dimension_of_v<Arg, 1> == index_dimension_of_v<NestedMatrix, 1>) and
92  std::constructible_from<NestedMatrix, Arg&&>
93 #else
94  template<typename Arg, std::enable_if_t<typed_matrix_nestable<Arg> and
95  (index_dimension_of<Arg, 0>::value == index_dimension_of<NestedMatrix, 0>::value) and
96  (index_dimension_of<Arg, 1>::value == index_dimension_of<NestedMatrix, 1>::value) and
97  stdex::constructible_from<NestedMatrix, Arg&&>, int> = 0>
98 #endif
99  EuclideanMean(Arg&& arg) : Base {std::forward<Arg>(arg)} {}
100 
101 
106 #ifdef __cpp_concepts
107  template<typed_matrix Arg> requires (not std::derived_from<std::decay_t<Arg>, EuclideanMean>) and
108  (euclidean_transformed<Arg> or coordinates::euclidean_pattern<RowCoefficients>) and
109  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
110  has_untyped_index<Arg, 1> and std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, nested_object_of_t<Arg&&>>
111 #else
112  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and
113  (not std::is_base_of_v<EuclideanMean, std::decay_t<Arg>>) and
114  (euclidean_transformed<Arg> or coordinates::euclidean_pattern<RowCoefficients>) and
115  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
116  has_untyped_index<Arg, 1> and std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, nested_object_of_t<Arg&&>>, int> = 0>
117 #endif
118  auto& operator=(Arg&& other)
119  {
120  if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
121  {
122  Base::operator=(nested_object(std::forward<Arg>(other)));
123  }
124  return *this;
125  }
126 
127 
132 #ifdef __cpp_concepts
133  template<typed_matrix Arg> requires (not std::derived_from<std::decay_t<Arg>, EuclideanMean>) and
134  (not euclidean_transformed<Arg> and fixed_pattern<RowCoefficients>) and
135  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
136  has_untyped_index<Arg, 1> and std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, nested_object_of_t<Arg&&>>
137 #else
138  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and
139  (not std::is_base_of_v<EuclideanMean, std::decay_t<Arg>>) and
140  (not euclidean_transformed<Arg> and fixed_pattern<RowCoefficients>) and
141  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
142  has_untyped_index<Arg, 1> and std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, nested_object_of_t<Arg&&>>, int> = 0>
143 #endif
144  auto& operator=(Arg&& other)
145  {
146  if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
147  {
148  Base::operator=(to_euclidean<RowCoefficients>(nested_object(std::forward<Arg>(other))));
149  }
150  return *this;
151  }
152 
153 
157 #ifdef __cpp_concepts
158  template<typed_matrix_nestable Arg> requires std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, Arg&&>
159 #else
160  template<typename Arg, std::enable_if_t<typed_matrix_nestable<Arg> and std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, Arg&&>, int> = 0>
161 #endif
162  auto& operator=(Arg&& arg)
163  {
164  if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
165  {
166  Base::operator=(std::forward<Arg>(arg));
167  }
168  return *this;
169  }
170 
171 
175  auto& operator+=(const EuclideanMean& other)
176  {
177  this->nested_object() += other.nested_object();
178  return *this;
179  }
180 
181 
183 #ifdef __cpp_concepts
184  template<typed_matrix Arg> requires
185  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
186  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
187  (coordinates::euclidean_pattern<RowCoefficients> or euclidean_transformed<Arg>)
188 #else
189  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and
190  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
191  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
192  (coordinates::euclidean_pattern<RowCoefficients> or euclidean_transformed<Arg>), int> = 0>
193 #endif
194  auto& operator+=(Arg&& other)
195  {
196  this->nested_object() += nested_object(std::forward<Arg>(other));
197  return *this;
198  }
199 
200 
202 #ifdef __cpp_concepts
203  template<distribution Arg> requires coordinates::euclidean_pattern<RowCoefficients> and
204  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>)
205 #else
206  template<typename Arg, std::enable_if_t<distribution<Arg> and coordinates::euclidean_pattern<RowCoefficients> and
207  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>), int> = 0>
208 #endif
209  auto& operator+=(const Arg& arg)
210  {
211  apply_columnwise([&arg](auto& col){ col += arg().nested_object(); }, this->nested_object());
212  return *this;
213  }
214 
215 
217  auto& operator-=(const EuclideanMean& other)
218  {
219  this->nested_object() -= other.nested_object();
220  return *this;
221  }
222 
223 
225 #ifdef __cpp_concepts
226  template<typed_matrix Arg> requires
227  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
228  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
229  (coordinates::euclidean_pattern<RowCoefficients> or euclidean_transformed<Arg>)
230 #else
231  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and
232  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>and
233  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>and
234  (coordinates::euclidean_pattern<RowCoefficients> or euclidean_transformed<Arg>), int> = 0>
235 #endif
236  auto& operator-=(Arg&& other)
237  {
238  this->nested_object() -= nested_object(std::forward<Arg>(other));
239  return *this;
240  }
241 
242 
244 #ifdef __cpp_concepts
245  template<distribution Arg> requires coordinates::euclidean_pattern<RowCoefficients> and
246  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>)
247 #else
248  template<typename Arg, std::enable_if_t<distribution<Arg> and coordinates::euclidean_pattern<RowCoefficients> and
249  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>), int> = 0>
250 #endif
251  auto& operator-=(const Arg& arg)
252  {
253  apply_columnwise([&arg](auto& col){ col -= arg().nested_object(); }, this->nested_object());
254  return *this;
255  }
256 
257  protected:
258 
259  template<typename C = RowCoefficients, typename Arg>
260  static auto make(Arg&& arg)
261  {
262  return EuclideanMean<C, std::decay_t<Arg>>(std::forward<Arg>(arg));
263  }
264 
265  };
266 
267 
268  // ------------------ //
269  // Deduction guides //
270  // ------------------ //
271 
273 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2
274  // \todo Unlike SFINAE version, this incorrectly matches V==EuclideanMean in both GCC 10.1.0 and clang 10.0.0:
275  template<typed_matrix V> requires (not euclidean_transformed<V>) and has_untyped_index<V, 1> and
276  (coordinates::stat_dimension_of_v<vector_space_descriptor_of_t<V, 0>> == index_dimension_of_v<V, 0>)
277 #else
278  template<typename V, std::enable_if_t<typed_matrix<V> and not euclidean_transformed<V> and has_untyped_index<V, 1> and
279 coordinates::stat_dimension_of_v<vector_space_descriptor_of_t<V, 0>> == index_dimension_of_v<V, 0>, int> = 0>
280 #endif
281  EuclideanMean(V&&)
282  -> EuclideanMean<vector_space_descriptor_of_t<V, 0>, std::remove_reference_t<
283  decltype(to_euclidean<vector_space_descriptor_of_t<V, 0>>(nested_object(std::declval<V&&>())))>>;
284 
285 
287 #ifdef __cpp_concepts
288  template<euclidean_transformed V>
289 #else
290  template<typename V, std::enable_if_t<typed_matrix<V> and euclidean_transformed<V>, int> = 0>
291 #endif
293 
294 
296 #ifdef __cpp_concepts
297  template<typed_matrix_nestable V>
298 #else
299  template<typename V, std::enable_if_t<typed_matrix_nestable<V>, int> = 0>
300 #endif
301  explicit EuclideanMean(V&&) -> EuclideanMean<Dimensions<index_dimension_of_v<V, 0>>, passable_t<V>>;
302 
303 
304  // ----------------------------- //
305  // Make functions //
306  // ----------------------------- //
307 
313 #ifdef __cpp_concepts
314  template<fixed_pattern StaticDescriptor, typed_matrix_nestable M> requires
315  (coordinates::stat_dimension_of_v<StaticDescriptor> == index_dimension_of_v<M, 0>)
316 #else
317  template<typename StaticDescriptor, typename M, std::enable_if_t<fixed_pattern<StaticDescriptor> and
318  typed_matrix_nestable<M> and (coordinates::stat_dimension_of_v<StaticDescriptor> == index_dimension_of<M, 0>::value), int> = 0>
319 #endif
320  auto make_euclidean_mean(M&& arg)
321  {
322  return EuclideanMean<StaticDescriptor, passable_t<M>>(std::forward<M>(arg));
323  }
324 
325 
330 #ifdef __cpp_concepts
331  template<typed_matrix_nestable M>
332 #else
333  template<typename M, std::enable_if_t<typed_matrix_nestable<M>, int> = 0>
334 #endif
336  {
337  using Coeffs = Dimensions<index_dimension_of_v<M, 0>>;
338  return make_mean<Coeffs>(std::forward<M>(m));
339  }
340 
341 
347 #ifdef __cpp_concepts
348  template<typed_matrix Arg> requires has_untyped_index<Arg, 1>
349 #else
350  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and has_untyped_index<Arg, 1>, int> = 0>
351 #endif
352  inline auto make_euclidean_mean(Arg&& arg)
353  {
354  using C = vector_space_descriptor_of_t<Arg, 0>;
355  if constexpr(euclidean_transformed<Arg>)
356  return make_euclidean_mean<C>(nested_object(std::forward<Arg>(arg)));
357  else
358  return make_euclidean_mean<C>(nested_object(to_euclidean<C>(std::forward<Arg>(arg))));
359  }
360 
361 
369 #ifdef __cpp_concepts
370  template<fixed_pattern StaticDescriptor, typed_matrix_nestable M> requires
371  (coordinates::stat_dimension_of_v<StaticDescriptor> == index_dimension_of_v<M, 0>)
372 #else
373  template<typename StaticDescriptor, typename M, std::enable_if_t<fixed_pattern<StaticDescriptor> and
374  typed_matrix_nestable<M> and (coordinates::stat_dimension_of_v<StaticDescriptor> == index_dimension_of<M, 0>::value), int> = 0>
375 #endif
377  {
379  }
380 
381 
388 #ifdef __cpp_concepts
389  template<typed_matrix_nestable M>
390 #else
391  template<typename M, std::enable_if_t<typed_matrix_nestable<M>, int> = 0>
392 #endif
394  {
395  return make_euclidean_mean<Dimensions<index_dimension_of_v<M, 0>>, M>();
396  }
397 
398 
399  // ------------------------- //
400  // Interfaces //
401  // ------------------------- //
402 
403  namespace interface
404  {
405  template<typename Coeffs, typename NestedMatrix>
406  struct object_traits<EuclideanMean<Coeffs, NestedMatrix>>
407  {
408  static const bool is_specialized = true;
409 
410  using scalar_type = scalar_type_of_t<NestedMatrix>;
411 
412  template<typename Arg>
413  static constexpr auto count_indices(const Arg& arg) { return OpenKalman::count_indices(nested_object(arg)); }
414 
415  template<typename Arg, typename N>
416  static constexpr auto get_pattern_collection(const Arg& arg, N n)
417  {
418  if constexpr (values::fixed<N>)
419  {
420  if constexpr (n == 0_uz) return arg.my_dimension;
422  }
423  else if constexpr (coordinates::uniform_pattern<Coeffs>)
424  {
425  return coordinates::uniform_pattern_component_of_t<Coeffs>;
426  }
427  else
428  {
429  if (n == 0) return DynamicDescriptor<scalar_type> {arg.my_dimension};
430  else return DynamicDescriptor<scalar_type> {OpenKalman::get_pattern_collection(nested_object(arg), n)};
431  }
432  }
433 
434 
435  template<typename Arg>
436  static decltype(auto) nested_object(Arg&& arg)
437  {
438  return std::forward<Arg>(arg).nested_object();
439  }
440 
441 
442  template<typename Arg>
443  static constexpr auto get_constant(const Arg& arg)
444  {
445  if constexpr (coordinates::euclidean_pattern<Coeffs>)
446  return constant_value {arg.nestedExpression()};
447  else
448  return std::monostate {};
449  }
450 
451 
452  template<typename Arg>
453  static constexpr auto get_constant_diagonal(const Arg& arg)
454  {
455  if constexpr (coordinates::euclidean_pattern<Coeffs>)
456  return constant_diagonal_value {arg.nestedExpression()};
457  else
458  return std::monostate {};
459  }
460 
461 
462  template<applicability b>
463  static constexpr bool one_dimensional = OpenKalman::one_dimensional<NestedMatrix, b>;
464 
465 
466  template<applicability b>
467  static constexpr bool is_square = OpenKalman::square_shaped<NestedMatrix, b>;
468 
469 
470  template<triangle_type t>
471  static constexpr bool triangle_type_value = coordinates::euclidean_pattern<Coeffs> and triangular_matrix<NestedMatrix, t>;
472 
473 
474  static constexpr bool is_triangular_adapter = false;
475 
476 
477  static constexpr bool is_hermitian = coordinates::euclidean_pattern<Coeffs> and hermitian_matrix<NestedMatrix>;
478 
479 
480  #ifdef __cpp_lib_concepts
481  template<typename Arg, typename...I> requires element_gettable<nested_object_of_t<Arg&&>, sizeof...(I)>
482  #else
483  template<typename Arg, typename...I, std::enable_if_t<element_gettable<typename nested_object_of<Arg&&>::type, sizeof...(I)>, int> = 0>
484  #endif
485  static constexpr decltype(auto)
486  get(Arg&& arg, I...i)
487  {
488  return get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), i...);
489  }
490 
491 
492  #ifdef __cpp_lib_concepts
493  template<typename Arg, typename I, typename...Is> requires writable_by_component<nested_object_of_t<Arg&>, 1 + sizeof...(Is)>
494  #else
495  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>
496  #endif
497  static constexpr void
498  set(Arg& arg, const scalar_type_of_t<Arg>& s, I i, Is...is)
499  {
500  set_component(OpenKalman::nested_object(arg), s, i, is...);
501  }
502 
503 
504  static constexpr bool is_writable = library_interface<std::decay_t<NestedMatrix>>::is_writable;
505 
506 
507 #ifdef __cpp_lib_concepts
508  template<typename Arg> requires raw_data_defined_for<NestedMatrix> and coordinates::euclidean_pattern<Coeffs>
509 #else
510  template<typename Arg, std::enable_if_t<raw_data_defined_for<NestedMatrix> and coordinates::euclidean_pattern<Coeffs>, int> = 0>
511 #endif
512  static constexpr auto * const
513  raw_data(Arg& arg) { return internal::raw_data(OpenKalman::nested_object(arg)); }
514 
515 
516  static constexpr data_layout layout = coordinates::euclidean_pattern<Coeffs> ? layout_of_v<NestedMatrix> : data_layout::none;
517 
518  };
519 
520  }
521 
522 
523 }
524 
525 
526 #endif
EuclideanMean(Arg &&arg)
Construct from a compatible Euclidean-transformed matrix.
Definition: EuclideanMean.hpp:68
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
auto & operator+=(Arg &&other)
Increment from another typed matrix.
Definition: EuclideanMean.hpp:194
scalar_type_of_t< OutputEuclideanMeanMatrix > Scalar
Scalar type for this matrix.
Definition: EuclideanMean.hpp:40
auto & operator-=(const EuclideanMean &other)
Decrement from another EuclideanMean.
Definition: EuclideanMean.hpp:217
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
decltype(auto) constexpr get_pattern_collection(T &&t)
Get the coordinates::pattern_collection associated with indexible object T.
Definition: get_pattern_collection.hpp:59
auto & operator=(Arg &&arg)
Assign from a compatible typed_matrix_nestable.
Definition: EuclideanMean.hpp:162
A wrapper type&#39;s nested object type, if it exists.
Definition: nested_object_of.hpp:34
auto & operator-=(Arg &&other)
Decrement from another typed matrix.
Definition: EuclideanMean.hpp:236
Similar to a Mean, but the coefficients are transformed into Euclidean space, based on their type...
Definition: EuclideanMean.hpp:29
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
auto make_euclidean_mean(M &&arg)
Make a EuclideanMean from a typed_matrix_nestable, specifying the row coefficients.
Definition: EuclideanMean.hpp:320
Definition: object_traits.hpp:38
constexpr auto stat_dimension_of_v
Helper template for coordinates::stat_dimension_of.
Definition: stat_dimension_of.hpp:56
decltype(auto) constexpr to_euclidean(Arg &&arg)
Project the vector space associated with index 0 to a Euclidean space for applying directional statis...
Definition: to_euclidean.hpp:38
auto & operator-=(const Arg &arg)
Subtract a stochastic value to each column of the matrix, based on a distribution.
Definition: EuclideanMean.hpp:251
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:35
auto & operator=(Arg &&other)
Assign from a compatible typed_matrix.
Definition: EuclideanMean.hpp:118
auto & operator+=(const EuclideanMean &other)
Increment from another EuclideanMean.
Definition: EuclideanMean.hpp:175
constexpr bool compares_with
Compares two coordinates::pattern objects.
Definition: compares_with.hpp:475
Definition: basics.hpp:48
auto & operator+=(const Arg &arg)
Add a stochastic value to each column of the matrix, based on a distribution.
Definition: EuclideanMean.hpp:209