Ginkgo Generated from branch based on master. Ginkgo version 1.8.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
precision_dispatch.hpp
1// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#ifndef GKO_PUBLIC_CORE_BASE_PRECISION_DISPATCH_HPP_
6#define GKO_PUBLIC_CORE_BASE_PRECISION_DISPATCH_HPP_
7
8
9#include <ginkgo/config.hpp>
10#include <ginkgo/core/base/math.hpp>
11#include <ginkgo/core/base/temporary_conversion.hpp>
12#include <ginkgo/core/distributed/vector.hpp>
13#include <ginkgo/core/matrix/dense.hpp>
14
15
16namespace gko {
17
18
43template <typename ValueType, typename Ptr>
44detail::temporary_conversion<std::conditional_t<
45 std::is_const<detail::pointee<Ptr>>::value, const matrix::Dense<ValueType>,
46 matrix::Dense<ValueType>>>
48{
49 using Pointee = detail::pointee<Ptr>;
50 using Dense = matrix::Dense<ValueType>;
52 using MaybeConstDense =
53 std::conditional_t<std::is_const<Pointee>::value, const Dense, Dense>;
54 auto result = detail::temporary_conversion<
55 MaybeConstDense>::template create<NextDense>(matrix);
56 if (!result) {
57 GKO_NOT_SUPPORTED(*matrix);
58 }
59 return result;
60}
61
62
77template <typename ValueType, typename Function, typename... Args>
78void precision_dispatch(Function fn, Args*... linops)
79{
80 fn(make_temporary_conversion<ValueType>(linops).get()...);
81}
82
83
93template <typename ValueType, typename Function>
94void precision_dispatch_real_complex(Function fn, const LinOp* in, LinOp* out)
95{
96 // do we need to convert complex Dense to real Dense?
97 // all real dense vectors are intra-convertible, thus by casting to
98 // ConvertibleTo<matrix::Dense<>>, we can check whether a LinOp is a real
99 // dense matrix:
100 auto complex_to_real =
102 dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in));
103 if (complex_to_real) {
106 using Dense = matrix::Dense<ValueType>;
107 // These dynamic_casts are only needed to make the code compile
108 // If ValueType is complex, this branch will never be taken
109 // If ValueType is real, the cast is a no-op
110 fn(dynamic_cast<const Dense*>(dense_in->create_real_view().get()),
111 dynamic_cast<Dense*>(dense_out->create_real_view().get()));
112 } else {
114 }
115}
116
117
127template <typename ValueType, typename Function>
128void precision_dispatch_real_complex(Function fn, const LinOp* alpha,
129 const LinOp* in, LinOp* out)
130{
131 // do we need to convert complex Dense to real Dense?
132 // all real dense vectors are intra-convertible, thus by casting to
133 // ConvertibleTo<matrix::Dense<>>, we can check whether a LinOp is a real
134 // dense matrix:
135 auto complex_to_real =
137 dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in));
138 if (complex_to_real) {
141 auto dense_alpha = make_temporary_conversion<ValueType>(alpha);
142 using Dense = matrix::Dense<ValueType>;
143 // These dynamic_casts are only needed to make the code compile
144 // If ValueType is complex, this branch will never be taken
145 // If ValueType is real, the cast is a no-op
146 fn(dense_alpha.get(),
147 dynamic_cast<const Dense*>(dense_in->create_real_view().get()),
148 dynamic_cast<Dense*>(dense_out->create_real_view().get()));
149 } else {
150 precision_dispatch<ValueType>(fn, alpha, in, out);
151 }
152}
153
154
164template <typename ValueType, typename Function>
165void precision_dispatch_real_complex(Function fn, const LinOp* alpha,
166 const LinOp* in, const LinOp* beta,
167 LinOp* out)
168{
169 // do we need to convert complex Dense to real Dense?
170 // all real dense vectors are intra-convertible, thus by casting to
171 // ConvertibleTo<matrix::Dense<>>, we can check whether a LinOp is a real
172 // dense matrix:
173 auto complex_to_real =
175 dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in));
176 if (complex_to_real) {
179 auto dense_alpha = make_temporary_conversion<ValueType>(alpha);
180 auto dense_beta = make_temporary_conversion<ValueType>(beta);
181 using Dense = matrix::Dense<ValueType>;
182 // These dynamic_casts are only needed to make the code compile
183 // If ValueType is complex, this branch will never be taken
184 // If ValueType is real, the cast is a no-op
185 fn(dense_alpha.get(),
186 dynamic_cast<const Dense*>(dense_in->create_real_view().get()),
187 dense_beta.get(),
188 dynamic_cast<Dense*>(dense_out->create_real_view().get()));
189 } else {
190 precision_dispatch<ValueType>(fn, alpha, in, beta, out);
191 }
192}
193
194
224template <typename ValueType, typename Function>
225void mixed_precision_dispatch(Function fn, const LinOp* in, LinOp* out)
226{
227#ifdef GINKGO_MIXED_PRECISION
228 using fst_type = matrix::Dense<ValueType>;
230 if (auto dense_in = dynamic_cast<const fst_type*>(in)) {
231 if (auto dense_out = dynamic_cast<fst_type*>(out)) {
232 fn(dense_in, dense_out);
233 } else if (auto dense_out = dynamic_cast<snd_type*>(out)) {
234 fn(dense_in, dense_out);
235 } else {
236 GKO_NOT_SUPPORTED(out);
237 }
238 } else if (auto dense_in = dynamic_cast<const snd_type*>(in)) {
239 if (auto dense_out = dynamic_cast<fst_type*>(out)) {
240 fn(dense_in, dense_out);
241 } else if (auto dense_out = dynamic_cast<snd_type*>(out)) {
242 fn(dense_in, dense_out);
243 } else {
244 GKO_NOT_SUPPORTED(out);
245 }
246 } else {
247 GKO_NOT_SUPPORTED(in);
248 }
249#else
251#endif
252}
253
254
264template <typename ValueType, typename Function,
265 std::enable_if_t<is_complex<ValueType>()>* = nullptr>
267 LinOp* out)
268{
269#ifdef GINKGO_MIXED_PRECISION
271#else
273#endif
274}
275
276
277template <typename ValueType, typename Function,
278 std::enable_if_t<!is_complex<ValueType>()>* = nullptr>
279void mixed_precision_dispatch_real_complex(Function fn, const LinOp* in,
280 LinOp* out)
281{
282#ifdef GINKGO_MIXED_PRECISION
283 if (!dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in)) {
285 [&fn](auto dense_in, auto dense_out) {
286 fn(dense_in->create_real_view().get(),
287 dense_out->create_real_view().get());
288 },
289 in, out);
290 } else {
292 }
293#else
295#endif
296}
297
298
299namespace experimental {
300
301
302#if GINKGO_BUILD_MPI
303
304
305namespace distributed {
306
307
333template <typename ValueType>
334detail::temporary_conversion<experimental::distributed::Vector<ValueType>>
336{
337 auto result = detail::temporary_conversion<
339 template create<
341 matrix);
342 if (!result) {
343 GKO_NOT_SUPPORTED(matrix);
344 }
345 return result;
346}
347
348
352template <typename ValueType>
353detail::temporary_conversion<const experimental::distributed::Vector<ValueType>>
355{
356 auto result = detail::temporary_conversion<
358 template create<
360 matrix);
361 if (!result) {
362 GKO_NOT_SUPPORTED(matrix);
363 }
364 return result;
365}
366
367
382template <typename ValueType, typename Function, typename... Args>
383void precision_dispatch(Function fn, Args*... linops)
384{
386}
387
388
398template <typename ValueType, typename Function>
399void precision_dispatch_real_complex(Function fn, const LinOp* in, LinOp* out)
400{
401 auto complex_to_real = !(
404 in));
405 if (complex_to_real) {
406 auto dense_in =
408 auto dense_out =
411 // These dynamic_casts are only needed to make the code compile
412 // If ValueType is complex, this branch will never be taken
413 // If ValueType is real, the cast is a no-op
414 fn(dynamic_cast<const Vector*>(dense_in->create_real_view().get()),
415 dynamic_cast<Vector*>(dense_out->create_real_view().get()));
416 } else {
418 }
419}
420
421
425template <typename ValueType, typename Function>
426void precision_dispatch_real_complex(Function fn, const LinOp* alpha,
427 const LinOp* in, LinOp* out)
428{
429 auto complex_to_real = !(
432 in));
433 if (complex_to_real) {
434 auto dense_in =
436 auto dense_out =
438 auto dense_alpha = gko::make_temporary_conversion<ValueType>(alpha);
440 // These dynamic_casts are only needed to make the code compile
441 // If ValueType is complex, this branch will never be taken
442 // If ValueType is real, the cast is a no-op
443 fn(dense_alpha.get(),
444 dynamic_cast<const Vector*>(dense_in->create_real_view().get()),
445 dynamic_cast<Vector*>(dense_out->create_real_view().get()));
446 } else {
450 }
451}
452
453
457template <typename ValueType, typename Function>
458void precision_dispatch_real_complex(Function fn, const LinOp* alpha,
459 const LinOp* in, const LinOp* beta,
460 LinOp* out)
461{
462 auto complex_to_real = !(
465 in));
466 if (complex_to_real) {
467 auto dense_in =
469 auto dense_out =
471 auto dense_alpha = gko::make_temporary_conversion<ValueType>(alpha);
472 auto dense_beta = gko::make_temporary_conversion<ValueType>(beta);
474 // These dynamic_casts are only needed to make the code compile
475 // If ValueType is complex, this branch will never be taken
476 // If ValueType is real, the cast is a no-op
477 fn(dense_alpha.get(),
478 dynamic_cast<const Vector*>(dense_in->create_real_view().get()),
479 dense_beta.get(),
480 dynamic_cast<Vector*>(dense_out->create_real_view().get()));
481 } else {
486 }
487}
488
489
490} // namespace distributed
491
492
506template <typename ValueType, typename Function>
507void precision_dispatch_real_complex_distributed(Function fn, const LinOp* in,
508 LinOp* out)
509{
510 if (dynamic_cast<const experimental::distributed::DistributedBase*>(in)) {
512 fn, in, out);
513 } else {
515 }
516}
517
518
523template <typename ValueType, typename Function>
524void precision_dispatch_real_complex_distributed(Function fn,
525 const LinOp* alpha,
526 const LinOp* in, LinOp* out)
527{
528 if (dynamic_cast<const experimental::distributed::DistributedBase*>(in)) {
530 fn, alpha, in, out);
531 } else {
533 }
534}
535
536
541template <typename ValueType, typename Function>
542void precision_dispatch_real_complex_distributed(Function fn,
543 const LinOp* alpha,
544 const LinOp* in,
545 const LinOp* beta, LinOp* out)
546{
547 if (dynamic_cast<const experimental::distributed::DistributedBase*>(in)) {
549 fn, alpha, in, beta, out);
550 } else {
552 out);
553 }
554}
555
556
557#else
558
559
570template <typename ValueType, typename Function, typename... Args>
571void precision_dispatch_real_complex_distributed(Function fn, Args*... args)
572{
574}
575
576
577#endif
578
579
580} // namespace experimental
581} // namespace gko
582
583
584#endif // GKO_PUBLIC_CORE_BASE_PRECISION_DISPATCH_HPP_
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition polymorphic_object.hpp:471
Definition lin_op.hpp:118
A base class for distributed objects.
Definition base.hpp:32
Vector is a format which explicitly stores (multiple) distributed column vectors in a dense storage f...
Definition dense.hpp:30
Dense is a matrix format which explicitly stores all values of the matrix.
Definition sparsity_csr.hpp:26
void precision_dispatch_real_complex(Function fn, const LinOp *in, LinOp *out)
Calls the given function with the given LinOps temporarily converted to experimental::distributed::Ve...
Definition precision_dispatch.hpp:399
detail::temporary_conversion< experimental::distributed::Vector< ValueType > > make_temporary_conversion(LinOp *matrix)
Convert the given LinOp from experimental::distributed::Vector<...> to experimental::distributed::Vec...
Definition precision_dispatch.hpp:335
void precision_dispatch(Function fn, Args *... linops)
Calls the given function with each given argument LinOp temporarily converted into experimental::dist...
Definition precision_dispatch.hpp:383
The Ginkgo namespace.
Definition abstract_factory.hpp:20
void mixed_precision_dispatch(Function fn, const LinOp *in, LinOp *out)
Calls the given function with each given argument LinOp converted into matrix::Dense<ValueType> as pa...
Definition precision_dispatch.hpp:225
void mixed_precision_dispatch_real_complex(Function fn, const LinOp *in, LinOp *out)
Calls the given function with the given LinOps cast to their dynamic type matrix::Dense<ValueType>* a...
Definition precision_dispatch.hpp:266
void precision_dispatch(Function fn, Args *... linops)
Calls the given function with each given argument LinOp temporarily converted into matrix::Dense<Valu...
Definition precision_dispatch.hpp:78
detail::temporary_conversion< std::conditional_t< std::is_const< detail::pointee< Ptr > >::value, const matrix::Dense< ValueType >, matrix::Dense< ValueType > > > make_temporary_conversion(Ptr &&matrix)
Convert the given LinOp from matrix::Dense<...> to matrix::Dense<ValueType>.
Definition precision_dispatch.hpp:47
void precision_dispatch_real_complex(Function fn, const LinOp *in, LinOp *out)
Calls the given function with the given LinOps temporarily converted to matrix::Dense<ValueType>* as ...
Definition precision_dispatch.hpp:94
constexpr bool is_complex()
Checks if T is a complex type.
Definition math.hpp:287