Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
ops/lq.hpp
Go to the documentation of this file.
1#pragma once
2
18#include <uni20/tensor/copy.hpp>
21
22#include <algorithm>
23#include <concepts>
24#include <type_traits>
25#include <utility>
26
27namespace uni20::linalg
28{
29namespace detail
30{
31using lq_matrix_extents = stdex::dextents<uni20::index_type, 2>;
32
33template <class LTensor, class QTensor, class MatrixTensor>
34concept CompatibleLqTensors =
37 detail::DecompositionScalar<uni20::tensor_element_t<MatrixTensor>> &&
38 std::same_as<uni20::tensor_element_t<LTensor>, uni20::tensor_element_t<MatrixTensor>> &&
39 std::same_as<uni20::tensor_element_t<QTensor>, uni20::tensor_element_t<MatrixTensor>>;
40
41template <uni20::MutableRankedTensorView<2> LTensor, uni20::MutableRankedTensorView<2> QTensor,
42 uni20::MutableRankedTensorView<2> MatrixTensor>
43void prepare_lq(LTensor& l, QTensor& q, MatrixTensor const& matrix_work)
44{
45 auto const rows = static_cast<uni20::index_type>(matrix_work.extent(0));
46 auto const cols = static_cast<uni20::index_type>(matrix_work.extent(1));
47 auto const rank = std::min(rows, cols);
48 uni20::prepare_output(l, lq_matrix_extents{rows, rank});
49 uni20::prepare_output(q, lq_matrix_extents{rank, cols});
50}
51
52template <KernelBackendSelector BackendSelector, uni20::MutableRankedTensorView<2> LTensor,
53 uni20::MutableRankedTensorView<2> QTensor, uni20::MutableRankedTensorView<2> MatrixTensor>
54void dispatch_lq(BackendSelector&& selector, LTensor& l, QTensor& q, MatrixTensor& matrix_work, Precision p)
55{
56 auto l_descriptor = uni20::mdspec_of(l);
57 auto q_descriptor = uni20::mdspec_of(q);
58 auto matrix_descriptor = uni20::mdspec_of(matrix_work);
59 detail::dispatch_at_precision<uni20::tensor_element_t<MatrixTensor>>(
60 std::forward<BackendSelector>(selector), lq_op{}, p, l_descriptor, q_descriptor, matrix_descriptor);
61
62 uni20::detail::record_output_precision(l, p);
63 uni20::detail::record_output_precision(q, p);
64 uni20::detail::record_output_precision(matrix_work, p);
65}
66} // namespace detail
67
73template <KernelBackendSelector BackendSelector, class LTensor, class QTensor, class MatrixTensor>
74 requires detail::CompatibleLqTensors<LTensor, QTensor, MatrixTensor>
75void lq_factorization(BackendSelector&& selector, LTensor&& l, QTensor&& q, MatrixTensor&& matrix_work,
76 std::optional<Precision> requested = {})
77{
78 auto const p = detail::decomposition_precision(matrix_work, requested);
79 detail::prepare_lq(l, q, matrix_work);
80 detail::dispatch_lq(std::forward<BackendSelector>(selector), l, q, matrix_work, p);
81}
82
84template <class LTensor, class QTensor, class MatrixTensor>
85 requires detail::CompatibleLqTensors<LTensor, QTensor, MatrixTensor>
86void lq_factorization(LTensor&& l, QTensor&& q, MatrixTensor&& matrix_work, std::optional<Precision> requested = {})
87{
88 auto const p = detail::decomposition_precision(matrix_work, requested);
89 detail::prepare_lq(l, q, matrix_work);
90 auto selector = select_backend(lq_op{}, l, q, matrix_work);
91 detail::dispatch_lq(selector, l, q, matrix_work, p);
92}
93
96template <class LTensor, class QTensor> struct LqResult
97{
98 using l_tensor_type = LTensor;
99 using q_tensor_type = QTensor;
100
101 LTensor l;
102 QTensor q;
103};
104
105namespace detail
106{
107template <class MatrixTensor> using lq_matrix_tensor_t = uni20::Tensor<uni20::tensor_element_t<MatrixTensor>, 2>;
108
109template <class MatrixTensor> consteval bool can_use_lq_storage_as_workspace()
110{
111 return std::same_as<std::remove_cvref_t<MatrixTensor>, lq_matrix_tensor_t<MatrixTensor>>;
112}
113
114template <KernelBackendSelector BackendSelector, uni20::OwningTensor MatrixTensor>
116[[nodiscard]] auto lq_from_work_matrix(BackendSelector&& selector, MatrixTensor matrix_work, Precision p)
117{
118 lq_matrix_tensor_t<MatrixTensor> l;
119 lq_matrix_tensor_t<MatrixTensor> q;
120 lq_factorization(std::forward<BackendSelector>(selector), l, q, matrix_work, p);
121 return LqResult<decltype(l), decltype(q)>{.l = std::move(l), .q = std::move(q)};
122}
123
124template <class MatrixTensor> [[nodiscard]] constexpr auto select_lq_backend()
125{
126 return select_backend_for<lq_matrix_tensor_t<MatrixTensor>, lq_matrix_tensor_t<MatrixTensor>,
127 std::remove_cvref_t<MatrixTensor>>(lq_op{});
128}
129} // namespace detail
130
132template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> MatrixTensor>
133 requires detail::DecompositionScalar<uni20::tensor_element_t<MatrixTensor>>
134[[nodiscard]] auto lq(BackendSelector&& selector, MatrixTensor const& matrix, std::optional<Precision> requested = {})
135{
136 auto const p = detail::decomposition_precision(matrix, requested);
137 auto matrix_work = uni20::make_tensor<uni20::ColumnMajor>(matrix);
138 return detail::lq_from_work_matrix(std::forward<BackendSelector>(selector), std::move(matrix_work), p);
139}
140
142template <uni20::RankedTensorView<2> MatrixTensor>
143 requires detail::DecompositionScalar<uni20::tensor_element_t<MatrixTensor>>
144[[nodiscard]] auto lq(MatrixTensor const& matrix, std::optional<Precision> requested = {})
145{
146 auto const p = detail::decomposition_precision(matrix, requested);
147 auto matrix_work = uni20::make_tensor<uni20::ColumnMajor>(matrix);
148 auto selector = detail::select_lq_backend<decltype(matrix_work)>();
149 return detail::lq_from_work_matrix(std::move(selector), std::move(matrix_work), p);
150}
151
155template <KernelBackendSelector BackendSelector, class MatrixTensor>
157 detail::DecompositionScalar<uni20::tensor_element_t<MatrixTensor>> &&
158 (!std::is_lvalue_reference_v<MatrixTensor>) && (!std::is_const_v<std::remove_reference_t<MatrixTensor>>)
159[[nodiscard]] auto lq(BackendSelector&& selector, MatrixTensor&& matrix, std::optional<Precision> requested = {})
160{
161 auto const p = detail::decomposition_precision(matrix, requested);
162 if constexpr (detail::can_use_lq_storage_as_workspace<MatrixTensor>())
163 {
164 return detail::lq_from_work_matrix(std::forward<BackendSelector>(selector), std::forward<MatrixTensor>(matrix), p);
165 }
166 else
167 {
168 auto matrix_work = uni20::make_tensor<uni20::ColumnMajor>(matrix);
169 return detail::lq_from_work_matrix(std::forward<BackendSelector>(selector), std::move(matrix_work), p);
170 }
171}
172
174template <class MatrixTensor>
176 detail::DecompositionScalar<uni20::tensor_element_t<MatrixTensor>> &&
177 (!std::is_lvalue_reference_v<MatrixTensor>) && (!std::is_const_v<std::remove_reference_t<MatrixTensor>>)
178[[nodiscard]] auto lq(MatrixTensor&& matrix, std::optional<Precision> requested = {})
179{
180 auto const p = detail::decomposition_precision(matrix, requested);
181 using work_type = std::conditional_t<detail::can_use_lq_storage_as_workspace<MatrixTensor>(),
182 std::remove_cvref_t<MatrixTensor>, detail::lq_matrix_tensor_t<MatrixTensor>>;
183 auto selector = detail::select_lq_backend<work_type>();
184 return uni20::linalg::lq(std::move(selector), std::forward<MatrixTensor>(matrix), p);
185}
186
187} // namespace uni20::linalg
LAPACK backend for reduced dense real or complex LQ factorization.
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
General-purpose owning tensor with immediate or deferred mdspan metadata.
Definition basic_tensor.hpp:109
MutableImmediateTensorView whose writable mdspan has a specified static rank.
Definition tensor/concepts.hpp:209
MutableTensorView with a specified static rank.
Definition tensor/concepts.hpp:166
Tensor-level object that owns the storage described by its multidimensional view.
Definition tensor/concepts.hpp:116
Operation-tag backend dispatch over tensor-view operands.
int rows(std::FILE *stream)
Return the terminal row count associated with a C stream.
Definition terminal.cpp:482
Definition linalg/async.hpp:28
void lq_factorization(BackendSelector &&selector, LTensor &&l, QTensor &&q, MatrixTensor &&matrix_work, std::optional< Precision > requested={})
Compute reduced LQ in a destructive input workspace through an explicit selector.
Definition ops/lq.hpp:75
auto lq(BackendSelector selector, async::Async< MatrixTensor > const &matrix, std::optional< Precision > requested={})
Schedule a preserving reduced real or complex LQ factorization through an explicit selector.
Definition async/lq.hpp:109
constexpr auto select_backend(Operation const &operation, FirstTensor const &, RestTensors const &...)
Select the default backend list for an operation on Tensor operands.
Definition backend_selector.hpp:252
Definition data_table.cpp:8
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
constexpr decltype(auto) mdspec_of(Tensor &tensor) noexcept(noexcept(tensor.mdspec()))
Return a tensor's immediate or descriptor-backed multidimensional metadata.
Definition tensor/concepts.hpp:50
std::remove_cv_t< typename tensor_mdspec_t< T >::element_type > tensor_element_t
Scalar value type exposed by a tensor-level object.
Definition tensor/concepts.hpp:126
std::ptrdiff_t index_type
Definition types.hpp:19
Backend-independent operation values used with normalized kernel operands.
Owning reduced factors returned by lq.
Definition ops/lq.hpp:97
LTensor l
Definition ops/lq.hpp:101
LTensor l_tensor_type
Definition ops/lq.hpp:98
QTensor q_tensor_type
Definition ops/lq.hpp:99
QTensor q
Definition ops/lq.hpp:102
Concepts for tensor-level objects that resolve mdspan kernel operands.
Backend-dispatched tensor copies and inferred owning materialization.
Shape preparation contracts for tensor operation outputs.
General-purpose owning tensors with runtime extents.