16 #ifndef OPENKALMAN_ADAPTERS_INTERFACE_HPP 17 #define OPENKALMAN_ADAPTERS_INTERFACE_HPP 26 template<
typename T> requires OpenKalman::internal::diagonal_expr<T> or OpenKalman::internal::triangular_expr<T> or OpenKalman::internal::hermitian_expr<T>
27 struct library_interface<T>
30 struct
library_interface<T,
std::enable_if_t<OpenKalman::internal::diagonal_expr<T> or OpenKalman::internal::triangular_expr<T> or OpenKalman::internal::hermitian_expr<T>>>
36 using Nested = std::decay_t<nested_object_of_t<T>>;
41 template<
typename Derived>
42 using library_base = internal::library_base_t<Derived, Nested>;
45 #ifdef __cpp_lib_ranges 46 template<indexible Arg, std::ranges::input_range Indices> requires
47 std::convertible_to<std::ranges::range_value_t<Indices>,
const typename std::decay_t<Arg>::Index>
49 template<
typename Arg,
typename Indices>
51 static constexpr scalar_type_of_t<Arg>
52 get_component(Arg&& arg,
const Indices& indices)
54 using Scalar = scalar_type_of_t<Arg>;
55 auto it = stdex::ranges::begin(indices);
57 std::size_t j {++it == stdex::ranges::end(indices) ? 1 : *it};
59 if constexpr (OpenKalman::internal::diagonal_expr<Arg>)
62 return OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), indices);
64 return static_cast<Scalar
>(0);
66 else if constexpr (OpenKalman::internal::triangular_expr<Arg>)
68 if (triangular_matrix<Arg, triangle_type::lower> ? i >= j : j >= i)
69 return OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), indices);
71 return static_cast<Scalar
>(0);
75 static_assert(OpenKalman::internal::hermitian_expr<Arg>);
77 if constexpr (values::complex<Scalar>)
80 return values::real(OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), indices));
81 else if (hermitian_adapter<Arg, HermitianAdapterType::lower> ? i > j : j > i)
82 return OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), indices);
84 return values::conj(OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), j, i));
88 if (hermitian_adapter<Arg, HermitianAdapterType::lower> ? i >= j : j >= i)
89 return OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), indices);
91 return OpenKalman::get_component(OpenKalman::nested_object(std::forward<Arg>(arg)), j, i);
97 #ifdef __cpp_lib_ranges 98 template<indexible Arg, std::ranges::input_range Indices> requires (not std::is_const_v<Arg>) and
99 std::convertible_to<std::ranges::range_value_t<Indices>,
const typename Arg::Index>
101 template<
typename Arg,
typename Indices, std::enable_if_t<(not std::is_const_v<Arg>),
int> = 0>
104 set_component(Arg& arg,
const scalar_type_of_t<Arg>& s,
const Indices& indices)
106 using Scalar = scalar_type_of_t<Arg>;
107 auto it = stdex::ranges::begin(indices);
109 std::size_t j {++it == stdex::ranges::end(indices) ? 1 : *it};
111 if constexpr (OpenKalman::internal::diagonal_expr<Arg>)
114 OpenKalman::set_component(arg, s, indices);
116 if (s != static_cast<Scalar>(0))
throw std::out_of_range(
"Cannot set non-diagonal element of a diagonal matrix to a non-zero value.");
118 else if constexpr (OpenKalman::internal::triangular_expr<Arg>)
120 if (triangular_matrix<Arg, triangle_type::lower> ? i >= j : j >= i)
121 OpenKalman::set_component(arg, s, indices);
123 if (s != static_cast<Scalar>(0))
throw std::out_of_range(
"Cannot set elements of a triangular matrix to non-zero values outside the triangle.");
127 static_assert(OpenKalman::internal::hermitian_expr<Arg>);
129 if (hermitian_adapter<Arg, HermitianAdapterType::lower> ? i >= j : j >= i)
130 OpenKalman::set_component(arg, s, indices);
152 template<
typename Arg,
typename...Begin,
typename...Size>
154 get_slice(Arg&& arg, std::tuple<Begin...> begin, std::tuple<Size...>
size)
156 auto dense = to_dense_object<scalar_type_of_t<Arg>>(std::forward<Arg>(arg));
157 static_assert(not OpenKalman::internal::diagonal_expr<decltype(dense)> and not OpenKalman::internal::triangular_expr<decltype(dense)> and
158 not OpenKalman::internal::hermitian_expr<decltype(dense)>);
163 template<
typename Arg,
typename Block,
typename...Begin>
164 static constexpr Arg&
165 set_slice(Arg& arg, Block&& block, Begin...begin) =
delete;
171 template<
typename Arg>
172 static decltype(
auto)
180 template<
typename Arg>
181 static decltype(
auto)
185 if constexpr (OpenKalman::internal::diagonal_expr<Arg>)
return nested_object(std::forward<Arg>(arg));
193 template<
typename...Ds,
typename Operation,
typename...Args>
194 static constexpr decltype(
auto)
195 n_ary_operation(
const std::tuple<Ds...>& tup, Operation&& op, Args&&...args)
202 template<std::size_t...indices,
typename BinaryFunction,
typename Arg>
203 static constexpr decltype(
auto)
204 reduce(BinaryFunction&& b, Arg&& arg)
207 return Traits::template
reduce<indices...>(std::forward<BinaryFunction>(b), std::forward<Arg>(arg));
216 template<
typename Arg>
217 static constexpr decltype(
auto)
220 if constexpr (OpenKalman::internal::hermitian_expr<Arg>)
222 constexpr
auto t = hermitian_adapter_type_of_v<Arg>;
227 static_assert(OpenKalman::internal::triangular_expr<Arg>);
228 constexpr
auto t = triangle_type_of_v<Arg>;
235 template<
typename Arg>
236 static constexpr decltype(
auto)
239 if constexpr (OpenKalman::internal::hermitian_expr<Arg>)
253 static_assert(OpenKalman::internal::triangular_expr<Arg>);
268 template<
typename Arg>
269 static constexpr decltype(
auto)
273 static_assert(OpenKalman::internal::triangular_expr<Arg>);
280 template<
typename Arg>
281 static constexpr
auto 285 static_assert(OpenKalman::internal::hermitian_expr<Arg>);
290 template<
typename Arg,
typename...Args>
291 static constexpr
auto 292 sum(Arg&& arg, Args&&...args)
298 template<
typename A,
typename B>
299 static constexpr
auto 309 template<triangle_type tri,
typename A>
310 static constexpr
auto 313 static_assert(not OpenKalman::internal::diagonal_expr<A>);
315 if constexpr (OpenKalman::internal::hermitian_expr<A>)
318 if constexpr (hermitian_adapter<A, h>)
319 return cholesky_factor<tri>(nested_object(std::forward<A>(a)));
325 static_assert(OpenKalman::internal::triangular_expr<A>);
326 if constexpr (triangular_matrix<A, tri>)
327 return OpenKalman::cholesky_factor<tri>(nested_object(std::forward<A>(a)));
334 template<HermitianAdapterType significant_triangle,
typename A,
typename U,
typename Alpha>
335 static decltype(
auto)
338 auto&& n = nested_object(std::forward<A>(a));
340 if constexpr (OpenKalman::internal::hermitian_expr<A>)
342 auto&& m = Trait::template rank_update_hermitian<significant_triangle>(std::forward<decltype(n)>(n), std::forward<U>(u), alpha);
343 return make_hermitian_matrix<significant_triangle>(std::forward<decltype(m)>(m));
347 static_assert(OpenKalman::internal::diagonal_expr<A>);
348 return Trait::template rank_update_hermitian<significant_triangle>(to_native_matrix(std::forward<A>(a)), std::forward<U>(u), alpha);
353 template<triangle_type triangle,
typename A,
typename U,
typename Alpha>
354 static decltype(
auto)
357 static_assert(OpenKalman::internal::diagonal_expr<A>);
358 using N = std::decay_t<nested_object_of_t<T>>;
363 template<
bool must_be_unique,
bool must_be_exact,
typename A,
typename B>
364 static constexpr decltype(
auto)
367 using N = std::decay_t<nested_object_of_t<T>>;
373 static constexpr decltype(
auto)
376 using N = std::decay_t<nested_object_of_t<T>>;
382 static constexpr decltype(
auto)
385 using N = std::decay_t<nested_object_of_t<T>>;
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
A lower-left triangular matrix.
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
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
decltype(auto) constexpr to_dense_object(Arg &&arg)
Convert the argument to a dense, writable matrix of a particular scalar type.
Definition: to_dense_object.hpp:37
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
constexpr bool triangular_matrix
Specifies that an argument is an indexible object having a given triangle_type (e.g., upper, lower, or diagonal).
Definition: triangular_matrix.hpp:36
constexpr bool hermitian_matrix
Specifies that a type is a hermitian matrix.
Definition: hermitian_matrix.hpp:59
An adapter for creating a diagonal matrix or tensor.
Definition: diagonal_adapter.hpp:27
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
decltype(auto) constexpr transpose(Arg &&arg)
Swap any two indices of an indexible_object.
Definition: transpose.hpp:49
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
constexpr bool size
T is either an index representing a size, or unbounded_size_t, which indicates that the size is unbou...
Definition: size.hpp:71
constexpr auto real(const Arg &arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
An upper-right triangular matrix.
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
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 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