OpenKalman
interfaces-defined.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-2026 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_DEFINED_HPP
17 #define OPENKALMAN_INTERFACES_DEFINED_HPP
18 
19 #include <type_traits>
20 #include <utility>
21 #include "object_traits.hpp"
22 #include "library_interface.hpp"
24 
25 namespace OpenKalman::interface
26 {
27  // *************************************************** //
28  // object_traits //
29  // *************************************************** //
30 
31  // ------------------------ //
32  // get_pattern_collection //
33  // ------------------------ //
34 
35 #ifdef __cpp_concepts
36  template<typename T>
37  concept get_pattern_collection_defined_for =
38  requires(T t) { object_traits<std::remove_cvref_t<T>>::get_pattern_collection(t); };
39 #else
40  namespace detail
41  {
42  template<typename T, typename = void>
43  struct get_pattern_collection_defined_for_impl : std::false_type {};
44 
45  template<typename T>
47  std::void_t<decltype(object_traits<stdex::remove_cvref_t<T>>::get_pattern_collection(std::declval<T>()))>>
48  : std::true_type {};
49  }
50 
51  template<typename T>
52  constexpr bool get_pattern_collection_defined_for = detail::get_pattern_collection_defined_for_impl<T>::value;
53 #endif
54 
55 
56  // -------------- //
57  // get_constant //
58  // -------------- //
59 
60 #ifdef __cpp_concepts
61  template<typename T>
62  concept get_constant_defined_for =
63  requires (T t) { object_traits<std::remove_cvref_t<T>>::get_constant(t); };
64 #else
65  namespace detail
66  {
67  template<typename T, typename = void>
68  struct get_constant_defined_for_impl : std::false_type {};
69 
70  template<typename T>
72  std::void_t<decltype(object_traits<stdex::remove_cvref_t<T>>::get_constant(std::declval<T>()))>>
73  : std::true_type {};
74  }
75 
76  template<typename T>
77  constexpr bool get_constant_defined_for = detail::get_constant_defined_for_impl<T>::value;
78 #endif
79 
80 
81  // ----------- //
82  // is_square //
83  // ----------- //
84 
85 #ifdef __cpp_concepts
86  template<typename T, applicability b = applicability::guaranteed>
87  concept is_square_defined_for = std::convertible_to<
88  decltype(object_traits<std::remove_cvref_t<T>>::template is_square<b>), bool>;
89 #else
90  namespace detail
91  {
92  template<typename T, applicability b, typename = void>
93  struct is_square_defined_for_impl : std::false_type {};
94 
95  template<typename T, applicability b>
96  struct is_square_defined_for_impl<T, b, std::enable_if_t<stdex::convertible_to<
97  decltype(object_traits<stdex::remove_cvref_t<T>>::template is_square<b>), bool>>>
98  : std::true_type {};
99  }
100 
101  template<typename T, applicability b = applicability::guaranteed>
102  constexpr bool is_square_defined_for = detail::is_square_defined_for_impl<T, b>::value;
103 #endif
104 
105 
106  // ----------------------- //
107  // is_triangular_adapter //
108  // ----------------------- //
109 
110 #ifdef __cpp_concepts
111  template<typename T>
112  concept is_triangular_adapter_defined_for = std::convertible_to<
113  decltype(object_traits<std::remove_cvref_t<T>>::is_triangular_adapter), bool>;
114 #else
115  namespace detail
116  {
117  template<typename T, typename = void>
118  struct is_triangular_adapter_defined_for_impl : std::false_type {};
119 
120  template<typename T>
121  struct is_triangular_adapter_defined_for_impl<T, std::enable_if_t<stdex::convertible_to<
122  decltype(object_traits<stdex::remove_cvref_t<T>>::is_triangular_adapter), bool>>>
123  : std::true_type {};
124  }
125 
126  template<typename T>
127  constexpr bool is_triangular_adapter_defined_for = detail::is_triangular_adapter_defined_for_impl<T>::value;
128 #endif
129 
130 
131  // -------------- //
132  // is_hermitian //
133  // -------------- //
134 
135 #ifdef __cpp_concepts
136  template<typename T>
137  concept is_hermitian_defined_for = std::convertible_to<
138  decltype(object_traits<std::remove_cvref_t<T>>::is_hermitian), bool>;
139 #else
140  namespace detail
141  {
142  template<typename T, typename = void>
143  struct is_hermitian_defined_for_impl : std::false_type {};
144 
145  template<typename T>
146  struct is_hermitian_defined_for_impl<T, std::enable_if_t<std::is_convertible_v<
147  decltype(object_traits<stdex::remove_cvref_t<T>>::is_hermitian), bool>>>
148  : std::true_type {};
149  }
150 
151  template<typename T>
152  constexpr bool is_hermitian_defined_for = detail::is_hermitian_defined_for_impl<T>::value;
153 
154 
155  template<typename T, typename = void>
156  struct is_explicitly_hermitian : std::false_type {};
157 
158  template<typename T>
159  struct is_explicitly_hermitian<T, std::enable_if_t<object_traits<stdex::remove_cvref_t<T>>::is_hermitian>>
160  : std::true_type {};
161 #endif
162 
163 
164  // ------------------------ //
165  // hermitian_adapter_type //
166  // ------------------------ //
167 
168 #ifdef __cpp_concepts
169  template<typename T>
170  concept hermitian_adapter_type_defined_for = std::convertible_to<
171  decltype(object_traits<std::remove_cvref_t<T>>::hermitian_adapter_type), HermitianAdapterType>;
172 #else
173  namespace detail
174  {
175  template<typename T, typename = void>
176  struct hermitian_adapter_type_defined_for_impl : std::false_type {};
177 
178  template<typename T>
179  struct hermitian_adapter_type_defined_for_impl<T, std::enable_if_t<std::is_convertible_v<
180  decltype(object_traits<stdex::remove_cvref_t<T>>::hermitian_adapter_type), HermitianAdapterType>>>
181  : std::true_type {};
182  }
183 
184  template<typename T>
185  constexpr bool hermitian_adapter_type_defined_for = detail::hermitian_adapter_type_defined_for_impl<T>::value;
186 #endif
187 
188 
189  // ******************************************************* //
190  // library_interface //
191  // ******************************************************* //
192 
193  // -------------------------- //
194  // library_base_defined_for //
195  // -------------------------- //
196 
197 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS
198  template<typename Derived, typename LibraryObject>
199  concept library_base_defined_for = requires {
200  typename library_interface<std::remove_cvref_t<LibraryObject>>::template library_base<std::decay_t<Derived>>;
201  };
202 #else
203  namespace detail
204  {
205  template<typename Derived, typename LibraryObject, typename = void>
206  struct LibraryBase_defined_for_impl : std::false_type {};
207 
208  template<typename Derived, typename LibraryObject>
209  struct LibraryBase_defined_for_impl<Derived, LibraryObject,
210  std::void_t<typename library_interface<stdex::remove_cvref_t<LibraryObject>>::template library_base<std::decay_t<Derived>>>>
211  : std::true_type {};
212  }
213 
214  template<typename Derived, typename LibraryObject>
215  constexpr bool library_base_defined_for = detail::LibraryBase_defined_for_impl<Derived, LibraryObject>::value;
216 #endif
217 
218 
219  // ----------- //
220  // copy_from //
221  // ----------- //
222 
223 #ifdef __cpp_concepts
224  template<typename LHS, typename RHS>
225  concept copy_from_defined_for = requires(LHS lhs, RHS rhs) {
226  library_interface<std::remove_cvref_t<LHS>>::copy(lhs, std::forward<RHS>(rhs));
227  };
228 #else
229  namespace detail
230  {
231  template<typename LHS, typename RHS, typename = void>
232  struct copy_from_defined_for_impl : std::false_type {};
233 
234  template<typename LHS, typename RHS>
235  struct copy_from_defined_for_impl<LHS, RHS,
236  std::void_t<decltype(library_interface<stdex::remove_cvref_t<LHS>>::copy(std::declval<LHS>(), std::declval<RHS>()))>>
237  : std::true_type {};
238  }
239 
240  template<typename LHS, typename RHS>
241  constexpr bool copy_from_defined_for = detail::copy_from_defined_for_impl<LHS, RHS>::value;
242 #endif
243 
244 
245  // ------------- //
246  // to_diagonal //
247  // ------------- //
248 
249 #ifdef __cpp_concepts
250  template<typename Arg>
251  concept to_diagonal_defined_for = requires (Arg arg) {
253  };
254 #else
255  namespace detail
256  {
257  template<typename Arg, typename = void>
258  struct to_diagonal_defined_for_impl: std::false_type {};
259 
260  template<typename Arg>
262  std::void_t<decltype(library_interface<stdex::remove_cvref_t<Arg>>::to_diagonal(std::declval<Arg>()))>>
263  : std::true_type {};
264  }
265 
266  template<typename Arg>
267  constexpr bool to_diagonal_defined_for = detail::to_diagonal_defined_for_impl<Arg>::value;
268 #endif
269 
270 
271  // ------------- //
272  // diagonal_of //
273  // ------------- //
274 
275 #ifdef __cpp_concepts
276  template<typename Arg>
277  concept diagonal_of_defined_for = requires (Arg arg) {
279  };
280 #else
281  namespace detail
282  {
283  template<typename Arg, typename = void>
284  struct diagonal_of_defined_for_impl: std::false_type {};
285 
286  template<typename Arg>
287  struct diagonal_of_defined_for_impl<Arg, std::void_t<
288  decltype(library_interface<stdex::remove_cvref_t<Arg>>::diagonal_of(std::declval<Arg>()))>>
289  : std::true_type {};
290  }
291 
292  template<typename Arg>
293  constexpr bool diagonal_of_defined_for = detail::diagonal_of_defined_for_impl<Arg>::value;
294 #endif
295 
296 
297  // ----------- //
298  // conjugate //
299  // ----------- //
300 
301 #ifdef __cpp_concepts
302  template<typename Arg>
303  concept conjugate_defined_for = requires (Arg arg) {
305  };
306 #else
307  namespace detail
308  {
309  template<typename Arg, typename = void>
310  struct conjugate_defined_for_impl: std::false_type {};
311 
312  template<typename Arg>
314  std::void_t<decltype(library_interface<stdex::remove_cvref_t<Arg>>::conjugate(std::declval<Arg>()))>>
315  : std::true_type {};
316  }
317 
318  template<typename Arg>
319  constexpr bool conjugate_defined_for = detail::conjugate_defined_for_impl<Arg>::value;
320 #endif
321 
322 
323  // ----------- //
324  // transpose //
325  // ----------- //
326 
327 #ifdef __cpp_concepts
328  template<typename Arg, std::size_t indexa, std::size_t indexb>
329  concept transpose_defined_for = requires (Arg arg) {
330  library_interface<std::remove_cvref_t<Arg>>::template transpose<indexa, indexb>(std::forward<Arg>(arg));
331  };
332 #else
333  namespace detail
334  {
335  template<typename Arg, std::size_t indexa, std::size_t indexb, typename = void>
336  struct transpose_defined_for_impl: std::false_type {};
337 
338  template<typename Arg, std::size_t indexa, std::size_t indexb>
339  struct transpose_defined_for_impl<Arg, indexa, indexb,
340  std::void_t<decltype(library_interface<stdex::remove_cvref_t<Arg>>::template transpose<indexa, indexb>(std::declval<Arg>()))>>
341  : std::true_type {};
342  }
343 
344  template<typename Arg, std::size_t indexa, std::size_t indexb>
345  constexpr bool transpose_defined_for = detail::transpose_defined_for_impl<Arg, indexa, indexb>::value;
346 #endif
347 
348 
349  // --------------------- //
350  // conjugate_transpose //
351  // --------------------- //
352 
353 #ifdef __cpp_concepts
354  template<typename Arg>
355  concept conjugate_transpose_defined_for = requires (Arg arg) {
357  };
358 #else
359  namespace detail
360  {
361  template<typename Arg, typename = void>
362  struct conjugate_transpose_defined_for_impl: std::false_type {};
363 
364  template<typename Arg>
366  std::void_t<decltype(library_interface<stdex::remove_cvref_t<Arg>>::conjugate_transpose(std::declval<Arg>()))>>
367  : std::true_type {};
368  }
369 
370  template<typename Arg>
371  constexpr bool conjugate_transpose_defined_for = detail::conjugate_transpose_defined_for_impl<Arg>::value;
372 #endif
373 
374 
375  // ------------------ //
376  // to_native_matrix //
377  // ------------------ //
378 
379 #ifdef __cpp_concepts
380  template<typename T, typename Arg>
381  concept to_native_matrix_defined_for = requires (Arg arg) {
382  library_interface<std::remove_cvref_t<T>>::to_native_matrix(std::forward<Arg>(arg));
383  };
384 #else
385  namespace detail
386  {
387  template<typename T, typename Arg, typename = void>
388  struct to_native_matrix_defined_for_impl: std::false_type {};
389 
390  template<typename T, typename Arg>
392  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::to_native_matrix(std::declval<Arg>()))>>
393  : std::true_type {};
394  }
395 
396  template<typename T, typename Arg>
397  constexpr bool to_native_matrix_defined_for = detail::to_native_matrix_defined_for_impl<T, Arg>::value;
398 #endif
399 
400 
401  // -------------- //
402  // make_default //
403  // -------------- //
404 
405 #ifdef __cpp_concepts
406  template<typename T, typename layout, typename Scalar, typename D>
407  concept make_default_defined_for = requires(D d) {
408  library_interface<std::remove_cvref_t<T>>::template make_default<layout, Scalar>(std::forward<D>(d));
409  };
410 #else
411  namespace detail
412  {
413  template<typename T, typename layout, typename Scalar, typename D, typename = void>
414  struct make_default_defined_for_impl : std::false_type {};
415 
416  template<typename T, typename layout, typename Scalar, typename D>
417  struct make_default_defined_for_impl<T, layout, Scalar, D,
418  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template make_default<layout, Scalar>(std::declval<D>()))>>
419  : std::true_type {};
420  }
421 
422  template<typename T, typename layout, typename Scalar, typename D>
423  constexpr bool make_default_defined_for = detail::make_default_defined_for_impl<T, layout, Scalar, D>::value;
424 #endif
425 
426 
427  // ----------------- //
428  // fill_components //
429  // ----------------- //
430 
431 #ifdef __cpp_concepts
432  template<typename T, typename layout, typename Arg, typename...Scalars>
433  concept fill_components_defined_for = requires(Arg arg, Scalars...scalars) {
434  library_interface<std::remove_cvref_t<T>>::template fill_components<layout>(std::forward<Arg>(arg), std::forward<Scalars>(scalars)...);
435  };
436 #else
437  namespace detail
438  {
439  template<typename T, typename layout, typename Arg, typename = void, typename...Scalars>
440  struct fill_components_defined_for_impl : std::false_type {};
441 
442  template<typename T, typename layout, typename Arg, typename...Scalars>
443  struct fill_components_defined_for_impl<T, layout, Arg,
444  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template fill_components<layout>(std::declval<Arg>(), std::declval<Scalars>()...))>, Scalars...>
445  : std::true_type {};
446  }
447 
448  template<typename T, typename layout, typename Arg, typename...Scalars>
449  constexpr bool fill_components_defined_for = detail::fill_components_defined_for_impl<T, layout, Arg, void, Scalars...>::value;
450 #endif
451 
452 
453  // ------------------------ //
454  // make_triangular_matrix //
455  // ------------------------ //
456 
457 #ifdef __cpp_concepts
458  template<typename T, triangle_type tri, typename Arg>
459  concept make_triangular_matrix_defined_for = requires (Arg arg) {
460  library_interface<std::remove_cvref_t<T>>::template make_triangular_matrix<tri>(std::forward<Arg>(arg));
461  };
462 #else
463  namespace detail
464  {
465  template<typename T, triangle_type tri, typename Arg, typename = void>
466  struct make_triangular_matrix_defined_for_impl: std::false_type {};
467 
468  template<typename T, triangle_type tri, typename Arg>
470  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template make_triangular_matrix<tri>(std::declval<Arg>()))>>
471  : std::true_type {};
472  }
473 
474  template<typename T, triangle_type tri, typename Arg>
475  constexpr bool make_triangular_matrix_defined_for = detail::make_triangular_matrix_defined_for_impl<T, tri, Arg>::value;
476 #endif
477 
478 
479  // ------------------------ //
480  // make_hermitian_adapter //
481  // ------------------------ //
482 
483 #ifdef __cpp_concepts
484  template<typename T, HermitianAdapterType adapter_type, typename Arg>
485  concept make_hermitian_adapter_defined_for = requires (Arg arg) {
486  library_interface<std::remove_cvref_t<T>>::template make_hermitian_adapter<adapter_type>(std::forward<Arg>(arg));
487  };
488 #else
489  namespace detail
490  {
491  template<typename T, HermitianAdapterType adapter_type, typename Arg, typename = void>
492  struct make_hermitian_adapter_defined_for_impl: std::false_type {};
493 
494  template<typename T, HermitianAdapterType adapter_type, typename Arg>
495  struct make_hermitian_adapter_defined_for_impl<T, adapter_type, Arg,
496  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template make_hermitian_adapter<adapter_type>(std::declval<Arg>()))>>
497  : std::true_type {};
498  }
499 
500  template<typename T, HermitianAdapterType adapter_type, typename Arg>
501  constexpr bool make_hermitian_adapter_defined_for = detail::make_hermitian_adapter_defined_for_impl<T, adapter_type, Arg>::value;
502 #endif
503 
504 
505  // -------------- //
506  // to_euclidean //
507  // -------------- //
508 
509 #ifdef __cpp_concepts
510  template<typename T, typename Arg>
511  concept to_euclidean_defined_for = requires (Arg arg) {
513  };
514 #else
515  namespace detail
516  {
517  template<typename T, typename Arg, typename = void>
518  struct to_euclidean_defined_for_impl: std::false_type {};
519 
520  template<typename T, typename Arg>
522  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::to_euclidean(std::declval<Arg>()))>>
523  : std::true_type {};
524  }
525 
526  template<typename T, typename Arg>
527  constexpr bool to_euclidean_defined_for = detail::to_euclidean_defined_for_impl<T, Arg>::value;
528 #endif
529 
530 
531  // ---------------- //
532  // from_euclidean //
533  // ---------------- //
534 
535 #ifdef __cpp_concepts
536  template<typename T, typename Arg, typename V>
537  concept from_euclidean_defined_for = requires (Arg arg, V v) {
538  library_interface<std::remove_cvref_t<T>>::from_euclidean(std::forward<Arg>(arg), std::forward<V>(v));
539  };
540 #else
541  namespace detail
542  {
543  template<typename T, typename Arg, typename V, typename = void>
544  struct from_euclidean_defined_for_impl: std::false_type {};
545 
546  template<typename T, typename Arg, typename V>
548  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::from_euclidean(std::declval<Arg>(), std::declval<V>()))>>
549  : std::true_type {};
550  }
551 
552  template<typename T, typename Arg, typename V>
553  constexpr bool from_euclidean_defined_for = detail::from_euclidean_defined_for_impl<T, Arg, V>::value;
554 #endif
555 
556 
557  // ------------- //
558  // wrap_angles //
559  // ------------- //
560 
561 #ifdef __cpp_concepts
562  template<typename T, typename Arg>
563  concept wrap_angles_defined_for = requires (Arg arg) {
564  library_interface<std::remove_cvref_t<T>>::wrap_angles(std::forward<Arg>(arg));
565  };
566 #else
567  namespace detail
568  {
569  template<typename T, typename Arg, typename = void>
570  struct wrap_angles_defined_for_impl: std::false_type {};
571 
572  template<typename T, typename Arg>
574  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::wrap_angles(std::declval<Arg>()))>>
575  : std::true_type {};
576  }
577 
578  template<typename T, typename Arg>
579  constexpr bool wrap_angles_defined_for = detail::wrap_angles_defined_for_impl<T, Arg>::value;
580 #endif
581 
582 
583  // ----------- //
584  // get_slice //
585  // ----------- //
586 
587 #ifdef __cpp_concepts
588  template<typename T, typename Arg, typename BeginTup, typename SizeTup>
589  concept get_slice_defined_for = requires(Arg arg, BeginTup begin_tup, SizeTup size_tup) {
590  library_interface<std::remove_cvref_t<T>>::set_slice(std::forward<Arg>(arg), begin_tup, size_tup);
591  };
592 #else
593  namespace detail
594  {
595  template<typename T, typename Arg, typename BeginTup, typename SizeTup, typename = void>
596  struct get_slice_defined_for_impl : std::false_type {};
597 
598  template<typename T, typename Arg, typename BeginTup, typename SizeTup>
599  struct get_slice_defined_for_impl<T, Arg, BeginTup, SizeTup,
600  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::set_slice(std::declval<Arg>(), std::declval<BeginTup>(), std::declval<SizeTup>()))>>
601  : std::true_type {};
602  }
603 
604  template<typename T, typename Arg, typename BeginTup, typename SizeTup>
605  constexpr bool get_slice_defined_for = detail::get_slice_defined_for_impl<T, Arg, BeginTup, SizeTup>::value;
606 #endif
607 
608 
609  // ----------- //
610  // set_slice //
611  // ----------- //
612 
613 #ifdef __cpp_concepts
614  template<typename T, typename Arg, typename Block, typename...Begin>
615  concept set_slice_defined_for = requires(Arg arg, Block block, Begin...begin) {
616  library_interface<std::remove_cvref_t<T>>::set_slice(std::forward<Arg>(arg), std::forward<Block>(block), std::forward<Begin>(begin)...);
617  };
618 #else
619  namespace detail
620  {
621  template<typename T, typename Arg, typename Block, typename = void, typename...Begin>
622  struct set_slice_defined_for_impl : std::false_type {};
623 
624  template<typename T, typename Arg, typename Block, typename...Begin>
625  struct set_slice_defined_for_impl<T, Arg, Block,
626  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::set_slice(std::declval<Arg>(), std::declval<Block>(), std::declval<Begin>()...))>, Begin...>
627  : std::true_type {};
628  }
629 
630  template<typename T, typename Arg, typename Block, typename...Begin>
631  constexpr bool set_slice_defined_for = detail::set_slice_defined_for_impl<T, Arg, Block, Begin...>::value;
632 #endif
633 
634 
635  // -------------- //
636  // set_triangle //
637  // -------------- //
638 
639 #ifdef __cpp_concepts
640  template<typename T, triangle_type tri, typename A, typename B>
641  concept set_triangle_defined_for = requires(A a, B b) {
642  library_interface<std::remove_cvref_t<T>>::template set_triangle<tri>(std::forward<A>(a), std::forward<B>(b));
643  };
644 #else
645  namespace detail
646  {
647  template<typename T, triangle_type tri, typename A, typename B, typename = void>
648  struct set_triangle_defined_for_impl : std::false_type {};
649 
650  template<typename T, triangle_type tri, typename A, typename B>
651  struct set_triangle_defined_for_impl<T, tri, A, B,
652  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template set_triangle<tri>(std::declval<A>(), std::declval<B>()))>>
653  : std::true_type {};
654  }
655 
656  template<typename T, triangle_type tri, typename A, typename B>
657  constexpr bool set_triangle_defined_for = detail::set_triangle_defined_for_impl<T, tri, A, B>::value;
658 #endif
659 
660 
661  // ----------- //
662  // broadcast //
663  // ----------- //
664 
665 #ifdef __cpp_concepts
666  template<typename T, typename Arg, typename...Factors>
667  concept broadcast_defined_for = requires(Arg arg, Factors...factors) {
668  library_interface<std::remove_cvref_t<T>>::broadcast(std::forward<Arg>(arg), std::forward<Factors>(factors)...);
669  };
670 #else
671  namespace detail
672  {
673  template<typename T, typename Arg, typename = void, typename...Factors>
674  struct broadcast_defined_for_impl: std::false_type {};
675 
676  template<typename T, typename Arg, typename...Factors>
678  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::broadcast(std::declval<Arg>(), std::declval<Factors>()...))>, Factors...>
679  : std::true_type {};
680  }
681 
682  template<typename T, typename Arg, typename...Factors>
683  constexpr bool broadcast_defined_for = detail::broadcast_defined_for_impl<T, Arg, void, Factors...>::value;
684 #endif
685 
686 
687  // ----------------- //
688  // n_ary_operation //
689  // ----------------- //
690 
691 #ifdef __cpp_concepts
692  template<typename T, typename DTup, typename Op, typename...Args>
693  concept n_ary_operation_defined_for = requires(DTup d_tup, Op op, Args...args) {
694  library_interface<std::remove_cvref_t<T>>::n_ary_operation(d_tup, std::forward<Op>(op), std::forward<Args>(args)...);
695  };
696 #else
697  namespace detail
698  {
699  template<typename T, typename DTup, typename Op, typename = void, typename...Args>
700  struct n_ary_operation_defined_for_impl: std::false_type {};
701 
702  template<typename T, typename DTup, typename Op, typename...Args>
704  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::n_ary_operation(std::declval<DTup>(), std::declval<Op>(), std::declval<Args>()...))>, Args...>
705  : std::true_type {};
706  }
707 
708  template<typename T, typename DTup, typename Op, typename...Args>
709  constexpr bool n_ary_operation_defined_for = detail::n_ary_operation_defined_for_impl<T, DTup, Op, void, Args...>::value;
710 #endif
711 
712 
713  // -------- //
714  // reduce //
715  // -------- //
716 
717 #ifdef __cpp_concepts
718  template<typename T, typename BinaryFunction, typename Arg, std::size_t...indices>
719  concept reduce_defined_for = requires (BinaryFunction op, Arg arg) {
720  library_interface<std::remove_cvref_t<T>>::template reduce<indices...>(std::forward<BinaryFunction>(op), std::forward<Arg>(arg));
721  };
722 #else
723  namespace detail
724  {
725  template<typename T, typename BinaryFunction, typename Arg, typename = void, std::size_t...indices>
726  struct reduce_defined_for_impl: std::false_type {};
727 
728  template<typename T, typename BinaryFunction, typename Arg, std::size_t...indices>
729  struct reduce_defined_for_impl<T, BinaryFunction, Arg,
730  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template reduce<indices...>(std::declval<BinaryFunction>(), std::declval<Arg>()))>, indices...>
731  : std::true_type {};
732  }
733 
734  template<typename T, typename BinaryFunction, typename Arg, std::size_t...indices>
735  constexpr bool reduce_defined_for = detail::reduce_defined_for_impl<T, BinaryFunction, Arg, void, indices...>::value;
736 #endif
737 
738 
739  // ------------- //
740  // determinant //
741  // ------------- //
742 
743 #ifdef __cpp_concepts
744  template<typename T, typename Arg>
745  concept determinant_defined_for = requires (Arg arg) {
747  };
748 #else
749  namespace detail
750  {
751  template<typename T, typename Arg, typename = void>
752  struct determinant_defined_for_impl: std::false_type {};
753 
754  template<typename T, typename Arg>
756  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::determinant(std::declval<Arg>()))>>
757  : std::true_type {};
758  }
759 
760  template<typename T, typename Arg>
761  constexpr bool determinant_defined_for = detail::determinant_defined_for_impl<T, Arg>::value;
762 #endif
763 
764 
765  // ----- //
766  // sum //
767  // ----- //
768 
769 #ifdef __cpp_concepts
770  template<typename T, typename...Args>
771  concept sum_defined_for = requires(Args...args) {
772  library_interface<std::remove_cvref_t<T>>::sum(std::forward<Args>(args)...);
773  };
774 #else
775  namespace detail
776  {
777  template<typename T, typename = void, typename...Args>
778  struct sum_defined_for_impl : std::false_type {};
779 
780  template<typename T, typename...Args>
782  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::sum(std::declval<Args>()...))>, Args...>
783  : std::true_type {};
784  }
785 
786  template<typename T, typename...Args>
787  constexpr bool sum_defined_for = detail::sum_defined_for_impl<T, void, Args...>::value;
788 #endif
789 
790 
791  // ---------------- //
792  // scalar_product //
793  // ---------------- //
794 
795 #ifdef __cpp_concepts
796  template<typename T, typename Arg, typename S>
797  concept scalar_product_defined_for = requires(Arg arg, S s) {
798  library_interface<std::remove_cvref_t<T>>::scalar_product(std::forward<Arg>(arg), std::forward<S>(s));
799  };
800 #else
801  namespace detail
802  {
803  template<typename T, typename Arg, typename S, typename = void>
804  struct scalar_product_defined_for_impl : std::false_type {};
805 
806  template<typename T, typename Arg, typename S>
808  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::scalar_product(std::declval<Arg>(), std::declval<S>()))>>
809  : std::true_type {};
810  }
811 
812  template<typename T, typename Arg, typename S>
813  constexpr bool scalar_product_defined_for = detail::scalar_product_defined_for_impl<T, Arg, S>::value;
814 #endif
815 
816 
817  // ---------------- //
818  // scalar_product //
819  // ---------------- //
820 
821 #ifdef __cpp_concepts
822  template<typename T, typename Arg, typename S>
823  concept scalar_quotient_defined_for = requires(Arg arg, S s) {
824  library_interface<std::remove_cvref_t<T>>::scalar_quotient(std::forward<Arg>(arg), std::forward<S>(s));
825  };
826 #else
827  namespace detail
828  {
829  template<typename T, typename Arg, typename S, typename = void>
830  struct scalar_quotient_defined_for_impl : std::false_type {};
831 
832  template<typename T, typename Arg, typename S>
834  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::scalar_quotient(std::declval<Arg>(), std::declval<S>()))>>
835  : std::true_type {};
836  }
837 
838  template<typename T, typename Arg, typename S>
839  constexpr bool scalar_quotient_defined_for = detail::scalar_quotient_defined_for_impl<T, Arg, S>::value;
840 #endif
841 
842 
843  // ---------- //
844  // contract //
845  // ---------- //
846 
847 #ifdef __cpp_concepts
848  template<typename T, typename A, typename B>
849  concept contract_defined_for = requires(A a, B b) {
850  library_interface<std::remove_cvref_t<T>>::contract(std::forward<A>(a), std::forward<B>(b));
851  };
852 #else
853  namespace detail
854  {
855  template<typename T, typename A, typename B, typename = void>
856  struct contract_defined_for_impl : std::false_type {};
857 
858  template<typename T, typename A, typename B>
860  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::contract(std::declval<A>(), std::declval<B>()))>>
861  : std::true_type {};
862  }
863 
864  template<typename T, typename A, typename B>
865  constexpr bool contract_defined_for = detail::contract_defined_for_impl<T, A, B>::value;
866 #endif
867 
868 
869  // ------------------- //
870  // contract_in_place //
871  // ------------------- //
872 
873 #ifdef __cpp_concepts
874  template<typename T, bool on_the_right, typename A, typename B>
875  concept contract_in_place_defined_for = requires(A a, B b) {
876  library_interface<std::remove_cvref_t<T>>::template contract_in_place<on_the_right>(std::forward<A>(a), std::forward<B>(b));
877  };
878 #else
879  namespace detail
880  {
881  template<typename T, bool on_the_right, typename A, typename B, typename = void>
882  struct contract_in_place_defined_for_impl : std::false_type {};
883 
884  template<typename T, bool on_the_right, typename A, typename B>
885  struct contract_in_place_defined_for_impl<T, on_the_right, A, B,
886  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template contract_in_place<on_the_right>(std::declval<A>(), std::declval<B>()))>>
887  : std::true_type {};
888  }
889 
890  template<typename T, bool on_the_right, typename A, typename B>
891  constexpr bool contract_in_place_defined_for = detail::contract_in_place_defined_for_impl<T, on_the_right, A, B>::value;
892 #endif
893 
894 
895  // ----------------- //
896  // cholesky_factor //
897  // ----------------- //
898 
899 #ifdef __cpp_concepts
900  template<typename T, triangle_type tri, typename Arg>
901  concept cholesky_factor_defined_for = requires (Arg arg) {
902  library_interface<std::remove_cvref_t<T>>::template cholesky_factor<tri>(std::forward<Arg>(arg));
903  };
904 #else
905  namespace detail
906  {
907  template<typename T, triangle_type tri, typename Arg, typename = void>
908  struct cholesky_factor_defined_for_impl: std::false_type {};
909 
910  template<typename T, triangle_type tri, typename Arg>
912  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template cholesky_factor<tri>(std::declval<Arg>()))>>
913  : std::true_type {};
914  }
915 
916  template<typename T, triangle_type tri, typename Arg>
917  constexpr bool cholesky_factor_defined_for = detail::cholesky_factor_defined_for_impl<T, tri, Arg>::value;
918 #endif
919 
920 
921  // ----------------------- //
922  // rank_update_hermitian //
923  // ----------------------- //
924 
925 #ifdef __cpp_concepts
926  template<typename T, HermitianAdapterType significant_triangle, typename A, typename U, typename Alpha>
927  concept rank_update_self_adjoint_defined_for = requires (A a, U u, Alpha alpha) {
928  library_interface<std::remove_cvref_t<T>>::template rank_update_hermitian<significant_triangle>(std::forward<A>(a), std::forward<U>(u), alpha);
929  };
930 #else
931  namespace detail
932  {
933  template<typename T, HermitianAdapterType significant_triangle, typename A, typename U, typename Alpha, typename = void>
934  struct rank_update_self_adjoint_defined_for_impl: std::false_type {};
935 
936  template<typename T, HermitianAdapterType significant_triangle, typename A, typename U, typename Alpha>
937  struct rank_update_self_adjoint_defined_for_impl<T, significant_triangle, A, U, Alpha,
938  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template rank_update_hermitian<significant_triangle>(std::declval<A>(), std::declval<U>(), std::declval<Alpha>()))>>
939  : std::true_type {};
940  }
941 
942  template<typename T, HermitianAdapterType significant_triangle, typename A, typename U, typename Alpha>
944 #endif
945 
946 
947  // ------------------------ //
948  // rank_update_triangular //
949  // ------------------------ //
950 
951 #ifdef __cpp_concepts
952  template<typename T, triangle_type tri, typename A, typename U, typename Alpha>
953  concept rank_update_triangular_defined_for = requires (A a, U u, Alpha alpha) {
954  library_interface<std::remove_cvref_t<T>>::template rank_update_triangular<tri>(std::forward<A>(a), std::forward<U>(u), alpha);
955  };
956 #else
957  namespace detail
958  {
959  template<typename T, triangle_type tri, typename A, typename U, typename Alpha, typename = void>
960  struct rank_update_triangular_defined_for_impl: std::false_type {};
961 
962  template<typename T, triangle_type tri, typename A, typename U, typename Alpha>
963  struct rank_update_triangular_defined_for_impl<T, tri, A, U, Alpha,
964  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template rank_update_triangular<tri>(std::declval<A>(), std::declval<U>(), std::declval<Alpha>()))>>
965  : std::true_type {};
966  }
967 
968  template<typename T, triangle_type tri, typename A, typename U, typename Alpha>
969  constexpr bool rank_update_triangular_defined_for = detail::rank_update_triangular_defined_for_impl<T, tri, A, U, Alpha>::value;
970 #endif
971 
972 
973  // ------- //
974  // solve //
975  // ------- //
976 
977 #ifdef __cpp_concepts
978  template<typename T, bool must_be_unique, bool must_be_exact, typename A, typename B>
979  concept solve_defined_for = requires(A a, B b) {
980  library_interface<std::remove_cvref_t<T>>::template solve<must_be_unique, must_be_exact>(std::forward<A>(a), std::forward<B>(b));
981  };
982 #else
983  namespace detail
984  {
985  template<typename T, bool must_be_unique, bool must_be_exact, typename A, typename B, typename = void>
986  struct solve_defined_for_impl : std::false_type {};
987 
988  template<typename T, bool must_be_unique, bool must_be_exact, typename A, typename B>
989  struct solve_defined_for_impl<T, must_be_unique, must_be_exact, A, B,
990  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::template solve<must_be_unique, must_be_exact>(std::declval<A>(), std::declval<B>()))>>
991  : std::true_type {};
992  }
993 
994  template<typename T, bool must_be_unique, bool must_be_exact, typename A, typename B>
996 #endif
997 
998 
999  // ------------------ //
1000  // LQ_decomposition //
1001  // ------------------ //
1002 
1003 #ifdef __cpp_concepts
1004  template<typename T, typename Arg>
1005  concept LQ_decomposition_defined_for = requires (Arg arg) {
1007  };
1008 #else
1009  namespace detail
1010  {
1011  template<typename T, typename Arg, typename = void>
1012  struct LQ_decomposition_defined_for_impl: std::false_type {};
1013 
1014  template<typename T, typename Arg>
1016  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::LQ_decomposition(std::declval<Arg>()))>>
1017  : std::true_type {};
1018  }
1019 
1020  template<typename T, typename Arg>
1021  constexpr bool LQ_decomposition_defined_for = detail::LQ_decomposition_defined_for_impl<T, Arg>::value;
1022 #endif
1023 
1024 
1025  // ------------------ //
1026  // LQ_decomposition //
1027  // ------------------ //
1028 
1029 #ifdef __cpp_concepts
1030  template<typename T, typename Arg>
1031  concept QR_decomposition_defined_for = requires (Arg arg) {
1033  };
1034 #else
1035  namespace detail
1036  {
1037  template<typename T, typename Arg, typename = void>
1038  struct QR_decomposition_defined_for_impl: std::false_type {};
1039 
1040  template<typename T, typename Arg>
1042  std::void_t<decltype(library_interface<stdex::remove_cvref_t<T>>::QR_decomposition(std::declval<Arg>()))>>
1043  : std::true_type {};
1044  }
1045 
1046  template<typename T, typename Arg>
1047  constexpr bool QR_decomposition_defined_for = detail::QR_decomposition_defined_for_impl<T, Arg>::value;
1048 #endif
1049 
1050 
1051 }
1052 
1053 
1054 #endif
decltype(auto) constexpr from_euclidean(Arg &&arg, const V &v)
Project the Euclidean vector space associated with index 0 to patterns::pattern v after applying dire...
Definition: from_euclidean.hpp:35
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:325
decltype(auto) constexpr contract(A &&a, B &&b)
Matrix multiplication of A * B.
Definition: contract.hpp:54
Definition: basics.hpp:41
decltype(auto) constexpr conjugate(Arg &&arg)
Take the complex conjugate of an indexible object.
Definition: conjugate.hpp:44
decltype(auto) constexpr get_pattern_collection(T &&t)
Get the patterns::pattern_collection associated with indexible object T.
Definition: get_pattern_collection.hpp:36
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
decltype(auto) constexpr conjugate_transpose(Arg &&arg)
Take the conjugate-transpose of an indexible_object.
Definition: conjugate_transpose.hpp:35
HermitianAdapterType
The type of a hermitian adapter, indicating which triangle of the nested matrix is used...
Definition: enumerations.hpp:79
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
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
Enumerations relating to linear algebra.
Definition: interfaces-defined.hpp:156
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
Definition: interfaces-defined.hpp:778
Definition: interfaces-defined.hpp:856
Forward declaration of object_traits, which must be defined for all objects used in OpenKalman...
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
Forward declaration of library_interface, which must be defined for all objects used in OpenKalman...
Definition: object_traits.hpp:38
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:44
constexpr auto determinant(Arg &&arg)
Take the determinant of a matrix.
Definition: determinant.hpp:44
Definition: interfaces-defined.hpp:726
Definition: interfaces-defined.hpp:310
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
Definition: interfaces-defined.hpp:622
Definition: interfaces-defined.hpp:232
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
Definition: interfaces-defined.hpp:674
Definition: interfaces-defined.hpp:336
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) constexpr to_diagonal(Arg &&arg, P &&p)
Convert a column vector (or any other array with a 1D second index) into a diagonal_matrix.
Definition: to_diagonal.hpp:46
Definition: interfaces-defined.hpp:986
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:292
Definition: interfaces-defined.hpp:596
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