16 #ifndef OPENKALMAN_INTERFACES_FIXEDSIZEADAPTER_HPP 17 #define OPENKALMAN_INTERFACES_FIXEDSIZEADAPTER_HPP 26 template<
typename NestedObject,
typename Descriptors>
27 struct object_traits<internal::FixedSizeAdapter<NestedObject, Descriptors>>
37 using scalar_type = scalar_type_of_t<NestedObject>;
40 template<
typename Arg>
44 using NewDesc = decltype(OpenKalman::patterns::internal::strip_1D_tail(std::declval<Descriptors>()));
49 template<
typename Arg,
typename N>
53 if constexpr (values::fixed<N>)
69 template<
typename Arg>
70 static decltype(
auto) nested_object(Arg&& arg)
72 return std::forward<Arg>(arg).nested_object();
77 template<
typename Arg> requires constant_matrix<NestedObject>
79 template<
typename M = NestedObject,
typename Arg, std::enable_if_t<constant_matrix<M>,
int> = 0>
81 static constexpr
auto get_constant(
const Arg& arg)
88 template<
typename Arg> requires constant_diagonal_matrix<NestedObject>
90 template<
typename M = NestedObject,
typename Arg, std::enable_if_t<constant_diagonal_matrix<M>,
int> = 0>
92 static constexpr
auto get_constant_diagonal(
const Arg& arg)
94 return constant_diagonal_value {nested_object(arg)};
107 static constexpr
bool is_triangular_adapter =
false;
110 static constexpr
bool is_hermitian = hermitian_matrix<NestedObject, applicability::permitted>;
113 static constexpr
bool is_writable = writable<NestedObject>;
116 #ifdef __cpp_lib_concepts 117 template<
typename Arg> requires raw_data_defined_for<nested_object_of_t<Arg&&>>
119 template<typename Arg, std::enable_if_t<raw_data_defined_for<typename nested_object_of<Arg&&>::type>,
int> = 0>
121 static constexpr decltype(
auto)
124 return internal::raw_data(OpenKalman::nested_object(std::forward<Arg>(arg)));
128 static constexpr data_layout layout = layout_of_v<NestedObject>;
131 #ifdef __cpp_concepts 132 template<
typename Arg> requires (layout == data_layout::stride)
134 template<data_layout l = layout,
typename Arg, std::enable_if_t<l == data_layout::str
ide,
int> = 0>
139 return OpenKalman::internal::strides(nested_object(std::forward<Arg>(arg)));
149 template<
typename Nested,
typename Descriptors>
154 using NestedObject = std::decay_t<Nested>;
159 template<
typename Derived>
160 using library_base = internal::library_base_t<Derived, NestedObject>;
164 template<
typename Object,
typename Indices>
165 static constexpr decltype(
auto) add_trailing_indices(
const Indices& indices)
167 if constexpr (not index_collection_for<Indices, Object>)
169 constexpr
auto N = index_count_v<Object>;
170 std::array<std::size_t, N> ret;
171 std::ranges::fill(std::ranges::copy<stdex::ranges::begin(indices), stdex::ranges::end(indices), stdex::ranges::begin(ret)), stdex::ranges::end(ret), 0);
179 #ifdef __cpp_lib_ranges 180 template<indexible Arg, std::ranges::input_range Indices> requires values::index<std::ranges::range_value_t<Indices>> and
181 interface::get_component_defined_for<NestedObject, nested_object_of_t<Arg&>, std::initializer_list<std::size_t>>
182 static constexpr values::scalar decltype(
auto)
184 template<
typename Arg,
typename Indices, std::enable_if_t<
185 interface::get_component_defined_for<NestedObject, typename nested_object_of<Arg&>::type, std::initializer_list<std::size_t>>,
int> = 0>
186 static constexpr decltype(
auto)
188 get_component(Arg&& arg,
const Indices& indices)
190 return NestedInterface::get_component(nested_object(std::forward<Arg>(arg)), add_trailing_indices<NestedObject>(indices));
194 #ifdef __cpp_lib_ranges 195 template<indexible Arg, std::ranges::input_range Indices> requires values::index<std::ranges::range_value_t<Indices>> and
196 interface::set_component_defined_for<NestedObject, nested_object_of_t<Arg&>,
const scalar_type_of_t<Arg>&, std::initializer_list<std::size_t>>
198 template<
typename Arg,
typename Indices, std::enable_if_t<
199 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>
201 static constexpr
void 202 set_component(Arg& arg,
const scalar_type_of_t<Arg>& s,
const Indices& indices)
204 NestedInterface::set_component(nested_object(arg), s, add_trailing_indices<NestedObject>(indices));
208 #ifdef __cpp_concepts 209 template<
typename A> requires interface::to_native_matrix_defined_for<NestedObject, nested_object_of_t<A&&>>
211 template<
typename A, std::enable_if_t<
interface::to_native_matrix_defined_for<NestedObject, nested_
object_of_t<A&&>>,
int> = 0>
213 static decltype(
auto)
214 to_native_matrix(
A&& a)
216 return internal::make_fixed_size_adapter<Descriptors>(NestedInterface::to_native_matrix(nested_object(std::forward<A>(a))));
220 #ifdef __cpp_concepts 221 template<
typename To,
typename From> requires
222 interface::copy_defined_for<NestedObject, nested_object_of_t<To&>, From&&>
224 template<
typename To,
typename From, std::enable_if_t<
225 interface::copy_defined_for<NestedObject, nested_object_of_t<To&>, From&&>,
int> = 0>
228 copy(To& a, From&& b)
230 NestedInterface::copy(nested_object(a), std::forward<From>(b));
234 #ifdef __cpp_concepts 235 template<data_layout layout,
typename Scalar,
typename D> requires
236 interface::make_default_defined_for<NestedObject, layout, Scalar, D&&>
238 template<data_layout layout,
typename Scalar,
typename D, std::enable_if_t<
239 interface::make_default_defined_for<NestedObject, layout, Scalar, D&&>,
int> = 0>
244 return NestedInterface::template make_default<layout, Scalar>(std::forward<D>(d));
248 #ifdef __cpp_concepts 249 template<data_layout layout,
typename Arg,
typename...Scalars> requires
250 interface::fill_components_defined_for<NestedObject, layout, nested_object_of_t<Arg&>, Scalars...>
252 template<data_layout layout,
typename Arg,
typename...Scalars, std::enable_if_t<
253 interface::fill_components_defined_for<NestedObject, layout, typename nested_object_of<Arg&>::type, Scalars...>,
int> = 0>
258 NestedInterface::template fill_components<layout>(nested_object(arg), scalars...);
262 #ifdef __cpp_concepts 263 template<
typename C,
typename D> requires interface::make_constant_defined_for<NestedObject, C&&, D&&>
265 template<
typename C,
typename D, std::enable_if_t<
interface::make_constant_defined_for<NestedObject, C&&, D&&>,
int> = 0>
267 static constexpr
auto 274 #ifdef __cpp_concepts 275 template<
typename Scalar,
typename D> requires interface::make_identity_matrix_defined_for<NestedObject, Scalar, D&&>
277 template<
typename Scalar,
typename D, std::enable_if_t<
interface::make_
identity_matrix_defined_for<NestedObject, Scalar, D&&>,
int> = 0>
279 static constexpr
auto 286 #ifdef __cpp_concepts 287 template<triangle_type t, indexible Arg> requires
288 interface::make_triangular_matrix_defined_for<NestedObject, t, nested_object_of_t<Arg&&>>
289 static constexpr triangular_matrix<t>
auto 292 interface::make_triangular_matrix_defined_for<NestedObject, t, typename nested_object_of<Arg&&>::type>,
int> = 0>
293 static constexpr
auto 297 return internal::make_fixed_size_adapter<Descriptors>(NestedInterface::template make_triangular_matrix<t>(nested_object(std::forward<Arg>(arg))));
301 #ifdef __cpp_concepts 302 template<HermitianAdapterType t, indexible Arg> requires
303 interface::make_hermitian_adapter_defined_for<NestedObject, t, nested_object_of_t<Arg&&>>
307 make_hermitian_adapter_defined_for<NestedObject, t, typename nested_object_of<Arg&>::type>,
int> = 0>
308 static constexpr
auto 310 make_hermitian_adapter(Arg&& arg)
312 return internal::make_fixed_size_adapter<Descriptors>(NestedInterface::template make_hermitian_adapter<t>(nested_object(std::forward<Arg>(arg))));
317 template<
typename Arg,
typename...Begin,
typename...Size, std::size_t...Ix>
318 static decltype(
auto)
319 get_slice_impl(Arg&& arg,
const std::tuple<Begin...>& begin_tup,
const std::tuple<Size...>& size_tup,
std::index_sequence<Ix...>)
321 using NewDesc = std::tuple<std::decay_t<decltype(patterns::get_slice<scalar_type_of_t<Arg>>(
322 std::declval<collections::collection_element_t<Ix, Descriptors>>, std::declval<Begin>(), std::declval<Size>()))>...>;
323 return internal::make_fixed_size_adapter<NewDesc>(
NestedInterface::get_slice(nested_object(std::forward<Arg>(arg)), begin_tup, size_tup));
328 #ifdef __cpp_concepts 329 template<
typename Arg,
typename...Begin,
typename...Size> requires
330 interface::get_slice_defined_for<NestedObject, nested_object_of_t<Arg&&>,
const std::tuple<Begin...>&,
const std::tuple<Size...>&>
332 template<
typename Arg,
typename...Begin,
typename...Size, std::enable_if_t<
333 interface::get_slice_defined_for<NestedObject, typename nested_object_of<Arg&&>::type,
const std::tuple<Begin...>&,
const std::tuple<Size...>&>,
int> = 0>
335 static decltype(
auto)
336 get_slice(Arg&& arg,
const std::tuple<Begin...>& begin_tup,
const std::tuple<Size...>& size_tup)
338 return get_slice_impl(std::forward<Arg>(arg), begin_tup, size_tup, std::make_index_sequence<collections::size_of_v<Descriptors>>{});
342 #ifdef __cpp_concepts 343 template<
typename Arg,
typename Block,
typename...Begin> requires
344 interface::set_slice_defined_for<Arg, nested_object_of_t<Arg&>, Block&&,
const Begin&...>
346 template<
typename Arg,
typename Block,
typename...Begin, std::enable_if_t<
347 interface::set_slice_defined_for<Arg, typename nested_object_of<Arg&>::type, Block&&,
const Begin&...>,
int> = 0>
350 set_slice(Arg& arg, Block&& block,
const Begin&...begin)
356 #ifdef __cpp_concepts 357 template<triangle_type t,
typename A,
typename B> requires
358 interface::set_triangle_defined_for<NestedObject, t, nested_object_of_t<A&&>, B&&>
360 template<
triangle_type t,
typename A,
typename B, std::enable_if_t<
361 interface::set_triangle_defined_for<NestedObject, t, typename nested_object_of<A&&>::type, B&&>,
int> = 0>
364 set_triangle(A&& a, B&& b)
366 NestedInterface::template set_triangle<t>(nested_object(std::forward<A>(a)), std::forward<B>(b));
370 #ifdef __cpp_concepts 371 template<
typename Arg> requires
372 interface::to_diagonal_defined_for<NestedObject, nested_object_of_t<Arg&&>>
375 template<
typename Arg, std::enable_if_t<
376 interface::to_diagonal_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
377 static constexpr
auto 381 using D = vector_space_descriptor_of_t<Arg, 0>;
387 template<
typename Arg,
typename V0,
typename V1,
typename...Vs>
388 static constexpr decltype(
auto)
389 diagonal_of_impl(Arg&& arg,
const std::tuple<V0, V1, Vs...>&)
391 using D0 = decltype(internal::smallest_pattern<scalar_type_of_t<Arg>>(std::declval<V0>(), std::declval<V1>()));
392 return OpenKalman::internal::make_fixed_size_adapter<D0, Vs...>(std::forward<Arg>(arg));
397 #ifdef __cpp_concepts 398 template<indexible Arg> requires (diagonal_matrix<NestedObject> and internal::has_nested_vector<NestedObject>) or
399 (diagonal_matrix<NestedObject> and internal::has_nested_vector<NestedObject, 1> and
400 interface::transpose_defined_for<NestedObject, decltype(nested_object(nested_object(std::declval<Arg>())))>) or
401 interface::diagonal_of_defined_for<NestedObject, nested_object_of_t<Arg&&>>
404 template<
typename Arg, std::enable_if_t<(diagonal_matrix<NestedObject> and
internal::has_nested_vector<NestedObject>) or
405 (diagonal_matrix<NestedObject> and
internal::has_nested_vector<NestedObject, 1> and
406 interface::transpose_defined_for<NestedObject, decltype(nested_
object(nested_
object(std::declval<Arg>())))>) or
407 interface::diagonal_of_defined_for<NestedObject,
typename nested_
object_of<Arg&&>::type>,
int> = 0>
408 static constexpr
auto 412 if constexpr (diagonal_matrix<NestedObject> and internal::has_nested_vector<NestedObject>)
413 return diagonal_of_impl(nested_object(nested_object(std::forward<Arg>(arg))));
414 else if constexpr (diagonal_matrix<NestedObject> and internal::has_nested_vector<NestedObject, 1> and
415 interface::transpose_defined_for<NestedObject, decltype(nested_object(nested_object(std::declval<Arg>())))>)
424 template<std::
size_t Ix,
typename Arg,
typename Factors_tup>
425 static constexpr
auto broadcast_for_index(
const Arg& arg,
const Factors_tup& factors_tup)
427 constexpr
auto N = collections::size_of_v<Factors_tup>;
428 if constexpr (Ix < N)
429 return get_pattern_collection<Ix>(arg) * std::get<Ix>(factors_tup);
435 template<
typename Arg, std::size_t...Is,
typename Factors_tup>
438 constexpr
auto N = collections::size_of_v<Factors_tup>;
439 return internal::make_fixed_size_adapter<decltype(broadcast_for_index<Is>(arg, factors_tup))...>(std::forward<Arg>(arg));
444 #ifdef __cpp_concepts 446 interface::broadcast_defined_for<NestedObject, nested_object_of_t<Arg&&>,
const Factors&...>
449 template<
typename Arg,
typename...Factors, std::enable_if_t<
450 interface::broadcast_defined_for<NestedObject, typename nested_object_of<Arg&&>::type,
const Factors&...>,
int> = 0>
453 broadcast(Arg&& arg,
const Factors&...factors)
456 using Ret = decltype(ret);
457 auto seq = std::make_index_sequence<std::max(index_count_v<Arg>,
sizeof...(factors))>{};
458 return broadcast_impl(std::forward<Ret>(ret), seq, std::forward_as_tuple(factors...));
462 #ifdef __cpp_concepts 464 interface::n_ary_operation_defined_for<
NestedInterface,
const std::tuple<IDs...>&, Operation&&>
467 template<
typename...IDs,
typename Operation, std::enable_if_t<
468 interface::n_ary_operation_defined_for<NestedInterface,
const std::tuple<IDs...>&, Operation&&>,
int> = 0>
477 #ifdef __cpp_concepts 479 interface::n_ary_operation_defined_for<NestedObject,
const std::tuple<IDs...>&, Operation&&, nested_object_of_t<Arg&&>, Args...>
482 template<
typename...IDs,
typename Operation,
typename Arg,
typename...Args, std::enable_if_t<
483 interface::n_ary_operation_defined_for<NestedObject,
const std::tuple<IDs...>&, Operation&&,
typename nested_object_of<Arg&&>::type, Args...>,
int> = 0>
486 n_ary_operation(
const std::tuple<IDs...>& d_tup, Operation&& op, Arg&& arg, Args&&...args)
488 return internal::make_fixed_size_adapter<IDs...>(
494 template<std::size_t Ix, std::size_t...indices>
495 static constexpr
bool matching_Ix() {
return ((Ix == indices) or ...); }
497 template<std::size_t...indices,
typename Arg, std::size_t...Ix>
498 static constexpr decltype(
auto)
501 return internal::make_fixed_size_adapter<std::tuple<
503 matching_Ix<Ix, indices...>(),
504 uniform_pattern_component_of_t<vector_space_descriptor_of_t<Arg, Ix>>,
506 (std::forward<Arg>(arg));
511 #ifdef __cpp_concepts 512 template<std::size_t...indices,
typename BinaryFunction,
indexible Arg> requires
513 interface::reduce_defined_for<NestedObject, BinaryFunction&&, nested_object_of_t<Arg&&>, indices...>
515 template<std::size_t...indices,
typename BinaryFunction,
typename Arg, std::enable_if_t<
516 interface::reduce_defined_for<NestedObject, BinaryFunction&&, typename nested_object_of<Arg&&>::type, indices...>,
int> = 0>
518 static constexpr decltype(
auto)
519 reduce(BinaryFunction&& op, Arg&& arg)
521 return reduce_impl<indices...>(
522 NestedInterface::template
reduce<indices...>(std::forward<BinaryFunction>(op), nested_object(std::forward<Arg>(arg))),
523 std::make_index_sequence<collections::size_of_v<Descriptors>>{});
527 #ifdef __cpp_concepts 528 template<indexible Arg> requires interface::to_euclidean_defined_for<NestedObject, nested_object_of_t<Arg&&>>
531 template<
typename Arg, std::enable_if_t<
532 interface::to_euclidean_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
533 static constexpr
auto 537 constexpr
auto dim = collections::size_of_v<Descriptors>;
538 if constexpr (dim == 0)
540 return std::forward<Arg>(arg);
545 if constexpr (patterns::euclidean_pattern<D0>)
547 return std::forward<Arg>(arg);
551 using V0 = std::conditional_t<
554 patterns::DynamicDescriptor<scalar_type_of_t<Arg>>>;
555 using Vtail = std::decay_t<decltype(internal::tuple_slice<1, dim>(std::declval<Descriptors>()))>;
556 using Vcat = decltype(std::tuple_cat(std::declval<V0>()), std::declval<Vtail>());
563 #ifdef __cpp_concepts 564 template<indexible Arg, patterns::pattern D> requires
565 interface::from_euclidean_defined_for<NestedObject, nested_object_of_t<Arg&&>, D&&>
568 template<
typename Arg,
typename V, std::enable_if_t<
569 interface::from_euclidean_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, V&&>,
int> = 0>
570 static constexpr
auto 574 if constexpr (patterns::euclidean_pattern<D>)
576 return std::forward<Arg>(arg);
580 constexpr
auto dim = collections::size_of_v<Descriptors>;
581 using Vtail = std::decay_t<decltype(internal::tuple_slice<1, dim>(std::declval<Descriptors>()))>;
582 using Vcat = decltype(std::tuple_cat(std::declval<D>()), std::declval<Vtail>());
588 #ifdef __cpp_concepts 589 template<indexible Arg> requires interface::wrap_angles_defined_for<NestedObject, nested_object_of_t<Arg&&>>
592 template<
typename Arg, std::enable_if_t<
593 interface::wrap_angles_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
594 static constexpr
auto 596 wrap_angles(Arg&& arg)
598 return internal::make_fixed_size_adapter<Descriptors>(NestedInterface::wrap_angles(nested_object(std::forward<Arg>(arg))));
602 #ifdef __cpp_concepts 603 template<indexible Arg> requires
604 interface::conjugate_defined_for<NestedObject, Arg&&> or
605 interface::conjugate_defined_for<NestedObject, nested_object_of_t<Arg&&>>
608 template<
typename Arg, std::enable_if_t<
609 interface::conjugate_defined_for<NestedObject, Arg&&> or
610 interface::conjugate_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
611 static constexpr
auto 615 if constexpr (interface::conjugate_defined_for<NestedObject, Arg&&>)
622 return internal::make_fixed_size_adapter_like<Arg>(std::forward<decltype(conj)>(
conj));
627 #ifdef __cpp_concepts 628 template<indexible Arg> requires
629 interface::transpose_defined_for<NestedObject, Arg&&> or
630 interface::transpose_defined_for<NestedObject, nested_object_of_t<Arg&&>>
633 template<
typename Arg, std::enable_if_t<
634 interface::transpose_defined_for<NestedObject, Arg&&> or
635 interface::transpose_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
636 static constexpr
auto 640 if constexpr (interface::transpose_defined_for<NestedObject, Arg&&>)
646 return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<Arg, 1>, vector_space_descriptor_of_t<Arg, 0>>(
652 #ifdef __cpp_concepts 653 template<indexible Arg> requires
654 interface::adjoint_defined_for<NestedObject, Arg&&> or
655 interface::adjoint_defined_for<NestedObject, nested_object_of_t<Arg&&>>
658 template<
typename Arg, std::enable_if_t<
659 interface::adjoint_defined_for<NestedObject, Arg&&> or
660 interface::adjoint_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
661 static constexpr
auto 665 if constexpr (interface::adjoint_defined_for<NestedObject, Arg&&>)
671 return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<Arg, 1>, vector_space_descriptor_of_t<Arg, 0>>(
677 #ifdef __cpp_concepts 678 template<indexible Arg> requires
679 interface::determinant_defined_for<NestedObject, Arg&&> or
680 interface::determinant_defined_for<NestedObject, nested_object_of_t<Arg&&>>
681 static constexpr std::convertible_to<scalar_type_of_t<Arg>>
auto 683 template<
typename Arg, std::enable_if_t<
684 interface::determinant_defined_for<NestedObject, Arg&&> or
685 interface::determinant_defined_for<NestedObject, typename nested_object_of<Arg&&>::type>,
int> = 0>
686 static constexpr
auto 690 if constexpr (interface::determinant_defined_for<NestedObject, Arg&&>)
701 #ifdef __cpp_concepts 702 template<
typename Arg,
typename...Args> requires
703 interface::sum_defined_for<NestedObject, Arg&&, Args&&...> or
704 interface::sum_defined_for<NestedObject, nested_object_of_t<Arg&&>, Args&&...>
706 template<
typename Arg,
typename...Args, std::enable_if_t<
707 interface::sum_defined_for<NestedObject, Arg&&, Args&&...> or
708 interface::sum_defined_for<NestedObject, typename nested_object_of<Arg&&>::type, Args&&...>,
int> = 0>
711 sum(Arg&& arg, Args&&...args)
713 if constexpr (interface::sum_defined_for<NestedObject, Arg&&, Args&&...>)
719 return NestedInterface::sum(nested_object(std::forward<Arg>(arg)), std::forward<Args>(args)...);
724 #ifdef __cpp_concepts 725 template<
typename A,
typename B> requires
726 interface::contract_defined_for<NestedObject, A&&, B&&> or
727 interface::contract_defined_for<NestedObject, nested_object_of_t<A&&>, B&&>
729 template<
typename A,
typename B, std::enable_if_t<
730 interface::contract_defined_for<NestedObject, A&&, B&&> or
731 interface::contract_defined_for<NestedObject, typename nested_object_of<A&&>::type, B&&>,
int> = 0>
736 if constexpr (interface::contract_defined_for<NestedObject, A&&, B&&>)
742 return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<A, 0>, vector_space_descriptor_of_t<B, 1>>(
748 #ifdef __cpp_concepts 749 template<
bool on_the_right,
typename A,
typename B> requires
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, nested_object_of_t<A&&>, B&&>
753 template<
bool on_the_right,
typename A,
typename B, std::enable_if_t<
754 interface::contract_in_place_defined_for<NestedObject, on_the_right, A&&, B&&> or
755 interface::contract_in_place_defined_for<NestedObject, on_the_right, typename nested_object_of<A&&>::type, B&&>,
int> = 0>
757 static decltype(
auto)
760 if constexpr (interface::contract_in_place_defined_for<NestedObject, on_the_right, A&&, B&&>)
762 return NestedInterface::template contract_in_place<on_the_right>(std::forward<A>(a), std::forward<B>(b));
766 auto&& ret = NestedInterface::template contract_in_place<on_the_right>(nested_object(std::forward<A>(a)), std::forward<B>(b));
767 using Ret = decltype(ret);
768 if constexpr (std::is_lvalue_reference_v<Ret> and std::is_same_v<Ret, nested_object_of_t<A&&>>)
770 return std::forward<A>(a);
772 else if constexpr (on_the_right)
774 return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<A, 0>, vector_space_descriptor_of_t<B, 1>>(std::forward<Ret>(ret));
778 return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<B, 0>, vector_space_descriptor_of_t<A, 1>>(std::forward<Ret>(ret));
784 #ifdef __cpp_concepts 785 template<triangle_type tri, indexible Arg> requires
786 interface::cholesky_factor_defined_for<NestedObject, tri, Arg&&> or
787 interface::cholesky_factor_defined_for<NestedObject, tri, nested_object_of_t<Arg&&>>
788 static constexpr triangular_matrix<tri>
auto 791 interface::cholesky_factor_defined_for<NestedObject, tri, Arg&&> or
792 interface::cholesky_factor_defined_for<NestedObject, tri, typename nested_object_of<Arg&&>::type>,
int> = 0>
793 static constexpr
auto 797 if constexpr (interface::cholesky_factor_defined_for<NestedObject, tri, Arg&&>)
799 return NestedInterface::template cholesky_factor<tri>(std::forward<Arg>(arg));
803 auto tri = NestedInterface::template cholesky_factor<tri>(nested_object(std::forward<Arg>(arg)));
804 return internal::make_fixed_square_adapter_like(std::move(tri));
809 #ifdef __cpp_concepts 810 template<HermitianAdapterType significant_triangle, indexible A, indexible U> requires
811 interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, A&&, U&&, const scalar_type_of_t<A>&> or
812 interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, nested_object_of_t<A&&>, U&&,
const scalar_type_of_t<A>&>
816 interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, A&&, U&&, const typename scalar_type_of<A>::type&> or
817 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>
818 static constexpr
auto 822 if constexpr (interface::rank_update_self_adjoint_defined_for<NestedObject, significant_triangle, A&&, U&&,
const scalar_type_of_t<A>&>)
824 return NestedInterface::template rank_update_hermitian<significant_triangle>(std::forward<A>(a), std::forward<U>(u), alpha);
828 auto tri = NestedInterface::template rank_update_hermitian<significant_triangle>(nested_object(std::forward<A>(a), std::forward<U>(u), alpha));
829 return internal::make_fixed_square_adapter_like(std::move(tri));
834 #ifdef __cpp_concepts 835 template<triangle_type tri, indexible A, indexible U> requires
836 interface::rank_update_triangular_defined_for<NestedObject, tri, A&&, U&&, const scalar_type_of_t<A>&> or
837 interface::rank_update_triangular_defined_for<NestedObject, tri, nested_object_of_t<A&&>, U&&,
const scalar_type_of_t<A>&>
838 static constexpr triangular_matrix<tri>
auto 840 template<
triangle_type tri,
typename A,
typename U, std::enable_if_t<
841 interface::rank_update_triangular_defined_for<NestedObject, tri, A&&, U&&, const typename scalar_type_of<A>::type&> or
842 interface::rank_update_triangular_defined_for<NestedObject, tri, typename nested_object_of<A&&>::type, U&&,
const typename scalar_type_of<A>::type&>,
int> = 0>
843 static constexpr
auto 847 if constexpr (interface::rank_update_triangular_defined_for<NestedObject, tri, A&&, U&&,
const scalar_type_of_t<A>&>)
849 return NestedInterface::template rank_update_triangular<tri>(std::forward<A>(a), std::forward<U>(u), alpha);
853 auto tri = NestedInterface::template rank_update_triangular<tri>(nested_object(std::forward<A>(a), std::forward<U>(u), alpha));
854 return internal::make_fixed_square_adapter_like(std::move(tri));
859 #ifdef __cpp_concepts 860 template<
bool must_be_unique,
bool must_be_exact,
typename A,
typename B> requires
861 interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, A&&, B&&> or
862 interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, nested_object_of_t<A&&>, B&&>
863 static compatible_with_vector_space_descriptor_collection<std::tuple<vector_space_descriptor_of_t<A, 1>, vector_space_descriptor_of_t<B, 1>>>
auto 865 template<
bool must_be_unique,
bool must_be_exact,
typename A,
typename B, std::enable_if_t<
866 interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, A&&, B&&> or
867 interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, typename nested_object_of<A&&>::type, B&&>,
int> = 0>
872 if constexpr (interface::solve_defined_for<NestedObject, must_be_unique, must_be_exact, A&&, B&&>)
874 return NestedInterface::template solve<must_be_unique, must_be_exact>(std::forward<A>(a), std::forward<B>(b));
878 return internal::make_fixed_size_adapter<vector_space_descriptor_of_t<A, 1>, vector_space_descriptor_of_t<B, 1>>(
879 NestedInterface::template solve<must_be_unique, must_be_exact>(nested_object(std::forward<A>(a)), std::forward<B>(b)));
884 #ifdef __cpp_concepts 885 template<
typename A> requires
886 interface::LQ_decomposition_defined_for<NestedObject, A&&> or
887 interface::LQ_decomposition_defined_for<NestedObject, nested_object_of_t<A&&>>
889 template<
typename A, std::enable_if_t<
890 interface::LQ_decomposition_defined_for<NestedObject, A&&> or
891 interface::LQ_decomposition_defined_for<NestedObject, typename nested_object_of<A&&>::type>,
int> = 0>
896 if constexpr (interface::LQ_decomposition_defined_for<NestedObject, A&&>)
903 using D0 = vector_space_descriptor_of<A, 0>;
904 return internal::make_fixed_square_adapter_like<D0>(std::forward<decltype(ret)>(ret));
909 #ifdef __cpp_concepts 910 template<
typename A> requires
911 interface::QR_decomposition_defined_for<NestedObject, A&&> or
912 interface::QR_decomposition_defined_for<NestedObject, nested_object_of_t<A&&>>
914 template<
typename A, std::enable_if_t<
915 interface::QR_decomposition_defined_for<NestedObject, A&&> or
916 interface::QR_decomposition_defined_for<NestedObject, typename nested_object_of<A&&>::type>,
int> = 0>
921 if constexpr (interface::QR_decomposition_defined_for<NestedObject, A&&>)
928 using D1 = vector_space_descriptor_of<A, 1>;
929 return internal::make_fixed_square_adapter_like<D1>(std::forward<decltype(ret)>(ret));
constexpr bool fixed_pattern
A patterns::pattern for which the dimension is fixed at compile time.
Definition: fixed_pattern.hpp:32
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) 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
triangle_type
The type of a triangular matrix.
Definition: enumerations.hpp:26
constexpr bool diagonal_matrix
Specifies that a type is a diagonal matrix or tensor.
Definition: diagonal_matrix.hpp:32
decltype(auto) constexpr conjugate(Arg &&arg)
Take the complex conjugate of an indexible object.
Definition: conjugate.hpp:44
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:103
constexpr auto count_indices(const T &)
Get the number of indices necessary to address all the components of an indexible object...
Definition: count_indices.hpp:51
constexpr bool pattern
An object describing the characteristics (e.g., dimensions, wrapping structure) of an index...
Definition: pattern.hpp:31
constexpr bool indexible
T is a multidimensional array type.
Definition: indexible.hpp:32
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
The size of a sized object (including a collection).
Definition: size_of.hpp:33
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
A structure representing the dimensions associated with of a particular index.
Definition: Dimensions.hpp:42
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
constexpr detail::to_diagonal_adapter to_diagonal
A RangeAdapterObject that converts one pattern_collection to another that is equivalent to duplicatin...
Definition: to_diagonal.hpp:81
constexpr bool hermitian_matrix
Specifies that a type is a hermitian matrix.
Definition: hermitian_matrix.hpp:59
static const bool is_specialized
Identifies types for which object_traits is specialized.
Definition: object_traits.hpp:44
constexpr auto make_identity_matrix(P &&p)
Make an identity_matrix with a given shape pattern.
Definition: make_identity_matrix.hpp:37
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
Definition: object_traits.hpp:38
decltype(auto) constexpr transpose(Arg &&arg)
Swap any two indices of an indexible_object.
Definition: transpose.hpp:49
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
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 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
Definition: FixedSizeAdapter.hpp:30
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
constexpr auto make_constant(C c, P &&p)
Make an indexible object in which every element is a constant value.
Definition: make_constant.hpp:41
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:67
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
The triangle_type associated with an indexible object.
Definition: triangle_type_of.hpp:66
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
decltype(auto) constexpr 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
constexpr detail::diagonal_of_adapter diagonal_of
A RangeAdapterObject that converts one pattern_collection to another corresponding to the diagonal_ma...
Definition: diagonal_of.hpp:153
Definition: trait_backports.hpp:64
typename collection_element< i, T >::type collection_element_t
Helper template for collection_element.
Definition: collection_element.hpp:116
constexpr bool index
T is an index value.
Definition: index.hpp:62
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
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:292
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