Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
dense_host_vector.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <cmath>
8#include <complex>
9#include <cstddef>
10#include <span>
11#include <stdexcept>
12#include <utility>
13#include <vector>
14
15namespace uni20::krylov
16{
17
19template <typename Scalar> struct DenseHostVector
20{
21 std::vector<Scalar> values;
22};
23
28{
29 template <RealOrComplex To, RealOrComplex From>
30 requires(Complex<To> == Complex<From>)
31 void operator()(DenseHostVector<To>& output, DenseHostVector<From> const& input, Precision p) const
32 {
33 require_precision<To>(p);
34 (void)p.bit_count();
35 if (output.values.size() != input.values.size())
36 throw std::invalid_argument("Krylov transfer requires matching vector dimensions");
37 for (std::size_t i = 0; i < input.values.size(); ++i)
38 output.values[i] = gmres_detail::convert_scalar<To>(input.values[i], p);
39 }
40};
41
43template <typename Scalar> class DenseHostVectorAlgebra {
44 public:
45 explicit DenseHostVectorAlgebra(std::size_t dimension) : dimension_(dimension) {}
46
47 [[nodiscard]] std::size_t dimension() const noexcept { return dimension_; }
48 [[nodiscard]] std::size_t problem_dimension() const noexcept { return dimension_; }
49 [[nodiscard]] std::size_t vector_dimension(DenseHostVector<Scalar> const& x) const noexcept
50 {
51 return x.values.size();
52 }
53
55 [[nodiscard]] auto prototype_view(DenseHostVector<Scalar> const& x) const -> std::span<Scalar const>
56 {
57 return x.values;
58 }
59 auto prototype_view(DenseHostVector<Scalar> const&&) const = delete;
60
62 template <class Element, std::size_t Extent>
63 requires std::same_as<std::remove_const_t<Element>, Scalar>
64 [[nodiscard]] auto prototype_view(std::span<Element, Extent> x) const -> std::span<Scalar const>
65 {
66 return x;
67 }
68
69 [[nodiscard]] std::size_t vector_dimension(std::span<Scalar const> x) const noexcept { return x.size(); }
70
71 [[nodiscard]] int allocation_count() const noexcept { return allocation_count_; }
72 [[nodiscard]] int copy_count() const noexcept { return copy_count_; }
73 [[nodiscard]] int axpy_count() const noexcept { return axpy_count_; }
74 [[nodiscard]] int scal_count() const noexcept { return scal_count_; }
75 [[nodiscard]] int set_zero_count() const noexcept { return set_zero_count_; }
76 [[nodiscard]] int inner_product_count() const noexcept { return inner_product_count_; }
77 [[nodiscard]] int norm_count() const noexcept { return norm_count_; }
78
80 {
81 return this->allocate_like(this->prototype_view(x));
82 }
83
85 [[nodiscard]] DenseHostVector<Scalar> allocate_like(std::span<Scalar const> x)
86 {
87 ++allocation_count_;
88 return DenseHostVector<Scalar>{std::vector<Scalar>(x.size())};
89 }
90
92 {
93 require_same_size(dst, src);
94 ++copy_count_;
95 dst.values = src.values;
96 }
97
99 {
100 require_same_size(y, x);
101 ++axpy_count_;
102 for (std::size_t i = 0; i < y.values.size(); ++i)
103 {
104 y.values[i] += alpha * x.values[i];
105 }
106 }
107
109 {
110 ++scal_count_;
111 for (auto& value : x.values)
112 {
113 value *= alpha;
114 }
115 }
116
118 {
119 ++set_zero_count_;
120 for (auto& value : x.values)
121 {
122 value = Scalar{};
123 }
124 }
125
127 {
128 require_same_size(x, y);
129 ++inner_product_count_;
130
131 auto x_span = make_span(x);
132 auto y_span = make_span(y);
134 }
135
137 {
138 ++norm_count_;
139
140 auto x_span = make_span(x);
142 }
143
144 private:
145 static void require_same_size(DenseHostVector<Scalar> const& lhs, DenseHostVector<Scalar> const& rhs)
146 {
147 if (lhs.values.size() != rhs.values.size())
148 {
149 throw std::invalid_argument("dense Krylov vectors have different sizes");
150 }
151 }
152
153 [[nodiscard]] static auto make_span(DenseHostVector<Scalar> const& vector)
154 {
155 using extents_type = stdex::dextents<uni20::index_type, 1>;
156 return stdex::mdspan<Scalar const, extents_type>(
157 vector.values.data(), extents_type{static_cast<uni20::index_type>(vector.values.size())});
158 }
159
160 std::size_t dimension_ = 0;
161 int allocation_count_ = 0;
162 int copy_count_ = 0;
163 int axpy_count_ = 0;
164 int scal_count_ = 0;
165 int set_zero_count_ = 0;
166 int inner_product_count_ = 0;
167 int norm_count_ = 0;
168};
169
171template <typename Scalar> class DenseHostVectorOps : public DenseHostVectorAlgebra<Scalar> {
172 public:
173 DenseHostVectorOps(std::size_t dimension, std::vector<Scalar> matrix)
174 : DenseHostVectorAlgebra<Scalar>(dimension), matrix_(std::move(matrix))
175 {
176 if (matrix_.size() != dimension * dimension)
177 throw std::invalid_argument("dense Krylov operator matrix has the wrong size");
178 }
179
180 [[nodiscard]] int matvec_count() const noexcept { return matvec_count_; }
181
183 {
184 if (x.values.size() != this->problem_dimension() || y.values.size() != this->problem_dimension())
185 {
186 throw std::invalid_argument("dense Krylov matvec vector has the wrong size");
187 }
188
189 ++matvec_count_;
190 for (std::size_t row = 0; row < this->problem_dimension(); ++row)
191 {
192 Scalar value{};
193 for (std::size_t col = 0; col < this->problem_dimension(); ++col)
194 {
195 value += matrix_[row * this->problem_dimension() + col] * x.values[col];
196 }
197 y.values[row] = value;
198 }
199 }
200
201 private:
202 std::vector<Scalar> matrix_;
203 int matvec_count_ = 0;
204};
205
206static_assert(KrylovMatrixFreeOperator<DenseHostVectorOps<float>, DenseHostVector<float>, float>);
207static_assert(KrylovMatrixFreeOperator<DenseHostVectorOps<double>, DenseHostVector<double>, double>);
208static_assert(KrylovMatrixFreeOperator<DenseHostVectorOps<uni20::complex<float>>,
209 DenseHostVector<uni20::complex<float>>, uni20::complex<float>>);
210static_assert(KrylovMatrixFreeOperator<DenseHostVectorOps<uni20::complex<double>>,
211 DenseHostVector<uni20::complex<double>>, uni20::complex<double>>);
212
213} // namespace uni20::krylov
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
Dense host vector algebra without an assembled operator.
Definition dense_host_vector.hpp:43
void scal(DenseHostVector< Scalar > &x, Scalar alpha)
Definition dense_host_vector.hpp:108
int set_zero_count() const noexcept
Definition dense_host_vector.hpp:75
uni20::make_real_t< Scalar > norm(DenseHostVector< Scalar > const &x)
Definition dense_host_vector.hpp:136
auto prototype_view(DenseHostVector< Scalar > const &&) const =delete
auto prototype_view(std::span< Element, Extent > x) const -> std::span< Scalar const >
Copy a borrowed span descriptor, including a temporary span.
Definition dense_host_vector.hpp:64
int axpy_count() const noexcept
Definition dense_host_vector.hpp:73
int inner_product_count() const noexcept
Definition dense_host_vector.hpp:76
DenseHostVector< Scalar > allocate_like(std::span< Scalar const > x)
Allocate independent owning storage from a retained span's extent.
Definition dense_host_vector.hpp:85
Scalar inner_product(DenseHostVector< Scalar > const &x, DenseHostVector< Scalar > const &y)
Definition dense_host_vector.hpp:126
int copy_count() const noexcept
Definition dense_host_vector.hpp:72
int allocation_count() const noexcept
Definition dense_host_vector.hpp:71
int scal_count() const noexcept
Definition dense_host_vector.hpp:74
void set_zero(DenseHostVector< Scalar > &x)
Definition dense_host_vector.hpp:117
std::size_t vector_dimension(std::span< Scalar const > x) const noexcept
Definition dense_host_vector.hpp:69
std::size_t problem_dimension() const noexcept
Definition dense_host_vector.hpp:48
std::size_t dimension() const noexcept
Definition dense_host_vector.hpp:47
int norm_count() const noexcept
Definition dense_host_vector.hpp:77
std::size_t vector_dimension(DenseHostVector< Scalar > const &x) const noexcept
Definition dense_host_vector.hpp:49
void axpy(DenseHostVector< Scalar > &y, Scalar alpha, DenseHostVector< Scalar > const &x)
Definition dense_host_vector.hpp:98
auto prototype_view(DenseHostVector< Scalar > const &x) const -> std::span< Scalar const >
Retain a read-only allocation descriptor without copying vector elements.
Definition dense_host_vector.hpp:55
DenseHostVectorAlgebra(std::size_t dimension)
Definition dense_host_vector.hpp:45
void copy(DenseHostVector< Scalar > &dst, DenseHostVector< Scalar > const &src)
Definition dense_host_vector.hpp:91
DenseHostVector< Scalar > allocate_like(DenseHostVector< Scalar > const &x)
Definition dense_host_vector.hpp:79
Dense reference operator combined with host vector algebra for prototypes.
Definition dense_host_vector.hpp:171
void matvec(DenseHostVector< Scalar > &y, DenseHostVector< Scalar > const &x)
Definition dense_host_vector.hpp:182
DenseHostVectorOps(std::size_t dimension, std::vector< Scalar > matrix)
Definition dense_host_vector.hpp:173
int matvec_count() const noexcept
Definition dense_host_vector.hpp:180
Concept for complex scalar types.
Definition scalar_concepts.hpp:75
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
locale_t value
Definition data_table.cpp:49
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
Definition qnum.hpp:403
Definition block_tensor_vector.hpp:23
Definition data_table.cpp:8
auto inner_product_host(BackendSelector selector, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs)
Return a nonblocking async host C++ scalar inner product through an explicit selector.
Definition linalg/async/reductions.hpp:496
auto norm_host(BackendSelector selector, async::Async< InputTensor > const &input)
Return a nonblocking async host C++ scalar norm through an explicit selector.
Definition linalg/async/reductions.hpp:554
Explicit precision conversion between dense prototype vector spaces.
Definition dense_host_vector.hpp:28
Prototype host vector used by matrix-free Krylov tests and adapters.
Definition dense_host_vector.hpp:20
std::vector< Scalar > values
Definition dense_host_vector.hpp:21
Backend value for the reference host CPU dense linalg oracle.
Definition backend_selector.hpp:55
Tensor sums, inner products, and Euclidean norms with explicit result residency.