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