tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
exposition.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2023 Tobias Hienzsch
3
4#ifndef TETL_LINALG_EXPOSITION_HPP
5#define TETL_LINALG_EXPOSITION_HPP
6
7#include <etl/_complex/complex.hpp>
8#include <etl/_concepts/same_as.hpp>
9#include <etl/_concepts/unsigned_integral.hpp>
10#include <etl/_math/abs.hpp>
11#include <etl/_mdspan/layout.hpp>
12#include <etl/_mdspan/layout_left.hpp>
13#include <etl/_mdspan/layout_right.hpp>
14#include <etl/_mdspan/mdspan.hpp>
15#include <etl/_numeric/abs.hpp>
16#include <etl/_type_traits/always_false.hpp>
17#include <etl/_type_traits/bool_constant.hpp>
18#include <etl/_type_traits/common_type.hpp>
19#include <etl/_type_traits/declval.hpp>
20#include <etl/_type_traits/is_arithmetic.hpp>
21#include <etl/_type_traits/is_same.hpp>
22#include <etl/_type_traits/remove_const.hpp>
23
24namespace etl::linalg::detail {
25
26template <typename... Ts>
27using common_index_type_t = common_type_t<typename Ts::index_type...>;
28
29namespace linalg_adl_checks {
30
31using etl::abs;
32using etl::conj;
33using etl::imag;
34using etl::real;
35
36template <typename T>
37auto abs(T const&) -> T = delete;
38template <typename T>
39auto conj(T const&) -> T = delete;
40template <typename T>
41auto real(T const&) -> T = delete;
42template <typename T>
43auto imag(T const&) -> T = delete;
44
45template <typename T>
46concept has_abs = requires { abs(declval<T>()); };
47
48template <typename T>
49concept has_conj = requires { conj(declval<T>()); };
50
51template <typename T>
52concept has_real = requires { real(declval<T>()); };
53
54template <typename T>
55concept has_imag = requires { imag(declval<T>()); };
56
57} // namespace linalg_adl_checks
58
59template <typename T>
60concept has_adl_abs = linalg_adl_checks::has_abs<T>;
61
62template <typename T>
63concept has_adl_conj = linalg_adl_checks::has_conj<T>;
64
65template <typename T>
66concept has_adl_real = linalg_adl_checks::has_real<T>;
67
68template <typename T>
69concept has_adl_imag = linalg_adl_checks::has_imag<T>;
70
71inline constexpr auto abs_if_needed = []<typename T>(T const& val) {
72 if constexpr (unsigned_integral<T>) {
73 return val;
74 } else if constexpr (is_arithmetic_v<T>) {
75 return etl::abs(val);
76 } else if constexpr (has_adl_abs<T>) {
77 return abs(val);
78 } else {
79 static_assert(always_false<T>);
80 }
81};
82
83inline constexpr auto conj_if_needed = []<typename T>(T const& val) {
84 if constexpr (not is_arithmetic_v<T> and has_adl_conj<T>) {
85 return conj(val);
86 } else {
87 return val;
88 }
89};
90
91inline constexpr auto real_if_needed = []<typename T>(T const& val) {
92 if constexpr (not is_arithmetic_v<T> and has_adl_real<T>) {
93 return real(val);
94 } else {
95 return val;
96 }
97};
98
99inline constexpr auto imag_if_needed = []<typename T>(T const& val) {
100 if constexpr (not is_arithmetic_v<T> and has_adl_imag<T>) {
101 return imag(val);
102 } else {
103 return T{};
104 }
105};
106
107} // namespace etl::linalg::detail
108
109namespace etl::linalg {
110
111/// \ingroup linalg
112template <typename T>
113concept in_vector = is_mdspan_v<T> and T::rank() == 1;
114
115/// \ingroup linalg
116template <typename T>
117concept out_vector = is_mdspan_v<T>
118 and T::rank() == 1
119 and same_as<remove_const_t<typename T::element_type>, typename T::element_type>
120 and T::is_always_unique();
121
122/// \ingroup linalg
123template <typename T>
124concept inout_vector = is_mdspan_v<T>
125 and T::rank() == 1
126 and same_as<remove_const_t<typename T::element_type>, typename T::element_type>
127 and T::is_always_unique();
128
129/// \ingroup linalg
130template <typename T>
131concept in_matrix = is_mdspan_v<T> and T::rank() == 2;
132
133/// \ingroup linalg
134template <typename T>
135concept out_matrix = is_mdspan_v<T>
136 and T::rank() == 2
137 and is_same_v<remove_const_t<typename T::element_type>, typename T::element_type>
138 and T::is_always_unique();
139
140/// \ingroup linalg
141template <typename T>
142concept inout_matrix = is_mdspan_v<T>
143 and T::rank() == 2
144 and is_same_v<remove_const_t<typename T::element_type>, typename T::element_type>
145 and T::is_always_unique();
146
147/// \ingroup linalg
148template <typename T>
149concept in_object = is_mdspan_v<T> and (T::rank() == 1 or T::rank() == 2);
150
151/// \ingroup linalg
152template <typename T>
153concept out_object = is_mdspan_v<T>
154 and (T::rank() == 1 or T::rank() == 2)
155 and is_same_v<remove_const_t<typename T::element_type>, typename T::element_type>
156 and T::is_always_unique();
157
158/// \ingroup linalg
159template <typename T>
160concept inout_object = is_mdspan_v<T>
161 and (T::rank() == 1 or T::rank() == 2)
162 and is_same_v<remove_const_t<typename T::element_type>, typename T::element_type>
163 and T::is_always_unique();
164
165namespace detail {
166
167template <typename MDS1, typename MDS2>
168 requires(is_mdspan_v<MDS1> and is_mdspan_v<MDS2>)
169[[nodiscard]] constexpr auto compatible_static_extents(etl::size_t r1, etl::size_t r2) -> bool
170{
171 return MDS1::static_extent(r1) == dynamic_extent
172 or MDS2::static_extent(r2) == dynamic_extent
173 or MDS1::static_extent(r1) == MDS2::static_extent(r2);
174}
175
176template <in_vector In1, in_vector In2, in_vector Out>
177[[nodiscard]] constexpr auto possibly_addable() -> bool
178{
179 return compatible_static_extents<Out, In1>(0, 0)
180 and compatible_static_extents<Out, In2>(0, 0)
181 and compatible_static_extents<In1, In2>(0, 0);
182}
183
184template <in_matrix In1, in_matrix In2, in_matrix Out>
185[[nodiscard]] constexpr auto possibly_addable() -> bool
186{
187 return compatible_static_extents<Out, In1>(0, 0)
188 and compatible_static_extents<Out, In1>(1, 1)
189 and compatible_static_extents<Out, In2>(0, 0)
190 and compatible_static_extents<Out, In2>(1, 1)
191 and compatible_static_extents<In1, In2>(0, 0)
192 and compatible_static_extents<In1, In2>(1, 1);
193}
194
195template <in_matrix InMat, in_vector InVec, in_vector OutVec>
196[[nodiscard]] constexpr auto possibly_multipliable() -> bool
197{
198 return compatible_static_extents<OutVec, InMat>(0, 0) and compatible_static_extents<InMat, InVec>(1, 0);
199}
200
201template <in_vector InVec, in_matrix InMat, in_vector OutVec>
202[[nodiscard]] constexpr auto possibly_multipliable() -> bool
203{
204 return compatible_static_extents<OutVec, InMat>(0, 1) and compatible_static_extents<InMat, InVec>(0, 0);
205}
206
207template <in_matrix InMat1, in_matrix InMat2, in_matrix OutMat>
208[[nodiscard]] constexpr auto possibly_multipliable() -> bool
209{
210 return compatible_static_extents<OutMat, InMat1>(0, 0)
211 and compatible_static_extents<OutMat, InMat2>(1, 1)
212 and compatible_static_extents<InMat1, InMat2>(1, 0);
213}
214
215[[nodiscard]] constexpr auto addable(in_vector auto const& in1, in_vector auto const& in2, in_vector auto const& out)
216 -> bool
217{
218 return out.extent(0) == in1.extent(0) and out.extent(0) == in2.extent(0);
219}
220
221[[nodiscard]] constexpr auto addable(in_matrix auto const& in1, in_matrix auto const& in2, in_matrix auto const& out)
222 -> bool
223{
224 return out.extent(0) == in1.extent(0)
225 and out.extent(1) == in1.extent(1)
226 and out.extent(0) == in2.extent(0)
227 and out.extent(1) == in2.extent(1);
228}
229
230[[nodiscard]] constexpr auto
231multipliable(in_matrix auto const& inMat, in_vector auto const& inVec, in_vector auto const& outVec) -> bool
232{
233 return outVec.extent(0) == inMat.extent(0) and inMat.extent(1) == inVec.extent(0);
234}
235
236[[nodiscard]] constexpr auto
237multipliable(in_vector auto const& inVec, in_matrix auto const& inMat, in_vector auto const& outVec) -> bool
238{
239 return outVec.extent(0) == inMat.extent(1) and inMat.extent(0) == inVec.extent(0);
240}
241
242[[nodiscard]] constexpr auto
243multipliable(in_matrix auto const& inMat1, in_matrix auto const& inMat2, in_matrix auto const& outMat) -> bool
244{
245 return outMat.extent(0) == inMat1.extent(0)
246 and outMat.extent(1) == inMat2.extent(1)
247 and inMat1.extent(1) == inMat2.extent(0);
248}
249
250} // namespace detail
251
252} // namespace etl::linalg
253
254#endif // TETL_LINALG_EXPOSITION_HPP
constexpr auto dynamic_extent
etl::dynamic_extent is a constant of type etl::size_t that is used to differentiate etl::span of stat...
Definition dynamic_extent.hpp:15
Definition accessor_conjugate.hpp:13
Definition adjacent_find.hpp:9