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 LibraryBase = 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>
55 #ifdef __cpp_lib_ranges 56 namespace ranges = std::ranges;
58 auto it = ranges::begin(indices);
60 std::size_t j {++it == ranges::end(indices) ? 1 : *it};
62 if constexpr (OpenKalman::internal::diagonal_expr<Arg>)
67 return static_cast<Scalar
>(0);
69 else if constexpr (OpenKalman::internal::triangular_expr<Arg>)
71 if (triangular_matrix<Arg, TriangleType::lower> ? i >= j : j >= i)
74 return static_cast<Scalar
>(0);
78 static_assert(OpenKalman::internal::hermitian_expr<Arg>);
80 if constexpr (values::complex<Scalar>)
84 else if (hermitian_adapter<Arg, HermitianAdapterType::lower> ? i > j : j > i)
91 if (hermitian_adapter<Arg, HermitianAdapterType::lower> ? i >= j : j >= i)
100 #ifdef __cpp_lib_ranges 101 template<indexible Arg, std::ranges::input_range Indices> requires (not std::is_const_v<Arg>) and
102 std::convertible_to<std::ranges::range_value_t<Indices>,
const typename Arg::Index>
104 template<
typename Arg,
typename Indices, std::enable_if_t<(not std::is_const_v<Arg>),
int> = 0>
110 #ifdef __cpp_lib_ranges 111 namespace ranges = std::ranges;
113 auto it = ranges::begin(indices);
115 std::size_t j {++it == ranges::end(indices) ? 1 : *it};
117 if constexpr (OpenKalman::internal::diagonal_expr<Arg>)
122 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.");
124 else if constexpr (OpenKalman::internal::triangular_expr<Arg>)
126 if (triangular_matrix<Arg, TriangleType::lower> ? i >= j : j >= i)
129 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.");
133 static_assert(OpenKalman::internal::hermitian_expr<Arg>);
135 if (hermitian_adapter<Arg, HermitianAdapterType::lower> ? i >= j : j >= i)
158 template<
typename Arg,
typename...Begin,
typename...Size>
160 get_slice(Arg&& arg, std::tuple<Begin...> begin, std::tuple<Size...>
size)
162 auto dense = to_dense_object<scalar_type_of_t<Arg>>(std::forward<Arg>(arg));
163 static_assert(not OpenKalman::internal::diagonal_expr<decltype(dense)> and not OpenKalman::internal::triangular_expr<decltype(dense)> and
164 not OpenKalman::internal::hermitian_expr<decltype(dense)>);
169 template<
typename Arg,
typename Block,
typename...Begin>
170 static constexpr Arg&
171 set_slice(Arg& arg, Block&& block, Begin...begin) =
delete;
177 template<
typename Arg>
178 static decltype(
auto)
186 template<
typename Arg>
187 static decltype(
auto)
191 if constexpr (OpenKalman::internal::diagonal_expr<Arg>)
return nested_object(std::forward<Arg>(arg));
199 template<
typename...Ds,
typename Operation,
typename...Args>
200 static constexpr decltype(
auto)
201 n_ary_operation(
const std::tuple<Ds...>& tup, Operation&& op, Args&&...args)
208 template<std::size_t...indices,
typename BinaryFunction,
typename Arg>
209 static constexpr decltype(
auto)
210 reduce(BinaryFunction&& b, Arg&& arg)
213 return Traits::template
reduce<indices...>(std::forward<BinaryFunction>(b), std::forward<Arg>(arg));
222 template<
typename Arg>
223 static constexpr decltype(
auto)
226 if constexpr (OpenKalman::internal::hermitian_expr<Arg>)
228 constexpr
auto t = hermitian_adapter_type_of_v<Arg>;
233 static_assert(OpenKalman::internal::triangular_expr<Arg>);
234 constexpr
auto t = triangle_type_of_v<Arg>;
241 template<
typename Arg>
242 static constexpr decltype(
auto)
245 if constexpr (OpenKalman::internal::hermitian_expr<Arg>)
259 static_assert(OpenKalman::internal::triangular_expr<Arg>);
274 template<
typename Arg>
275 static constexpr decltype(
auto)
279 static_assert(OpenKalman::internal::triangular_expr<Arg>);
286 template<
typename Arg>
287 static constexpr
auto 291 static_assert(OpenKalman::internal::hermitian_expr<Arg>);
296 template<
typename Arg,
typename...Args>
297 static constexpr
auto 298 sum(Arg&& arg, Args&&...args)
304 template<
typename A,
typename B>
305 static constexpr
auto 315 template<TriangleType triangle_type,
typename A>
316 static constexpr
auto 319 static_assert(not OpenKalman::internal::diagonal_expr<A>);
321 if constexpr (OpenKalman::internal::hermitian_expr<A>)
324 if constexpr (hermitian_adapter<A, h>)
325 return cholesky_factor<triangle_type>(
nested_object(std::forward<A>(a)));
331 static_assert(OpenKalman::internal::triangular_expr<A>);
332 if constexpr (triangular_matrix<A, triangle_type>)
333 return OpenKalman::cholesky_factor<triangle_type>(
nested_object(std::forward<A>(a)));
340 template<HermitianAdapterType significant_triangle,
typename A,
typename U,
typename Alpha>
341 static decltype(
auto)
346 if constexpr (OpenKalman::internal::hermitian_expr<A>)
348 auto&& m = Trait::template rank_update_hermitian<significant_triangle>(std::forward<decltype(n)>(n), std::forward<U>(u), alpha);
349 return make_hermitian_matrix<significant_triangle>(std::forward<decltype(m)>(m));
353 static_assert(OpenKalman::internal::diagonal_expr<A>);
354 return Trait::template rank_update_hermitian<significant_triangle>(
to_native_matrix(std::forward<A>(a)), std::forward<U>(u), alpha);
359 template<TriangleType triangle,
typename A,
typename U,
typename Alpha>
360 static decltype(
auto)
363 static_assert(OpenKalman::internal::diagonal_expr<A>);
364 using N = std::decay_t<nested_object_of_t<T>>;
369 template<
bool must_be_unique,
bool must_be_exact,
typename A,
typename B>
370 static constexpr decltype(
auto)
373 using N = std::decay_t<nested_object_of_t<T>>;
379 static constexpr decltype(
auto)
382 using N = std::decay_t<nested_object_of_t<T>>;
388 static constexpr decltype(
auto)
391 using N = std::decay_t<nested_object_of_t<T>>;
401 #endif //OPENKALMAN_ADAPTERS_INTERFACE_HPP 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
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
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
decltype(auto) to_native_matrix(Arg &&arg)
If it isn'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
Definition: tuple_reverse.hpp:103
HermitianAdapterType
The type of a hermitian adapter, indicating which triangle of the nested matrix is used...
Definition: global-definitions.hpp:78
decltype(auto) constexpr to_diagonal(Arg &&arg)
Convert an indexible object into a diagonal matrix.
Definition: to_diagonal.hpp:32
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
An upper-right triangular matrix.
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 a type is a triangular matrix (upper, lower, or diagonal).
Definition: triangular_matrix.hpp:37
decltype(auto) constexpr transpose(Arg &&arg)
Take the transpose of a matrix.
Definition: transpose.hpp:58
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:37
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
constexpr auto real(Arg arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
decltype(auto) constexpr adjoint(Arg &&arg)
Take the adjoint of a matrix.
Definition: adjoint.hpp:33
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 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
An adapter for creating a diagonal matrix or tensor.
Definition: DiagonalAdapter.hpp:27
A lower-left triangular matrix.
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
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