Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
backends/cpu/matrix_exponential.hpp
Go to the documentation of this file.
1
7#pragma once
8
9#include <uni20/config.hpp>
10
11#if UNI20_HAS_FLOAT128 && UNI20_FLOAT128_PROVIDER_MPLAPACK
12#include <mplapack_config.h>
13#endif
14
23
24#include <complex>
25#include <concepts>
26#include <type_traits>
27
29{
30
39template <uni20::RealOrComplex Scalar>
41
49template <uni20::RealOrComplex Scalar>
52
53} // namespace uni20::linalg::backends::cpu
54
55namespace uni20::linalg
56{
57namespace detail::cpu_reference
58{
59
61template <uni20::MutableRankedMdspanLike<2> OutputMdspan, uni20::RankedMdspanLike<2> InputMdspan, class TimeScalar>
62consteval auto matrix_exponential_acceptance()
63{
64 using input_scalar = std::remove_cv_t<typename InputMdspan::element_type>;
65 using input_matrix = uni20::DenseMatrix<input_scalar>;
66
67 if constexpr (requires(input_matrix const& input, TimeScalar time) {
69 })
70 {
71 using result_matrix =
72 decltype(backends::cpu::matrix_exponential(std::declval<input_matrix const&>(), std::declval<TimeScalar>()));
73 if constexpr (requires(result_matrix& result, OutputMdspan& output, InputMdspan& input,
74 typename OutputMdspan::index_type output_index,
75 typename InputMdspan::index_type input_index) {
76 output.operator[](output_index, output_index) = result[std::size_t{}, std::size_t{}];
77 static_cast<input_scalar>(input.operator[](input_index, input_index));
78 })
79 {
80 return kernel_types_yes;
81 }
82 else
83 {
84 return kernel_types_no;
85 }
86 }
87 else
88 {
89 return kernel_types_no;
90 }
91}
92
94template <class OutputMdspan, class InputMdspan, class TimeScalar>
95KernelAttempt matrix_exponential(OutputMdspan& output, InputMdspan& input, TimeScalar time)
96{
97 using input_type = std::remove_cvref_t<InputMdspan>;
98 using input_scalar = std::remove_cv_t<typename input_type::element_type>;
99 using input_index_type = typename input_type::index_type;
100 using output_index_type = typename std::remove_cvref_t<OutputMdspan>::index_type;
101
102 CHECK_EQUAL(input.extent(0), input.extent(1));
103 CHECK_EQUAL(output.extent(0), input.extent(0));
104 CHECK_EQUAL(output.extent(1), input.extent(1));
105
106 std::size_t const rows = static_cast<std::size_t>(input.extent(0));
107 std::size_t const cols = static_cast<std::size_t>(input.extent(1));
109 for (input_index_type row = 0; row < input.extent(0); ++row)
110 {
111 for (input_index_type col = 0; col < input.extent(1); ++col)
112 {
113 materialized[static_cast<std::size_t>(row), static_cast<std::size_t>(col)] =
114 static_cast<input_scalar>(input[row, col]);
115 }
116 }
117
118 auto result = backends::cpu::matrix_exponential(materialized, time);
119 for (output_index_type row = 0; row < output.extent(0); ++row)
120 {
121 for (output_index_type col = 0; col < output.extent(1); ++col)
122 {
123 output[row, col] = result[static_cast<std::size_t>(row), static_cast<std::size_t>(col)];
124 }
125 }
127}
128} // namespace detail::cpu_reference
129
131template <uni20::MutableRankedMdspecLike<2> OutputMdspan, uni20::RankedMdspecLike<2> InputMdspan, class TimeScalar>
133consteval auto kernel_accepts_types(CpuReferenceBackend const&, matrix_exponential_op const&, OutputMdspan&,
134 InputMdspan&, TimeScalar const&)
135{
138 constexpr auto acceptance =
139 detail::cpu_reference::matrix_exponential_acceptance<output_span, input_span, TimeScalar>();
140 if constexpr (acceptance == KernelTypeAcceptance::yes)
141 return kernel_types_yes;
142 else
143 return kernel_types_no;
144}
145
147template <uni20::MutableRankedMdspecLike<2> OutputMdspan, uni20::RankedMdspecLike<2> InputMdspan, class TimeScalar>
149KernelAttempt try_kernel(CpuReferenceBackend, matrix_exponential_op const&, OutputMdspan& output, InputMdspan& input,
150 TimeScalar time)
151{
152 auto output_access = acquire_host_write_access_sync(output);
153 auto input_access = acquire_host_read_access_sync(input);
154 auto output_span = output_access.mdspan();
155 auto input_span = input_access.mdspan();
156 return detail::cpu_reference::matrix_exponential(output_span, input_span, time);
157}
158
159} // namespace uni20::linalg
RAII leases that resolve device descriptors and tensor views to mdspans.
General-purpose owning tensor with immediate or deferred mdspan metadata.
Definition basic_tensor.hpp:109
Mdspec metadata supporting host read acquisition.
Definition access.hpp:688
Mutable mdspec metadata supporting host write acquisition.
Definition access.hpp:694
Operation-tag backend dispatch over tensor-view operands.
typename detail::complex_type< Real >::type complex
Project-level complex scalar spelling.
Definition types.hpp:66
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
Mdspan concept and accessor extensions for Uni20.
int rows(std::FILE *stream)
Return the terminal row count associated with a C stream.
Definition terminal.cpp:482
Definition compensated_sum.hpp:10
uni20::DenseMatrix< Scalar > matrix_exponential(uni20::DenseMatrix< Scalar > const &matrix, uni20::make_real_t< Scalar > t)
Compute the matrix exponential using the adaptive scaling-and-squaring algorithm.
Definition matrix_exponential.cpp:562
Definition linalg/async.hpp:28
KernelAttempt try_kernel(BlasBackend, gemm_op const &, C &c, S const &alpha, A &a, B &b, S const &beta)
Pack logical host values and execute GEMM through value-preserving provider conversion.
Definition linalg/backends/blas/binary80.hpp:30
KernelAttempt
Result of one runtime kernel backend attempt.
Definition kernel_attempt.hpp:27
constexpr KernelAcceptance< KernelTypeAcceptance::no > kernel_types_no
Report that a backend rejects the argument types.
Definition dispatch_error.hpp:34
consteval auto kernel_accepts_types(BlasBackend, gemm_op const &, C &, S const &, A &, B &, S const &)
Accept host-readable native binary80 operands, including transforming accessors.
Definition linalg/backends/blas/binary80.hpp:19
void matrix_exponential(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input, TimeScalar &&time)
Schedule fixed-output matrix exponentiation through an explicit selector.
Definition async/matrix_exponential.hpp:64
constexpr KernelAcceptance< KernelTypeAcceptance::yes > kernel_types_yes
Report that a backend accepts every instance of the argument types.
Definition dispatch_error.hpp:40
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
std::remove_cvref_t< decltype(std::declval< detail::host_read_mdspan_lease_t< Mdspec > & >().mdspan())> host_read_mdspan_t
Read-only mdspan type resolved by host descriptor acquisition.
Definition access.hpp:679
auto acquire_host_read_access_sync(Mdspan const &mdspan)
Acquire a directly host-accessible read-only mdspan.
Definition access.hpp:616
std::remove_cvref_t< decltype(std::declval< detail::host_write_mdspan_lease_t< Mdspec > & >().mdspan())> host_write_mdspan_t
Writable mdspan type resolved by host descriptor acquisition.
Definition access.hpp:684
auto acquire_host_write_access_sync(Mdspan &mdspan)
Acquire a directly host-accessible writable mdspan.
Definition access.hpp:626
Backend-independent operation values used with normalized kernel operands.
Backend value for the reference host CPU dense linalg oracle.
Definition backend_selector.hpp:55
Dense matrix exponential operation tag.
Definition operation_tags.hpp:202
Concepts for tensor-level objects that resolve mdspan kernel operands.
General-purpose owning tensors with runtime extents.
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309