OpenKalman
VectorSpaceAdapter.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2024 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 
16 #ifndef OPENKALMAN_INTERFACES_VECTORSPACEADAPTER_HPP
17 #define OPENKALMAN_INTERFACES_VECTORSPACEADAPTER_HPP
18 
19 
20 namespace OpenKalman::interface
21 {
22  // --------------------------- //
23  // indexible_object_traits //
24  // --------------------------- //
25 
26  template<typename NestedObject, typename Descriptors>
27  struct indexible_object_traits<VectorSpaceAdapter<NestedObject, Descriptors>>
28  {
29  private:
30 
32 
33  public:
34 
35  using scalar_type = scalar_type_of_t<NestedObject>;
36 
37 
38  template<typename Arg>
39  static constexpr auto count_indices(const Arg&)
40  {
41  // Truncate any trailing ℝ¹ dimensions
42  using NewDesc = decltype(OpenKalman::internal::remove_trailing_1D_descriptors(std::declval<Descriptors>()));
44  }
45 
46 
47  template<typename Arg, typename N>
48  static constexpr auto get_vector_space_descriptor(Arg&& arg, const N& n)
49  {
50  constexpr auto dim = decltype(count_indices(arg))::value;
51 
52  if constexpr (coordinates::euclidean_pattern_collection<Descriptors>)
53  {
54  return get_index_dimension_of(std::forward<Arg>(arg).nested_object(), n);
55  }
56  else if constexpr (pattern_tuple<Descriptors>)
57  {
58  static_assert (dim != dynamic_size);
59  if constexpr (values::fixed<N>)
60  {
61  if constexpr (N::value >= dim)
62  return coordinates::Axis{};
63  else if constexpr (fixed_pattern<std::tuple_element_t<N::value, Descriptors>>)
64  return std::tuple_element_t<N::value, Descriptors> {};
65  else
66  return std::get<N::value>(std::forward<Arg>(arg).my_descriptors);
67  }
68  else
69  {
70  return std::apply(
71  [](auto&&...vs){ return std::array<coordinates::DynamicDescriptor<scalar_type>, dim> {std::forward<decltype(vs)>(vs)...}; },
72  std::forward<Arg>(arg).my_descriptors)[n];
73  }
74  }
75  else
76  {
77  using Dyn = coordinates::DynamicDescriptor<scalar_type>;
78 #ifdef __cpp_lib_ranges
79  namespace ranges = std::ranges;
80 #endif
81  if (n >= ranges::size(arg.my_descriptors))
82  {
83  return Dyn {coordinates::Axis{}};
84  }
85  else
86  {
87  return static_cast<Dyn>(std::forward<Arg>(arg).my_descriptors[n]);
88  }
89  }
90  }
91 
92 
93  template<typename Arg>
94  static decltype(auto) nested_object(Arg&& arg)
95  {
96  return std::forward<Arg>(arg).nested_object();
97  }
98 
99 
100  static constexpr auto get_constant(const Xpr& arg)
101  {
102  return constant_coefficient{arg.nested_object()};
103  }
104 
105 
106  static constexpr auto get_constant_diagonal(const Xpr& arg)
107  {
109  }
110 
111 
112  template<Applicability b>
113  static constexpr bool one_dimensional = OpenKalman::one_dimensional<NestedObject, b>;
114 
115 
116  template<Applicability b>
117  static constexpr bool is_square = square_shaped<NestedObject, b>;
118 
119 
120  template<TriangleType t>
121  static constexpr bool is_triangular = triangular_matrix<NestedObject, t>;
122 
123 
124  static constexpr bool is_triangular_adapter = false;
125 
126 
127  static constexpr bool is_hermitian = hermitian_matrix<NestedObject, Applicability::permitted>;
128 
129 
130  static constexpr bool is_writable = writable<NestedObject>;
131 
132 
133 #ifdef __cpp_lib_concepts
134  template<typename Arg> requires raw_data_defined_for<nested_object_of_t<Arg&&>>
135 #else
136  template<typename Arg, std::enable_if_t<raw_data_defined_for<typename nested_object_of<Arg&&>::type>, int> = 0>
137 #endif
138  static constexpr decltype(auto)
139  raw_data(Arg&& arg)
140  {
141  return internal::raw_data(OpenKalman::nested_object(std::forward<Arg>(arg)));
142  }
143 
144 
145  static constexpr Layout layout = layout_of_v<NestedObject>;
146 
147 
148 #ifdef __cpp_concepts
149  template<typename Arg> requires (layout == Layout::stride)
150 #else
151  template<Layout l = layout, typename Arg, std::enable_if_t<l == Layout::stride, int> = 0>
152 #endif
153  static auto
154  strides(Arg&& arg)
155  {
156  return OpenKalman::internal::strides(nested_object(std::forward<Arg>(arg)));
157  }
158 
159  };
160 
161 
162  // ------------------- //
163  // library_interface //
164  // ------------------- //
165 
166  template<typename Nested, typename...Ds>
167  struct library_interface<VectorSpaceAdapter<Nested, Ds...>> : library_interface<std::decay_t<Nested>>
168  {
169  private:
170 
171  using NestedObject = std::decay_t<Nested>;
173 
174  template<typename T, typename Arg>
175  static constexpr auto
176  make_adapter(T&& t, Arg&& arg)
177  {
178  return std::apply([](auto&& a, auto&&...vs){
179  return make_vector_space_adapter(std::forward<decltype(a)>(a), std::forward<decltype(vs)>(vs)...);
180  }, std::tuple_cat(std::forward_as_tuple(std::forward<Arg>(arg)), std::forward<T>(t).my_descriptors));
181  }
182 
183  public:
184 
185  template<typename Derived>
186  using LibraryBase = internal::library_base_t<Derived, NestedObject>;
187 
188 #ifdef __cpp_lib_ranges
189  template<indexible Arg, std::ranges::input_range Indices> requires values::index<std::ranges::range_value_t<Indices>> and
190  interface::get_component_defined_for<NestedObject, nested_object_of_t<Arg&&>, const Indices&>
191  static constexpr values::scalar decltype(auto)
192 #else
193  template<typename Arg, typename Indices, std::enable_if_t<
194  interface::get_component_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, const Indices&>, int> = 0>
195  static constexpr decltype(auto)
196 #endif
197  get_component(Arg&& arg, const Indices& indices)
198  {
199  return NestedInterface::get_component(nested_object(std::forward<Arg>(arg)), indices);
200  }
201 
202 
203 #ifdef __cpp_lib_ranges
204  template<indexible Arg, std::ranges::input_range Indices> requires values::index<std::ranges::range_value_t<Indices>> and
205  interface::set_component_defined_for<NestedObject, nested_object_of_t<Arg&&>, const scalar_type_of_t<Arg>&, const Indices&>
206 #else
207  template<typename Arg, typename Indices, std::enable_if_t<
208  interface::set_component_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, const typename scalar_type_of<Arg>::type&, const Indices&>, int> = 0>
209 #endif
210  static constexpr void
211  set_component(Arg& arg, const scalar_type_of_t<Arg>& s, const Indices& indices)
212  {
214  }
215 
216 
217 #ifdef __cpp_concepts
218  template<typename Arg> requires interface::to_native_matrix_defined_for<NestedObject, nested_object_of_t<Arg&&>>
219 #else
220  template<typename Arg, std::enable_if_t<interface::to_native_matrix_defined_for<NestedObject, nested_object_of_t<Arg&&>>, int> = 0>
221 #endif
222  static decltype(auto)
223  to_native_matrix(Arg&& arg)
224  {
225  return make_adapter(std::forward<Arg>(arg), NestedInterface::to_native_matrix(nested_object(std::forward<Arg>(arg))));
226  }
227 
228 
229 #ifdef __cpp_concepts
230  template<typename To, typename From> requires
231  interface::assign_defined_for<NestedObject, nested_object_of_t<To&>, From&&>
232 #else
233  template<typename To, typename From, std::enable_if_t<
234  interface::assign_defined_for<NestedObject, nested_object_of_t<To&>, From&&>, int> = 0>
235 #endif
236  static void
237  assign(To& a, From&& b)
238  {
239  NestedInterface::assign(nested_object(a), std::forward<From>(b));
240  }
241 
242 
243 #ifdef __cpp_concepts
244  template<Layout layout, typename Scalar, typename D> requires
245  interface::make_default_defined_for<NestedObject, layout, Scalar, D&&>
246 #else
247  template<Layout layout, typename Scalar, typename D, std::enable_if_t<
248  interface::make_default_defined_for<NestedObject, layout, Scalar, D&&>, int> = 0>
249 #endif
250  static auto
251  make_default(D&& d)
252  {
253  return NestedInterface::template make_default<layout, Scalar>(std::forward<D>(d));
254  }
255 
256 
257 #ifdef __cpp_concepts
258  template<Layout layout, typename Arg, typename...Scalars> requires
259  interface::fill_components_defined_for<NestedObject, layout, nested_object_of_t<Arg&>, Scalars...>
260 #else
261  template<Layout layout, typename Arg, typename...Scalars, std::enable_if_t<
262  interface::fill_components_defined_for<NestedObject, layout, typename nested_object_of<Arg&>::type, Scalars...>, int> = 0>
263 #endif
264  static void
265  fill_components(Arg& arg, const Scalars...scalars)
266  {
267  NestedInterface::template fill_components<layout>(nested_object(arg), scalars...);
268  }
269 
270 
271 #ifdef __cpp_concepts
272  template<typename C, typename D> requires interface::make_constant_defined_for<NestedObject, C&&, D&&>
273 #else
274  template<typename C, typename D, std::enable_if_t<interface::make_constant_defined_for<NestedObject, C&&, D&&>, int> = 0>
275 #endif
276  static constexpr auto
277  make_constant(C&& c, D&& d)
278  {
279  return NestedInterface::make_constant(std::forward<C>(c), std::forward<D>(d));
280  }
281 
282 
283 #ifdef __cpp_concepts
284  template<typename Scalar, typename D> requires interface::make_identity_matrix_defined_for<NestedObject, Scalar, D&&>
285 #else
286  template<typename Scalar, typename D, std::enable_if_t<interface::make_identity_matrix_defined_for<NestedObject, Scalar, D&&>, int> = 0>
287 #endif
288  static constexpr auto
289  make_identity_matrix(D&& d)
290  {
291  return NestedInterface::make_identity_matrix(std::forward<D>(d));
292  }
293 
294 
295 #ifdef __cpp_concepts
296  template<TriangleType t, indexible Arg> requires
297  interface::make_triangular_matrix_defined_for<NestedObject, t, nested_object_of_t<Arg&&>>
298  static constexpr triangular_matrix<t> auto
299 #else
300  template<TriangleType t, typename Arg, std::enable_if_t<
301  interface::make_triangular_matrix_defined_for<NestedObject, t, typename nested_object_of<Arg&&>::type>, int> = 0>
302  static constexpr auto
303 #endif
304  make_triangular_matrix(Arg&& arg)
305  {
306  return make_adapter(std::forward<Arg>(arg), (NestedInterface::template make_triangular_matrix<t>(nested_object(std::forward<Arg>(arg)))));
307  }
308 
309 
310 #ifdef __cpp_concepts
311  template<HermitianAdapterType t, indexible Arg> requires
312  interface::make_hermitian_adapter_defined_for<NestedObject, t, nested_object_of_t<Arg&&>>
313  static constexpr hermitian_matrix auto
314 #else
315  template<HermitianAdapterType t, typename Arg, std::enable_if_t<
316  make_hermitian_adapter_defined_for<NestedObject, t, typename nested_object_of<Arg&>::type>, int> = 0>
317  static constexpr auto
318 #endif
319  make_hermitian_adapter(Arg&& arg)
320  {
321  return make_adapter(std::forward<Arg>(arg), NestedInterface::template make_hermitian_adapter<t>(nested_object(std::forward<Arg>(arg))));
322  }
323 
324  private:
325 
326  template<typename Arg, typename BeginTup, typename SizeTup, std::size_t...Ix>
327  static decltype(auto)
328  get_slice_impl(Arg&& arg, const BeginTup& begin_tup, const SizeTup& size_tup, std::index_sequence<Ix...>)
329  {
330  return make_vector_space_adapter(NestedInterface::get_slice(nested_object(std::forward<Arg>(arg)), begin_tup, size_tup),
331  std::tuple {coordinates::get_slice<scalar_type_of_t<Arg>>(OpenKalman::get_vector_space_descriptor(arg, Ix), std::get<Ix>(begin_tup), std::get<Ix>(size_tup))...});
332  }
333 
334  public:
335 
336 #ifdef __cpp_concepts
337  template<typename Arg, typename...Begin, typename...Size> requires
338  interface::get_slice_defined_for<NestedObject, nested_object_of_t<Arg&&>, const std::tuple<Begin...>&, const std::tuple<Size...>&>
339 #else
340  template<typename Arg, typename...Begin, typename...Size, std::enable_if_t<
341  interface::get_slice_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, const std::tuple<Begin...>&, const std::tuple<Size...>&>, int> = 0>
342 #endif
343  static decltype(auto)
344  get_slice(Arg&& arg, const std::tuple<Begin...>& begin_tup, const std::tuple<Size...>& size_tup)
345  {
346  return get_slice_impl(std::forward<Arg>(arg), begin_tup, size_tup, std::index_sequence_for<Begin...>{});
347  };
348 
349 
350 #ifdef __cpp_concepts
351  template<typename Arg, typename Block, typename...Begin> requires
352  interface::set_slice_defined_for<Arg, nested_object_of_t<Arg&>, Block&&, const Begin&...>
353 #else
354  template<typename Arg, typename Block, typename...Begin, std::enable_if_t<
355  interface::set_slice_defined_for<Arg, typename nested_object_of<Arg&>::type, Block&&, const Begin&...>, int> = 0>
356 #endif
357  static void
358  set_slice(Arg& arg, Block&& block, const Begin&...begin)
359  {
360  NestedInterface::set_slice(nested_object(arg), std::forward<Block>(block), begin...);
361  };
362 
363 
364 #ifdef __cpp_concepts
365  template<TriangleType t, typename A, typename B> requires
366  interface::set_triangle_defined_for<NestedObject, t, nested_object_of_t<A&&>, B&&>
367 #else
368  template<TriangleType t, typename A, typename B, std::enable_if_t<
369  interface::set_triangle_defined_for<NestedObject, t, typename nested_object_of<A&&>::type, B&&>, int> = 0>
370 #endif
371  static void
372  set_triangle(A&& a, B&& b)
373  {
374  NestedInterface::template set_triangle<t>(nested_object(std::forward<A>(a)), std::forward<B>(b));
375  }
376 
377 
378 #ifdef __cpp_concepts
379  template<typename Arg> requires
380  interface::to_diagonal_defined_for<NestedObject, nested_object_of_t<Arg&&>>
381  static constexpr diagonal_matrix auto
382 #else
383  template<typename Arg, std::enable_if_t<
384  interface::to_diagonal_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
385  static constexpr auto
386 #endif
387  to_diagonal(Arg&& arg)
388  {
389  return std::apply([](auto&& a, auto&& v, auto&&...vs){
391  std::forward<decltype(a)>(a),
392  std::forward<decltype(v)>(v),
393  std::forward<decltype(v)>(v),
394  std::forward<decltype(vs)>(vs)...);
395  }, std::tuple_cat(
396  std::forward_as_tuple(NestedInterface::to_diagonal(nested_object(std::forward<Arg>(arg)))),
397  std::forward<Arg>(arg).my_descriptors),
398  std::tuple{coordinates::Axis{}});
399  }
400 
401  private:
402 
403  template<typename Arg, typename V0, typename V1, typename...Vs>
404  static constexpr decltype(auto)
405  diagonal_of_impl(Arg&& arg, V0&& v0, V1&& v1, const Vs&...vs)
406  {
407  auto d0 = internal::smallest_vector_space_descriptor<scalar_type_of_t<Arg>>(std::forward<V0>(v0), std::forward<V1>(v1));
408  return make_vector_space_adapter(std::forward<Arg>(arg), d0, vs...);
409  }
410 
411  public:
412 
413 #ifdef __cpp_concepts
414  template<indexible Arg> requires diagonal_adapter<NestedObject> or
415  (diagonal_adapter<NestedObject, 1> and
416  interface::transpose_defined_for<NestedObject, decltype(nested_object(nested_object(std::declval<Arg>())))>) or
417  interface::diagonal_of_defined_for<NestedObject, nested_object_of_t<Arg&&>>
418  static constexpr vector auto
419 #else
420  template<typename Arg, std::enable_if_t<diagonal_adapter<NestedObject> or
421  (diagonal_adapter<NestedObject, 1> and
422  interface::transpose_defined_for<NestedObject, decltype(nested_object(nested_object(std::declval<Arg>())))>) or
423  interface::diagonal_of_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
424  static constexpr auto
425 #endif
426  diagonal_of(Arg&& arg)
427  {
428  if constexpr (diagonal_adapter<NestedObject>)
429  return diagonal_of_impl(nested_object(nested_object(std::forward<Arg>(arg))));
430  else if constexpr (diagonal_adapter<NestedObject, 1> and
431  interface::transpose_defined_for<NestedObject, decltype(nested_object(nested_object(std::declval<Arg>())))>)
432  return diagonal_of_impl(NestedInterface::transpose(nested_object(nested_object(std::forward<Arg>(arg)))));
433  else
434  return diagonal_of_impl(NestedInterface::diagonal_of(nested_object(std::forward<Arg>(arg))),
435  std::tuple_cat(all_vector_space_descriptors(std::forward<Arg>(arg)), std::tuple{coordinates::Axis{}, coordinates::Axis{}}));
436  }
437 
438  private:
439 
440  template<std::size_t Ix, typename Arg, typename Factors_tup>
441  static constexpr auto broadcast_for_index(const Arg& arg, const Factors_tup& factors_tup)
442  {
443  constexpr auto N = std::tuple_size_v<Factors_tup>;
444  if constexpr (Ix < N)
445  return get_vector_space_descriptor<Ix>(arg) * std::get<Ix>(factors_tup);
446  else
447  return coordinates::Axis{};
448  }
449 
450 
451  template<typename Arg, std::size_t...Is, typename Factors_tup>
452  static constexpr auto broadcast_impl(Arg&& arg, std::index_sequence<Is...>, const Factors_tup& factors_tup)
453  {
454  constexpr auto N = std::tuple_size_v<Factors_tup>;
455  return make_vector_space_adapter(std::forward<Arg>(arg), broadcast_for_index<Is>(arg, factors_tup)...);
456  }
457 
458  public:
459 
460 #ifdef __cpp_concepts
461  template<indexible Arg, values::index...Factors> requires
462  interface::broadcast_defined_for<NestedObject, nested_object_of_t<Arg&&>, const Factors&...>
463  static indexible auto
464 #else
465  template<typename Arg, typename...Factors, std::enable_if_t<
466  interface::broadcast_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, const Factors&...>, int> = 0>
467  static auto
468 #endif
469  broadcast(Arg&& arg, const Factors&...factors)
470  {
471  auto&& ret = NestedInterface::broadcast(nested_object(std::forward<Arg>(arg)), factors...);
472  using Ret = decltype(ret);
473  auto seq = std::make_index_sequence<std::max(index_count_v<Arg>, sizeof...(factors))>{};
474  return broadcast_impl(std::forward<Ret>(ret), seq, std::forward_as_tuple(factors...));
475  }
476 
477 
478 #ifdef __cpp_concepts
479  template<coordinates::pattern...Vs, typename Operation> requires
480  interface::n_ary_operation_defined_for<NestedInterface, const std::tuple<Vs...>&, Operation&&>
481  static indexible auto
482 #else
483  template<typename...Vs, typename Operation, std::enable_if_t<
484  interface::n_ary_operation_defined_for<NestedInterface, const std::tuple<Vs...>&, Operation&&>, int> = 0>
485  static auto
486 #endif
487  n_ary_operation(const std::tuple<Vs...>& d_tup, Operation&& op)
488  {
489  return NestedInterface::n_ary_operation(d_tup, std::forward<Operation>(op));
490  }
491 
492 
493 #ifdef __cpp_concepts
494  template<coordinates::pattern...Vs, typename Operation, indexible Arg, indexible...Args> requires
495  interface::n_ary_operation_defined_for<NestedObject, const std::tuple<Vs...>&, Operation&&, nested_object_of_t<Arg&&>, Args...>
496  static indexible auto
497 #else
498  template<typename...Vs, typename Operation, typename Arg, typename...Args, std::enable_if_t<
499  interface::n_ary_operation_defined_for<NestedObject, const std::tuple<Vs...>&, Operation&&, typename nested_object_of<Arg&&>::type, Args...>, int> = 0>
500  static auto
501 #endif
502  n_ary_operation(const std::tuple<Vs...>& d_tup, Operation&& op, Arg&& arg, Args&&...args)
503  {
504  return NestedInterface::n_ary_operation(d_tup, std::forward<Operation>(op), nested_object(std::forward<Arg>(arg)), std::forward<Args>(args)...);
505  }
506 
507  private:
508 
509  template<std::size_t...indices, typename Arg, typename...Vs, std::size_t...Ix>
510  static constexpr decltype(auto)
511  reduce_impl(Arg&& arg, const std::tuple<Vs...>& tup_vs, std::index_sequence<Ix...> seq)
512  {
513  return make_vector_space_adapter(std::forward<Arg>(arg),
514  ([]{ constexpr auto I = Ix; return ((I == indices) or ...); } ?
515  uniform_static_vector_space_descriptor_component_of_t<vector_space_descriptor_of_t<Vs, Ix>>{} :
516  std::get<Ix>(tup_vs))...);
517  }
518 
519  public:
520 
521 #ifdef __cpp_concepts
522  template<std::size_t...indices, typename BinaryFunction, indexible Arg> requires
523  interface::reduce_defined_for<NestedObject, BinaryFunction&&, nested_object_of_t<Arg&&>, indices...>
524 #else
525  template<std::size_t...indices, typename BinaryFunction, typename Arg, std::enable_if_t<
526  interface::reduce_defined_for<NestedObject, BinaryFunction&&, typename nested_object_of<Arg&&>::type, indices...>, int> = 0>
527 #endif
528  static constexpr auto
529  reduce(BinaryFunction&& op, Arg&& arg)
530  {
531  return reduce_impl<indices...>(
532  NestedInterface::template reduce<indices...>(std::forward<BinaryFunction>(op), nested_object(std::forward<Arg>(arg))),
533  std::forward<Arg>(arg).my_descriptors,
534  std::index_sequence_for<Ds...>{});
535  }
536 
537 
538 #ifdef __cpp_concepts
539  template<indexible Arg> requires
540  interface::to_euclidean_defined_for<NestedObject, Arg&&> or
541  interface::to_euclidean_defined_for<NestedObject, nested_object_of_t<Arg&&>>
542  static constexpr indexible auto
543 #else
544  template<typename Arg, std::enable_if_t<
545  interface::to_euclidean_defined_for<NestedObject, Arg&&> or
546  interface::to_euclidean_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
547  static constexpr auto
548 #endif
549  to_euclidean(Arg&& arg)
550  {
551  if constexpr (interface::to_euclidean_defined_for<NestedObject, Arg&&>)
552  return NestedInterface::to_euclidean(std::forward<Arg>(arg));
553  else
554  return NestedInterface::to_euclidean(nested_object(std::forward<Arg>(arg)));
555  }
556 
557 
558 #ifdef __cpp_concepts
559  template<indexible Arg, coordinates::pattern V> requires
560  interface::from_euclidean_defined_for<NestedObject, Arg&&, const V&> or
561  interface::from_euclidean_defined_for<NestedObject, nested_object_of_t<Arg&&>, const V&>
562  static constexpr indexible auto
563 #else
564  template<typename Arg, typename V, std::enable_if_t<
565  interface::from_euclidean_defined_for<NestedObject, Arg&&, const V&> or
566  interface::from_euclidean_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, const V&>, int> = 0>
567  static constexpr auto
568 #endif
569  from_euclidean(Arg&& arg, const V& v)
570  {
571  if constexpr (interface::from_euclidean_defined_for<NestedObject, Arg&&, const V&>)
572  return NestedInterface::from_euclidean(std::forward<Arg>(arg), v);
573  else
574  return NestedInterface::from_euclidean(nested_object(std::forward<Arg>(arg)), v);
575  }
576 
577 
578 #ifdef __cpp_concepts
579  template<indexible Arg> requires
580  interface::wrap_angles_defined_for<NestedObject, Arg&&> or
581  interface::wrap_angles_defined_for<NestedObject, nested_object_of_t<Arg&&>>
582  static constexpr indexible auto
583 #else
584  template<typename Arg, std::enable_if_t<
585  interface::wrap_angles_defined_for<NestedObject, Arg&&> or
586  interface::wrap_angles_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
587  static constexpr auto
588 #endif
589  wrap_angles(Arg&& arg)
590  {
591  if constexpr (interface::wrap_angles_defined_for<NestedObject, Arg&&>)
592  return NestedInterface::wrap_angles(std::forward<Arg>(arg));
593  else
594  return NestedInterface::wrap_angles(nested_object(std::forward<Arg>(arg)));
595  }
596 
597 
598 #ifdef __cpp_concepts
599  template<indexible Arg> requires
600  interface::conjugate_defined_for<NestedObject, Arg&&> or
601  interface::conjugate_defined_for<NestedObject, nested_object_of_t<Arg&&>>
602  static constexpr indexible auto
603 #else
604  template<typename Arg, std::enable_if_t<
605  interface::conjugate_defined_for<NestedObject, Arg&&> or
606  interface::conjugate_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
607  static constexpr auto
608 #endif
609  conjugate(Arg&& arg)
610  {
611  if constexpr (interface::conjugate_defined_for<NestedObject, Arg&&>)
612  {
613  return NestedInterface::conjugate(std::forward<Arg>(arg));
614  }
615  else
616  {
617  auto&& conj = NestedInterface::conjugate(nested_object(std::forward<Arg>(arg)));
618  return internal::make_fixed_size_adapter_like<Arg>(std::forward<decltype(conj)>(conj));
619  }
620  }
621 
622 
623 #ifdef __cpp_concepts
624  template<indexible Arg> requires
625  interface::transpose_defined_for<NestedObject, Arg&&> or
626  interface::transpose_defined_for<NestedObject, nested_object_of_t<Arg&&>>
627  static constexpr indexible auto
628 #else
629  template<typename Arg, std::enable_if_t<
630  interface::transpose_defined_for<NestedObject, Arg&&> or
631  interface::transpose_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
632  static constexpr auto
633 #endif
634  transpose(Arg&& arg)
635  {
636  if constexpr (interface::transpose_defined_for<NestedObject, Arg&&>)
637  {
638  return NestedInterface::transpose(std::forward<Arg>(arg));
639  }
640  else
641  {
642  return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<Arg, 1>, vector_space_descriptor_of_t<Arg, 0>>(
643  NestedInterface::transpose(nested_object(std::forward<Arg>(arg))));
644  }
645  }
646 
647 
648 #ifdef __cpp_concepts
649  template<indexible Arg> requires
650  interface::adjoint_defined_for<NestedObject, Arg&&> or
651  interface::adjoint_defined_for<NestedObject, nested_object_of_t<Arg&&>>
652  static constexpr indexible auto
653 #else
654  template<typename Arg, std::enable_if_t<
655  interface::adjoint_defined_for<NestedObject, Arg&&> or
656  interface::adjoint_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
657  static constexpr auto
658 #endif
659  adjoint(Arg&& arg)
660  {
661  if constexpr (interface::adjoint_defined_for<NestedObject, Arg&&>)
662  {
663  return NestedInterface::adjoint(std::forward<Arg>(arg));
664  }
665  else
666  {
667  return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<Arg, 1>, vector_space_descriptor_of_t<Arg, 0>>(
668  NestedInterface::adjoint(nested_object(std::forward<Arg>(arg))));
669  }
670  }
671 
672 
673 #ifdef __cpp_concepts
674  template<indexible Arg> requires
675  interface::determinant_defined_for<NestedObject, Arg&&> or
676  interface::determinant_defined_for<NestedObject, nested_object_of_t<Arg&&>>
677  static constexpr std::convertible_to<scalar_type_of_t<Arg>> auto
678 #else
679  template<typename Arg, std::enable_if_t<
680  interface::determinant_defined_for<NestedObject, Arg&&> or
681  interface::determinant_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>, int> = 0>
682  static constexpr auto
683 #endif
684  determinant(Arg&& arg)
685  {
686  if constexpr (interface::determinant_defined_for<NestedObject, Arg&&>)
687  {
688  return NestedInterface::determinant(std::forward<Arg>(arg));
689  }
690  else
691  {
692  return NestedInterface::determinant(nested_object(std::forward<Arg>(arg)));
693  }
694  }
695 
696 
697 #ifdef __cpp_concepts
698  template<typename Arg, typename...Args> requires
699  interface::sum_defined_for<NestedObject, Arg&&, Args&&...> or
700  interface::sum_defined_for<NestedObject, nested_object_of_t<Arg&&>, Args&&...>
701 #else
702  template<typename Arg, typename...Args, std::enable_if_t<
703  interface::sum_defined_for<NestedObject, Arg&&, Args&&...> or
704  interface::sum_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, Args&&...>, int> = 0>
705 #endif
706  static auto
707  sum(Arg&& arg, Args&&...args)
708  {
709  if constexpr (interface::sum_defined_for<NestedObject, Arg&&, Args&&...>)
710  {
711  return NestedInterface::sum(std::forward<Arg>(arg), std::forward<Args>(args)...);
712  }
713  else
714  {
715  return NestedInterface::sum(nested_object(std::forward<Arg>(arg)), std::forward<Args>(args)...);
716  }
717  }
718 
719 
720 #ifdef __cpp_concepts
721  template<typename A, typename B> requires
722  interface::contract_defined_for<NestedObject, A&&, B&&> or
723  interface::contract_defined_for<NestedObject, nested_object_of_t<A&&>, B&&>
724 #else
725  template<typename A, typename B, std::enable_if_t<
726  interface::contract_defined_for<NestedObject, A&&, B&&> or
727  interface::contract_defined_for<NestedObject, typename nested_object_of<A&&>::type, B&&>, int> = 0>
728 #endif
729  static auto
730  contract(A&& a, B&& b)
731  {
732  if constexpr (interface::contract_defined_for<NestedObject, A&&, B&&>)
733  {
734  return NestedInterface::contract(std::forward<A>(a), std::forward<B>(b));
735  }
736  else
737  {
738  return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<A, 0>, vector_space_descriptor_of_t<B, 1>>(
739  NestedInterface::contract(nested_object(std::forward<A>(a)), std::forward<B>(b)));
740  }
741  }
742 
743 
744 #ifdef __cpp_concepts
745  template<bool on_the_right, typename A, typename B> requires
746  interface::contract_in_place_defined_for<NestedObject, on_the_right, A&&, B&&> or
747  interface::contract_in_place_defined_for<NestedObject, on_the_right, nested_object_of_t<A&&>, B&&>
748 #else
749  template<bool on_the_right, typename A, typename B, std::enable_if_t<
750  interface::contract_in_place_defined_for<NestedObject, on_the_right, A&&, B&&> or
751  interface::contract_in_place_defined_for<NestedObject, on_the_right, typename nested_object_of<A&&>::type, B&&>, int> = 0>
752 #endif
753  static decltype(auto)
754  contract_in_place(A&& a, B&& b)
755  {
756  if constexpr (interface::contract_in_place_defined_for<NestedObject, on_the_right, A&&, B&&>)
757  {
758  return NestedInterface::template contract_in_place<on_the_right>(std::forward<A>(a), std::forward<B>(b));
759  }
760  else
761  {
762  auto&& ret = NestedInterface::template contract_in_place<on_the_right>(nested_object(std::forward<A>(a)), std::forward<B>(b));
763  using Ret = decltype(ret);
764  if constexpr (std::is_lvalue_reference_v<Ret> and std::is_same_v<Ret, nested_object_of_t<A&&>>)
765  {
766  return std::forward<A>(a);
767  }
768  else if constexpr (on_the_right)
769  {
770  return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<A, 0>, vector_space_descriptor_of_t<B, 1>>(std::forward<Ret>(ret));
771  }
772  else
773  {
774  return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<B, 0>, vector_space_descriptor_of_t<A, 1>>(std::forward<Ret>(ret));
775  }
776  }
777  }
778 
779 
780 #ifdef __cpp_concepts
781  template<TriangleType triangle_type, indexible Arg> requires
782  interface::cholesky_factor_defined_for<NestedObject, triangle_type, Arg&&> or
783  interface::cholesky_factor_defined_for<NestedObject, triangle_type, nested_object_of_t<Arg&&>>
784  static constexpr triangular_matrix<triangle_type> auto
785 #else
786  template<TriangleType triangle_type, typename Arg, std::enable_if_t<
787  interface::cholesky_factor_defined_for<NestedObject, triangle_type, Arg&&> or
788  interface::cholesky_factor_defined_for<NestedObject, triangle_type, typename nested_object_of<Arg&&>::type>, int> = 0>
789  static constexpr auto
790 #endif
791  cholesky_factor(Arg&& arg)
792  {
793  if constexpr (interface::cholesky_factor_defined_for<NestedObject, triangle_type, Arg&&>)
794  {
795  return NestedInterface::template cholesky_factor<triangle_type>(std::forward<Arg>(arg));
796  }
797  else
798  {
799  auto tri = NestedInterface::template cholesky_factor<triangle_type>(nested_object(std::forward<Arg>(arg)));
800  return internal::make_fixed_square_adapter_like(std::move(tri));
801  }
802  }
803 
804 
805 #ifdef __cpp_concepts
806  template<HermitianAdapterType significant_triangle, indexible A, indexible U> requires
807  interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, A&&, U&&, const scalar_type_of_t<A>&> or
808  interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, nested_object_of_t<A&&>, U&&, const scalar_type_of_t<A>&>
809  static constexpr hermitian_matrix auto
810 #else
811  template<HermitianAdapterType significant_triangle, typename A, typename U, std::enable_if_t<
812  interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, A&&, U&&, const typename scalar_type_of<A>::type&> or
813  interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, typename nested_object_of<A&&>::type, U&&, const typename scalar_type_of<A>::type&>, int> = 0>
814  static constexpr auto
815 #endif
816  rank_update_hermitian(A&& a, U&& u, const scalar_type_of_t<A>& alpha)
817  {
818  if constexpr (interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, A&&, U&&, const scalar_type_of_t<A>&>)
819  {
820  return NestedInterface::template rank_update_hermitian<significant_triangle>(std::forward<A>(a), std::forward<U>(u), alpha);
821  }
822  else
823  {
824  auto tri = NestedInterface::template rank_update_hermitian<significant_triangle>(nested_object(std::forward<A>(a), std::forward<U>(u), alpha));
825  return internal::make_fixed_square_adapter_like(std::move(tri));
826  }
827  }
828 
829 
830 #ifdef __cpp_concepts
831  template<TriangleType triangle_type, indexible A, indexible U> requires
832  interface::rank_update_triangular_defined_for<NestedObject, triangle_type, A&&, U&&, const scalar_type_of_t<A>&> or
833  interface::rank_update_triangular_defined_for<NestedObject, triangle_type, nested_object_of_t<A&&>, U&&, const scalar_type_of_t<A>&>
834  static constexpr triangular_matrix<triangle_type> auto
835 #else
836  template<TriangleType triangle_type, typename A, typename U, std::enable_if_t<
837  interface::rank_update_triangular_defined_for<NestedObject, triangle_type, A&&, U&&, const typename scalar_type_of<A>::type&> or
838  interface::rank_update_triangular_defined_for<NestedObject, triangle_type, typename nested_object_of<A&&>::type, U&&, const typename scalar_type_of<A>::type&>, int> = 0>
839  static constexpr auto
840 #endif
841  rank_update_triangular(A&& a, U&& u, const scalar_type_of_t<A>& alpha)
842  {
843  if constexpr (interface::rank_update_triangular_defined_for<NestedObject, triangle_type, A&&, U&&, const scalar_type_of_t<A>&>)
844  {
845  return NestedInterface::template rank_update_triangular<triangle_type>(std::forward<A>(a), std::forward<U>(u), alpha);
846  }
847  else
848  {
849  auto tri = NestedInterface::template rank_update_triangular<triangle_type>(nested_object(std::forward<A>(a), std::forward<U>(u), alpha));
850  return internal::make_fixed_square_adapter_like(std::move(tri));
851  }
852  }
853 
854 
855 #ifdef __cpp_concepts
856  template<bool must_be_unique, bool must_be_exact, typename A, typename B> requires
857  interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, A&&, B&&> or
858  interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, nested_object_of_t<A&&>, B&&>
859  static compatible_with_vector_space_descriptor_collection<std::tuple<vector_space_descriptor_of_t<A, 1>, vector_space_descriptor_of_t<B, 1>>> auto
860 #else
861  template<bool must_be_unique, bool must_be_exact, typename A, typename B, std::enable_if_t<
862  interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, A&&, B&&> or
863  interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, typename nested_object_of<A&&>::type, B&&>, int> = 0>
864  static auto
865 #endif
866  solve(A&& a, B&& b)
867  {
868  if constexpr (interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, A&&, B&&>)
869  {
870  return NestedInterface::template solve<must_be_unique, must_be_exact>(std::forward<A>(a), std::forward<B>(b));
871  }
872  else
873  {
874  return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<A, 1>, vector_space_descriptor_of_t<B, 1>>(
875  NestedInterface::template solve<must_be_unique, must_be_exact>(nested_object(std::forward<A>(a)), std::forward<B>(b)));
876  }
877  }
878 
879 
880 #ifdef __cpp_concepts
881  template<typename A> requires
882  interface::LQ_decomposition_defined_for<NestedObject, A&&> or
883  interface::LQ_decomposition_defined_for<NestedObject, nested_object_of_t<A&&>>
884 #else
885  template<typename A, std::enable_if_t<
886  interface::LQ_decomposition_defined_for<NestedObject, A&&> or
887  interface::LQ_decomposition_defined_for<NestedObject, typename nested_object_of<A&&>::type>, int> = 0>
888 #endif
889  static auto
890  LQ_decomposition(A&& a)
891  {
892  if constexpr (interface::LQ_decomposition_defined_for<NestedObject, A&&>)
893  {
894  return NestedInterface::LQ_decomposition(std::forward<A>(a));
895  }
896  else
897  {
898  auto&& ret = NestedInterface::LQ_decomposition(nested_object(std::forward<A>(a)));
900  return internal::make_fixed_square_adapter_like<D0>(std::forward<decltype(ret)>(ret));
901  }
902  }
903 
904 
905 #ifdef __cpp_concepts
906  template<typename A> requires
907  interface::QR_decomposition_defined_for<NestedObject, A&&> or
908  interface::QR_decomposition_defined_for<NestedObject, nested_object_of_t<A&&>>
909 #else
910  template<typename A, std::enable_if_t<
911  interface::QR_decomposition_defined_for<NestedObject, A&&> or
912  interface::QR_decomposition_defined_for<NestedObject, typename nested_object_of<A&&>::type>, int> = 0>
913 #endif
914  static auto
915  QR_decomposition(A&& a)
916  {
917  if constexpr (interface::QR_decomposition_defined_for<NestedObject, A&&>)
918  {
919  return NestedInterface::QR_decomposition(std::forward<A>(a));
920  }
921  else
922  {
923  auto&& ret = NestedInterface::QR_decomposition(nested_object(std::forward<A>(a)));
925  return internal::make_fixed_square_adapter_like<D1>(std::forward<decltype(ret)>(ret));
926  }
927  }
928 
929  };
930 
931 } // namespace OpenKalman::interface
932 
933 
934 #endif //OPENKALMAN_INTERFACES_VECTORSPACEADAPTER_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 auto n_ary_operation(const std::tuple< Ds... > &d_tup, Operation &&operation, Args &&...args)
Perform a component-wise n-ary operation, using broadcasting to match the size of a pattern matrix...
Definition: n_ary_operation.hpp:319
constexpr NestedObject & nested_object() &
Get the nested object.
Definition: AdapterBase.hpp:97
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:83
An adapter that adds vector space descriptors for each index.
Definition: forward-class-declarations.hpp:301
decltype(auto) constexpr contract(A &&a, B &&b)
Matrix multiplication of A * B.
Definition: contract.hpp:54
TriangleType
The type of a triangular matrix.
Definition: global-definitions.hpp:60
Definition: indexible_object_traits.hpp:36
Definition: basics.hpp:41
decltype(auto) rank_update_hermitian(A &&a, U &&u, scalar_type_of_t< A > alpha=1)
Do a rank update on a hermitian matrix.
Definition: rank_update_hermitian.hpp:45
constexpr bool diagonal_matrix
Specifies that a type is a diagonal matrix or tensor.
Definition: diagonal_matrix.hpp:32
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
decltype(auto) constexpr conjugate(Arg &&arg)
Take the conjugate of a matrix.
Definition: conjugate.hpp:33
auto make_vector_space_adapter(Arg &&arg, Descriptors &&descriptors)
If necessary, wrap an object in a wrapper that adds vector space descriptors for each index...
Definition: make_vector_space_adapter.hpp:37
decltype(auto) constexpr get_slice(Arg &&arg, const std::tuple< Offset... > &offsets, const std::tuple< Extent... > &extents)
Extract a slice from a matrix or tensor.
Definition: get_slice.hpp:101
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
The coordinates::pattern for index N of object T.
Definition: vector_space_descriptor_of.hpp:34
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
decltype(auto) to_native_matrix(Arg &&arg)
If it isn&#39;t already, convert Arg to a native object in the library associated with LibraryObject...
Definition: to_native_matrix.hpp:35
decltype(auto) constexpr QR_decomposition(A &&a)
Perform a QR decomposition of matrix A=Q[U,0], U is a upper-triangular matrix, and Q is orthogonal...
Definition: QR_decomposition.hpp:33
HermitianAdapterType
The type of a hermitian adapter, indicating which triangle of the nested matrix is used...
Definition: global-definitions.hpp:78
The size of a sized object (including a collection).
Definition: size_of.hpp:36
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
decltype(auto) constexpr to_diagonal(Arg &&arg)
Convert an indexible object into a diagonal matrix.
Definition: to_diagonal.hpp:32
decltype(auto) constexpr reduce(BinaryFunction &&b, Arg &&arg)
Perform a partial reduction based on an associative binary function, across one or more indices...
Definition: reduce.hpp:143
decltype(auto) constexpr broadcast(Arg &&arg, const Factors &...factors)
Broadcast an object by replicating it by factors specified for each index.
Definition: broadcast.hpp:49
Type scalar type (e.g., std::float, std::double, std::complex<double>) of a tensor.
Definition: scalar_type_of.hpp:32
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
decltype(auto) constexpr transpose(Arg &&arg)
Take the transpose of a matrix.
Definition: transpose.hpp:58
decltype(auto) constexpr all_vector_space_descriptors(const T &t)
Return a collection of coordinates::pattern objects associated with T.
Definition: all_vector_space_descriptors.hpp:52
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
constexpr A && contract_in_place(A &&a, B &&b)
In-place matrix multiplication of A * B, storing the result in A.
Definition: contract_in_place.hpp:38
constexpr auto solve(A &&a, B &&b)
Solve the equation AX = B for X, which may or may not be a unique solution.
Definition: solve.hpp:87
constexpr auto conj(const Arg &arg)
A constexpr function for the complex conjugate of a (complex) number.
Definition: conj.hpp:39
constexpr auto determinant(Arg &&arg)
Take the determinant of a matrix.
Definition: determinant.hpp:44
decltype(auto) constexpr diagonal_of(Arg &&arg)
Extract a column vector (or column slice for rank>2 tensors) comprising the diagonal elements...
Definition: diagonal_of.hpp:33
A generalization of the above: a custom stride is specified for each index.
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
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
decltype(auto) constexpr adjoint(Arg &&arg)
Take the adjoint of a matrix.
Definition: adjoint.hpp:33
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
Arg && fill_components(Arg &&arg, S...s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: fill_components.hpp:44
Layout
The layout format of a multidimensional array.
Definition: global-definitions.hpp:47
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
decltype(auto) constexpr LQ_decomposition(A &&a)
Perform an LQ decomposition of matrix A=[L,0]Q, L is a lower-triangular matrix, and Q is orthogonal...
Definition: LQ_decomposition.hpp:33
decltype(auto) rank_update_triangular(A &&a, U &&u, scalar_type_of_t< A > alpha=1)
Do a rank update on triangular matrix.
Definition: rank_update_triangular.hpp:48
A structure representing the dimensions associated with of a particular index.
Definition: Dimensions.hpp:42
constexpr bool index
T is an index value.
Definition: index.hpp:56
constexpr auto make_constant(C &&c, Descriptors &&descriptors)
Make a constant object based on a particular library object.
Definition: make_constant.hpp:37
constexpr To && assign(To &&a, From &&b)
Assign a writable object from an indexible object.
Definition: assign.hpp:51
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
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:34
constexpr bool vector
T is a vector (e.g., column or row vector).
Definition: vector.hpp:67
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448
constexpr auto get_index_dimension_of(const T &t, N n=N{})
Get the runtime dimensions of index N of indexible T.
Definition: get_index_dimension_of.hpp:34
constexpr bool hermitian_matrix
Specifies that a type is a hermitian matrix (assuming it is square_shaped).
Definition: hermitian_matrix.hpp:50
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
decltype(auto) constexpr make_triangular_matrix(Arg &&arg)
Create a triangular_matrix from a general matrix.
Definition: make_triangular_matrix.hpp:35
decltype(auto) constexpr cholesky_factor(A &&a)
Take the Cholesky factor of a matrix.
Definition: cholesky_factor.hpp:38
constexpr Arg && set_slice(Arg &&arg, Block &&block, const Begin &...begin)
Assign an object to a particular slice of a matrix or tensor.
Definition: set_slice.hpp:56