OpenKalman
Matrix.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) 2018-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_MATRIX_HPP
12 #define OPENKALMAN_MATRIX_HPP
13 
14 namespace OpenKalman
15 {
16  namespace oin = OpenKalman::internal;
17 
18  // --------------------- //
19  // Matrix //
20  // --------------------- //
21 
22 #ifdef __cpp_concepts
23  template<fixed_pattern RowCoefficients, fixed_pattern ColumnCoefficients, typed_matrix_nestable NestedMatrix>
24  requires (coordinates::dimension_of_v<RowCoefficients> == index_dimension_of_v<NestedMatrix, 0>) and
25  (coordinates::dimension_of_v<ColumnCoefficients> == index_dimension_of_v<NestedMatrix, 1>) and
26  (not std::is_rvalue_reference_v<NestedMatrix>) and
27  (dynamic_pattern<RowCoefficients> == dynamic_dimension<NestedMatrix, 0>) and
28  (dynamic_pattern<ColumnCoefficients> == dynamic_dimension<NestedMatrix, 1>)
29 #else
30  template<typename RowCoefficients, typename ColumnCoefficients, typename NestedMatrix>
31 #endif
32  struct Matrix : oin::TypedMatrixBase<Matrix<RowCoefficients, ColumnCoefficients, NestedMatrix>, NestedMatrix,
33  RowCoefficients, ColumnCoefficients>
34  {
35 
36 #ifndef __cpp_concepts
37  static_assert(fixed_pattern<RowCoefficients>);
38  static_assert(fixed_pattern<ColumnCoefficients>);
39  static_assert(typed_matrix_nestable<NestedMatrix>);
40  static_assert(coordinates::dimension_of_v<RowCoefficients> == index_dimension_of_v<NestedMatrix, 0>);
41  static_assert(coordinates::dimension_of_v<ColumnCoefficients> == index_dimension_of_v<NestedMatrix, 1>);
42  static_assert(not std::is_rvalue_reference_v<NestedMatrix>);
43  static_assert(dynamic_pattern<RowCoefficients> == dynamic_dimension<NestedMatrix, 0>);
44  static_assert(dynamic_pattern<ColumnCoefficients> == dynamic_dimension<NestedMatrix, 1>);
45 #endif
46 
48 
49  private:
50 
51  using Base = oin::TypedMatrixBase<Matrix, NestedMatrix, RowCoefficients, ColumnCoefficients>;
52 
53  public:
54 
55  using Base::Base;
56 
57 
59 #ifdef __cpp_concepts
60  template<typed_matrix Arg> requires (not std::derived_from<std::decay_t<Arg>, Matrix>) and
61  (not euclidean_transformed<Arg>) and
62  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
63  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
64  //requires(Arg&& arg) { NestedMatrix {nested_object(std::forward<Arg>(arg))}; } // \todo 't work in GCC 10
65  std::constructible_from<NestedMatrix, decltype(nested_object(std::declval<Arg&&>()))>
66 #else
67  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and not std::is_base_of_v<Matrix, std::decay_t<Arg>> and
68  not euclidean_transformed<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  std::is_constructible_v<NestedMatrix, decltype(nested_object(std::declval<Arg&&>()))>, int> = 0>
72 #endif
73  Matrix(Arg&& arg) : Base {nested_object(std::forward<Arg>(arg))} {}
74 
75 
77 #ifdef __cpp_concepts
78  template<euclidean_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)))}; }
82 #else
83  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and euclidean_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  std::is_constructible_v<NestedMatrix,
87  decltype(from_euclidean<RowCoefficients>(nested_object(std::declval<Arg&&>())))>, int> = 0>
88 #endif
89  Matrix(Arg&& arg)
90  : Base {from_euclidean<RowCoefficients>(nested_object(std::forward<Arg>(arg)))} {}
91 
92 
94 #ifdef __cpp_concepts
95  template<typed_matrix_nestable Arg> requires (index_dimension_of_v<Arg, 0> == index_dimension_of_v<NestedMatrix, 0>) and
96  (index_dimension_of_v<Arg, 1> == index_dimension_of_v<NestedMatrix, 1>) and
97  std::constructible_from<NestedMatrix, Arg&&>
98 #else
99  template<typename Arg, std::enable_if_t<typed_matrix_nestable<Arg> and
100  (index_dimension_of<Arg, 0>::value == index_dimension_of<NestedMatrix, 0>::value) and
101  (index_dimension_of<Arg, 1>::value == index_dimension_of<NestedMatrix, 1>::value) and
102  std::is_constructible_v<NestedMatrix, Arg&&>, int> = 0>
103 #endif
104  explicit Matrix(Arg&& arg) : Base {std::forward<Arg>(arg)} {}
105 
106 
108 #ifdef __cpp_concepts
109  template<covariance Arg> requires
110  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
111  compares_with<vector_space_descriptor_of_t<Arg, 0>, ColumnCoefficients> and
112  requires(Arg&& arg) { NestedMatrix {to_dense_object(std::forward<Arg>(arg))}; }
113 #else
114  template<typename Arg, std::enable_if_t<covariance<Arg> and
115  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
116  compares_with<vector_space_descriptor_of_t<Arg, 0>, ColumnCoefficients> and
117  std::is_constructible_v<NestedMatrix, dense_writable_matrix_t<Arg>>, int> = 0>
118 #endif
119  Matrix(Arg&& arg) : Base {to_dense_object(std::forward<Arg>(arg))} {}
120 
121 
123 #ifdef __cpp_concepts
124  template<typed_matrix Arg> requires (not euclidean_transformed<Arg>) and
125  (not std::derived_from<std::decay_t<Arg>, Matrix>) and
126  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
127  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
128  std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, nested_object_of_t<Arg&&>>
129 #else
130  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and (not euclidean_transformed<Arg>) and
131  (not std::is_base_of_v<Matrix, std::decay_t<Arg>>) and
132  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
133  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
134  std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, nested_object_of_t<Arg&&>>, int> = 0>
135 #endif
136  auto& operator=(Arg&& other)
137  {
138  if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
139  {
140  Base::operator=(nested_object(std::forward<Arg>(other)));
141  }
142  return *this;
143  }
144 
145 
147 #ifdef __cpp_concepts
148  template<euclidean_transformed Arg> requires
149  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
150  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
151  std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, decltype(from_euclidean<RowCoefficients>(std::declval<nested_object_of_t<Arg>>()))>
152 #else
153  template<typename Arg, std::enable_if_t<euclidean_transformed<Arg> and
154  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
155  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients> and
156  std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, decltype(from_euclidean<RowCoefficients>(std::declval<nested_object_of_t<Arg>>()))>,
157  int> = 0>
158 #endif
159  auto& operator=(Arg&& other)
160  {
161  if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
162  {
163  Base::operator=(from_euclidean<RowCoefficients>(nested_object(std::forward<Arg>(other))));
164  }
165  return *this;
166  }
167 
168 
170 #ifdef __cpp_concepts
171  template<typed_matrix_nestable Arg> requires std::assignable_from<std::add_lvalue_reference_t<NestedMatrix>, Arg&&>
172 #else
173  template<typename Arg, std::enable_if_t<typed_matrix_nestable<Arg> and
174  std::is_assignable_v<std::add_lvalue_reference_t<NestedMatrix>, Arg&&>, int> = 0>
175 #endif
176  auto& operator=(Arg&& arg)
177  {
178  if constexpr (not zero<NestedMatrix> and not identity_matrix<NestedMatrix>)
179  {
180  Base::operator=(std::forward<Arg>(arg));
181  }
182  return *this;
183  }
184 
185 
187  auto& operator+=(const Matrix& other)
188  {
189  this->nested_object() += other.nested_object();
190  return *this;
191  }
192 
194 #ifdef __cpp_concepts
195  template<typed_matrix Arg> requires
196  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients> and
197  coordinates::compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>
198 #else
199  template<typename Arg, std::enable_if_t<typed_matrix<Arg> and
200  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>and
201  compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>, int> = 0>
202 #endif
203  auto& operator+=(Arg&& other)
204  {
205  this->nested_object() += nested_object(std::forward<Arg>(other));
206  return *this;
207  }
208 
209 
211 #ifdef __cpp_concepts
212  template<distribution Arg> requires (coordinates::euclidean_pattern<ColumnCoefficients>) and
213  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>)
214 #else
215  template<typename Arg, std::enable_if_t<distribution<Arg> and (coordinates::euclidean_pattern<ColumnCoefficients>) and
216  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>), int> = 0>
217 #endif
218  auto& operator+=(const Arg& arg)
219  {
220  apply_columnwise([&arg](auto& col) { col += arg().nested_object(); }, this->nested_object());
221  return *this;
222  }
223 
224 
226  auto& operator-=(const Matrix& other)
227  {
228  this->nested_object() -= other.nested_object();
229  return *this;
230  }
231 
232 
234 #ifdef __cpp_concepts
235  template<typed_matrix Arg> requires
236  compares_with<vector_space_descriptor_of_t<Arg, 0>, RowCoefficients>and
237  coordinates::compares_with<vector_space_descriptor_of_t<Arg, 1>, ColumnCoefficients>
238 #else
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>, int> = 0>
242 #endif
243  auto& operator-=(Arg&& other)
244  {
245  this->nested_object() -= nested_object(std::forward<Arg>(other));
246  return *this;
247  }
248 
249 
251 #ifdef __cpp_concepts
252  template<distribution Arg> requires (coordinates::euclidean_pattern<ColumnCoefficients>) and
253  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>)
254 #else
255  template<typename Arg, std::enable_if_t<distribution<Arg> and (coordinates::euclidean_pattern<ColumnCoefficients>) and
256  (compares_with<typename DistributionTraits<Arg>::StaticDescriptor, RowCoefficients>), int> = 0>
257 #endif
258  auto& operator-=(const Arg& arg)
259  {
260  apply_columnwise([&arg](auto& col){ col -= arg().nested_object(); }, this->nested_object());
261  return *this;
262  }
263 
264  private:
265 
266  template<typename CR = RowCoefficients, typename CC = ColumnCoefficients, typename Arg>
267  static auto make(Arg&& arg)
268  {
269  return Matrix<CR, CC, std::decay_t<Arg>>(std::forward<Arg>(arg));
270  }
271 
272  };
273 
274 
275  // ------------------------------- //
276  // Deduction Guides //
277  // ------------------------------- //
278 
280 #ifdef __cpp_concepts
281  template<typed_matrix_nestable M>
282 #else
283  template<typename M, std::enable_if_t<typed_matrix_nestable<M>, int> = 0>
284 #endif
285  explicit Matrix(M&&) -> Matrix<Dimensions<index_dimension_of_v<M, 0>>, Dimensions<index_dimension_of_v<M, 1>>, passable_t<M>>;
286 
287 
288 #ifdef __cpp_concepts
289  template<typed_matrix_nestable M, coordinates::pattern...Cs>
290 #else
291  template<typename M, std::enable_if_t<typed_matrix_nestable<M>, int> = 0>
292 #endif
293  explicit Matrix(M&&, const Cs&...) -> Matrix<Cs..., passable_t<M>>;
294 
295 
297 #ifdef __cpp_concepts
298  template<typed_matrix V> requires (not euclidean_transformed<V>)
299 #else
300  template<typename V, std::enable_if_t<typed_matrix<V> and not euclidean_transformed<V>, int> = 0>
301 #endif
302  Matrix(V&&) -> Matrix<
305  passable_t<nested_object_of_t<V>>>;
306 
307 
309 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2
310  // \todo Unlike SFINAE version, this incorrectly matches V==Mean and V==Matrix in both GCC 10.1.0 and clang 10.0.0:
311  template<euclidean_transformed V> requires has_untyped_index<V, 1>
312 #else
313  template<typename V, std::enable_if_t<euclidean_transformed<V> and has_untyped_index<V, 1>, int> = 0>
314 #endif
315  Matrix(V&&) -> Matrix<
316  vector_space_descriptor_of_t<V, 0>,
317  vector_space_descriptor_of_t<V, 1>,
318  decltype(from_euclidean<vector_space_descriptor_of_t<V, 0>>(
319  nested_object(std::forward<V>(std::declval<V>()))))>;
320 
321 
323 #ifdef __cpp_concepts
324  template<covariance V>
325 #else
326  template<typename V, std::enable_if_t<covariance<V>, int> = 0>
327 #endif
328  Matrix(V&&) -> Matrix<
329  vector_space_descriptor_of_t<V, 0>,
330  vector_space_descriptor_of_t<V, 0>,
332 
333 
334  // ------------------------- //
335  // Interfaces //
336  // ------------------------- //
337 
338  namespace interface
339  {
340  template<typename RowCoeffs, typename ColCoeffs, typename NestedMatrix>
341  struct indexible_object_traits<Matrix<RowCoeffs, ColCoeffs, NestedMatrix>>
342  {
343  using scalar_type = scalar_type_of_t<NestedMatrix>;
344 
345  template<typename Arg>
346  static constexpr auto count_indices(const Arg& arg) { return std::tuple_size_v<decltype(arg.my_dimensions)>; }
347 
348  template<typename Arg, typename N>
349  static constexpr auto get_vector_space_descriptor(Arg&& arg, N n)
350  {
351  if constexpr (values::fixed<N>)
352  return std::get<N>(std::forward<Arg>(arg).my_dimensions);
353  else if constexpr (compares_with<RowCoeffs, ColCoeffs>)
354  return std::get<0>(std::forward<Arg>(arg).my_dimensions);
355  else
356  return std::apply(
357  [](const auto&...ds, N n){ return std::array {DynamicDescriptor<scalar_type>{ds}...}[n]; },
358  arg.my_dimensions, n);
359  }
360 
361 
362  template<typename Arg>
363  static decltype(auto) nested_object(Arg&& arg)
364  {
365  return std::forward<Arg>(arg).nested_object();
366  }
367 
368 
369  template<typename Arg>
370  static constexpr auto get_constant(const Arg& arg)
371  {
372  return constant_coefficient{arg.nestedExpression()};
373  }
374 
375 
376  template<typename Arg>
377  static constexpr auto get_constant_diagonal(const Arg& arg)
378  {
379  if constexpr (coordinates::euclidean_pattern<RowCoeffs> and coordinates::euclidean_pattern<ColCoeffs>)
380  return constant_diagonal_coefficient {arg.nestedExpression()};
381  else
382  return std::monostate {};
383  }
384 
385 
386  template<Applicability b>
387  static constexpr bool one_dimensional = OpenKalman::one_dimensional<NestedMatrix, b>;
388 
389 
390  template<Applicability b>
391  static constexpr bool is_square = OpenKalman::square_shaped<NestedMatrix, b>;
392 
393 
394  template<TriangleType t>
395  static constexpr bool is_triangular = compares_with<RowCoeffs, ColCoeffs>and triangular_matrix<NestedMatrix, t>;
396 
397 
398  static constexpr bool is_triangular_adapter = false;
399 
400 
401  static constexpr bool is_hermitian = compares_with<RowCoeffs, ColCoeffs>and hermitian_matrix<NestedMatrix>;
402 
403 
404  #ifdef __cpp_lib_concepts
405  template<typename Arg, typename...I> requires element_gettable<nested_object_of_t<Arg&&>, sizeof...(I)>
406  #else
407  template<typename Arg, typename...I, std::enable_if_t<element_gettable<typename nested_object_of<Arg&&>::type, sizeof...(I)>, int> = 0>
408  #endif
409  static constexpr decltype(auto) get(Arg&& arg, I...i)
410  {
411  return get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), i...);
412  }
413 
414 
415  #ifdef __cpp_lib_concepts
416  template<typename Arg, typename I, typename...Is> requires writable_by_component<nested_object_of_t<Arg&>, 1 + sizeof...(Is)>
417  #else
418  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>
419  #endif
420  static constexpr void set(Arg& arg, const scalar_type_of_t<Arg>& s, I i, Is...is)
421  {
422  set_component(OpenKalman::nested_object(arg), s, i, is...);
423  }
424 
425 
426  static constexpr bool is_writable = library_interface<std::decay_t<NestedMatrix>>::is_writable;
427 
428 
429 #ifdef __cpp_lib_concepts
430  template<typename Arg> requires raw_data_defined_for<NestedMatrix>
431 #else
432  template<typename Arg, std::enable_if_t<raw_data_defined_for<NestedMatrix>, int> = 0>
433 #endif
434  static constexpr auto * const
435  raw_data(Arg& arg) { return internal::raw_data(nested_object(arg)); }
436 
437 
438  static constexpr Layout layout = layout_of_v<NestedMatrix>;
439 
440  };
441 
442  } // namespace interface
443 
444 } // namespace OpenKalman
445 
446 
447 #endif //OPENKALMAN_MATRIX_HPP
constexpr auto count_indices(const T &t)
Get the number of indices available to address the components of an indexible object.
Definition: count_indices.hpp:33
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:66
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:83
auto & operator+=(Arg &&other)
Increment from another typed matrix.
Definition: Matrix.hpp:203
Matrix(Arg &&arg)
Construct from a compatible typed_matrix.
Definition: Matrix.hpp:73
Definition: indexible_object_traits.hpp:36
auto & operator-=(Arg &&other)
Decrement from another typed matrix.
Definition: Matrix.hpp:243
constexpr bool euclidean_transformed
Specifies that T is a Euclidean mean that actually has coefficients that are transformed to Euclidean...
Definition: object-types.hpp:87
Arg && set_component(Arg &&arg, const scalar_type_of_t< Arg > &s, const Indices &indices)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: set_component.hpp:51
auto & operator+=(const Arg &arg)
Add a stochastic value to each column of the matrix, based on a distribution.
Definition: Matrix.hpp:218
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
auto & operator+=(const Matrix &other)
Increment from another Matrix.
Definition: Matrix.hpp:187
auto & operator=(Arg &&arg)
Assign from a compatible typed_matrix_nestable.
Definition: Matrix.hpp:176
Definition: tuple_reverse.hpp:103
auto & operator-=(const Matrix &other)
Decrement from another Matrix.
Definition: Matrix.hpp:226
decltype(auto) constexpr to_dense_object(Arg &&arg)
Convert the argument to a dense, writable matrix of a particular scalar type.
Definition: to_dense_object.hpp:37
A wrapper type&#39;s nested object type, if it exists.
Definition: nested_object_of.hpp:33
The constant associated with T, assuming T is a constant_matrix.
Definition: constant_coefficient.hpp:36
Matrix(M &&) -> Matrix< Dimensions< index_dimension_of_v< M, 0 >>, Dimensions< index_dimension_of_v< M, 1 >>, passable_t< M >>
Deduce parameter types from a typed_matrix_nestable.
constexpr bool typed_matrix_nestable
Specifies a type that is nestable in a general typed matrix (e.g., matrix, mean, or euclidean_mean) ...
Definition: object-types.hpp:253
The root namespace for OpenKalman.
Definition: basics.hpp:34
scalar_type_of_t< CrossCovarianceMatrix > Scalar
Scalar type for this matrix.
Definition: Matrix.hpp:47
auto & operator-=(const Arg &arg)
Subtract a stochastic value to each column of the matrix, based on a distribution.
Definition: Matrix.hpp:258
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:37
The constant associated with T, assuming T is a constant_diagonal_matrix.
Definition: constant_diagonal_coefficient.hpp:32
typename vector_space_descriptor_of< T, N >::type vector_space_descriptor_of_t
helper template for vector_space_descriptor_of.
Definition: vector_space_descriptor_of.hpp:56
Layout
The layout format of a multidimensional array.
Definition: global-definitions.hpp:47
constexpr bool element_gettable
Specifies that a type has components addressable by N indices.
Definition: element_gettable.hpp:33
std::decay_t< decltype(make_dense_object< T, layout, S >(std::declval< D >()))> dense_writable_matrix_t
An alias for a dense, writable matrix, patterned on parameter T.
Definition: dense_writable_matrix_t.hpp:38
decltype(auto) constexpr get_component(Arg &&arg, const Indices &indices)
Get a component of an object at a particular set of indices.
Definition: get_component.hpp:54
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:34
Definition: basics.hpp:48
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56
constexpr bool writable_by_component
Specifies that a type has components that can be set with Indices (an std::ranges::input_range) of ty...
Definition: writable_by_component.hpp:36
auto & operator=(Arg &&other)
Assign from a compatible typed_matrix.
Definition: Matrix.hpp:136