Ginkgo Generated from branch based on master. Ginkgo version 1.7.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
precision_dispatch.hpp
1/*******************************<GINKGO LICENSE>******************************
2Copyright (c) 2017-2023, the Ginkgo authors
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
8
91. Redistributions of source code must retain the above copyright
10notice, this list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
163. Neither the name of the copyright holder nor the names of its
17contributors may be used to endorse or promote products derived from
18this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31******************************<GINKGO LICENSE>*******************************/
32
33#ifndef GKO_PUBLIC_CORE_BASE_PRECISION_DISPATCH_HPP_
34#define GKO_PUBLIC_CORE_BASE_PRECISION_DISPATCH_HPP_
35
36
37#include <ginkgo/config.hpp>
38#include <ginkgo/core/base/math.hpp>
39#include <ginkgo/core/base/temporary_conversion.hpp>
40#include <ginkgo/core/distributed/vector.hpp>
41#include <ginkgo/core/matrix/dense.hpp>
42
43
44namespace gko {
45
46
71template <typename ValueType, typename Ptr>
72detail::temporary_conversion<std::conditional_t<
73 std::is_const<detail::pointee<Ptr>>::value, const matrix::Dense<ValueType>,
74 matrix::Dense<ValueType>>>
76{
77 using Pointee = detail::pointee<Ptr>;
78 using Dense = matrix::Dense<ValueType>;
80 using MaybeConstDense =
81 std::conditional_t<std::is_const<Pointee>::value, const Dense, Dense>;
82 auto result = detail::temporary_conversion<
84 if (!result) {
85 GKO_NOT_SUPPORTED(*matrix);
86 }
87 return result;
88}
89
90
105template <typename ValueType, typename Function, typename... Args>
110
111
121template <typename ValueType, typename Function>
123{
124 // do we need to convert complex Dense to real Dense?
125 // all real dense vectors are intra-convertible, thus by casting to
126 // ConvertibleTo<matrix::Dense<>>, we can check whether a LinOp is a real
127 // dense matrix:
128 auto complex_to_real =
130 dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in));
131 if (complex_to_real) {
134 using Dense = matrix::Dense<ValueType>;
135 // These dynamic_casts are only needed to make the code compile
136 // If ValueType is complex, this branch will never be taken
137 // If ValueType is real, the cast is a no-op
138 fn(dynamic_cast<const Dense*>(dense_in->create_real_view().get()),
139 dynamic_cast<Dense*>(dense_out->create_real_view().get()));
140 } else {
142 }
143}
144
145
155template <typename ValueType, typename Function>
157 const LinOp* in, LinOp* out)
158{
159 // do we need to convert complex Dense to real Dense?
160 // all real dense vectors are intra-convertible, thus by casting to
161 // ConvertibleTo<matrix::Dense<>>, we can check whether a LinOp is a real
162 // dense matrix:
163 auto complex_to_real =
165 dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in));
166 if (complex_to_real) {
170 using Dense = matrix::Dense<ValueType>;
171 // These dynamic_casts are only needed to make the code compile
172 // If ValueType is complex, this branch will never be taken
173 // If ValueType is real, the cast is a no-op
174 fn(dense_alpha.get(),
175 dynamic_cast<const Dense*>(dense_in->create_real_view().get()),
176 dynamic_cast<Dense*>(dense_out->create_real_view().get()));
177 } else {
179 }
180}
181
182
192template <typename ValueType, typename Function>
194 const LinOp* in, const LinOp* beta,
195 LinOp* out)
196{
197 // do we need to convert complex Dense to real Dense?
198 // all real dense vectors are intra-convertible, thus by casting to
199 // ConvertibleTo<matrix::Dense<>>, we can check whether a LinOp is a real
200 // dense matrix:
201 auto complex_to_real =
203 dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in));
204 if (complex_to_real) {
209 using Dense = matrix::Dense<ValueType>;
210 // These dynamic_casts are only needed to make the code compile
211 // If ValueType is complex, this branch will never be taken
212 // If ValueType is real, the cast is a no-op
213 fn(dense_alpha.get(),
214 dynamic_cast<const Dense*>(dense_in->create_real_view().get()),
215 dense_beta.get(),
216 dynamic_cast<Dense*>(dense_out->create_real_view().get()));
217 } else {
218 precision_dispatch<ValueType>(fn, alpha, in, beta, out);
219 }
220}
221
222
252template <typename ValueType, typename Function>
254{
255#ifdef GINKGO_MIXED_PRECISION
258 if (auto dense_in = dynamic_cast<const fst_type*>(in)) {
259 if (auto dense_out = dynamic_cast<fst_type*>(out)) {
261 } else if (auto dense_out = dynamic_cast<snd_type*>(out)) {
263 } else {
264 GKO_NOT_SUPPORTED(out);
265 }
266 } else if (auto dense_in = dynamic_cast<const snd_type*>(in)) {
267 if (auto dense_out = dynamic_cast<fst_type*>(out)) {
269 } else if (auto dense_out = dynamic_cast<snd_type*>(out)) {
271 } else {
272 GKO_NOT_SUPPORTED(out);
273 }
274 } else {
275 GKO_NOT_SUPPORTED(in);
276 }
277#else
279#endif
280}
281
282
292template <typename ValueType, typename Function,
293 std::enable_if_t<is_complex<ValueType>()>* = nullptr>
295 LinOp* out)
296{
297#ifdef GINKGO_MIXED_PRECISION
299#else
301#endif
302}
303
304
305template <typename ValueType, typename Function,
306 std::enable_if_t<!is_complex<ValueType>()>* = nullptr>
308 LinOp* out)
309{
310#ifdef GINKGO_MIXED_PRECISION
311 if (!dynamic_cast<const ConvertibleTo<matrix::Dense<>>*>(in)) {
313 [&fn](auto dense_in, auto dense_out) {
314 fn(dense_in->create_real_view().get(),
315 dense_out->create_real_view().get());
316 },
317 in, out);
318 } else {
320 }
321#else
323#endif
324}
325
326
327namespace experimental {
328
329
330#if GINKGO_BUILD_MPI
331
332
333namespace distributed {
334
335
361template <typename ValueType>
362detail::temporary_conversion<experimental::distributed::Vector<ValueType>>
364{
365 auto result = detail::temporary_conversion<
367 template create<
369 matrix);
370 if (!result) {
371 GKO_NOT_SUPPORTED(matrix);
372 }
373 return result;
374}
375
376
380template <typename ValueType>
381detail::temporary_conversion<const experimental::distributed::Vector<ValueType>>
383{
384 auto result = detail::temporary_conversion<
386 template create<
388 matrix);
389 if (!result) {
390 GKO_NOT_SUPPORTED(matrix);
391 }
392 return result;
393}
394
395
410template <typename ValueType, typename Function, typename... Args>
412{
413 fn(distributed::make_temporary_conversion<ValueType>(linops).get()...);
414}
415
416
426template <typename ValueType, typename Function>
428{
429 auto complex_to_real = !(
432 in));
433 if (complex_to_real) {
434 auto dense_in =
435 distributed::make_temporary_conversion<to_complex<ValueType>>(in);
436 auto dense_out =
437 distributed::make_temporary_conversion<to_complex<ValueType>>(out);
439 // These dynamic_casts are only needed to make the code compile
440 // If ValueType is complex, this branch will never be taken
441 // If ValueType is real, the cast is a no-op
442 fn(dynamic_cast<const Vector*>(dense_in->create_real_view().get()),
443 dynamic_cast<Vector*>(dense_out->create_real_view().get()));
444 } else {
445 distributed::precision_dispatch<ValueType>(fn, in, out);
446 }
447}
448
449
453template <typename ValueType, typename Function>
455 const LinOp* in, LinOp* out)
456{
457 auto complex_to_real = !(
460 in));
461 if (complex_to_real) {
462 auto dense_in =
463 distributed::make_temporary_conversion<to_complex<ValueType>>(in);
464 auto dense_out =
465 distributed::make_temporary_conversion<to_complex<ValueType>>(out);
468 // These dynamic_casts are only needed to make the code compile
469 // If ValueType is complex, this branch will never be taken
470 // If ValueType is real, the cast is a no-op
471 fn(dense_alpha.get(),
472 dynamic_cast<const Vector*>(dense_in->create_real_view().get()),
473 dynamic_cast<Vector*>(dense_out->create_real_view().get()));
474 } else {
476 distributed::make_temporary_conversion<ValueType>(in).get(),
477 distributed::make_temporary_conversion<ValueType>(out).get());
478 }
479}
480
481
485template <typename ValueType, typename Function>
487 const LinOp* in, const LinOp* beta,
488 LinOp* out)
489{
490 auto complex_to_real = !(
493 in));
494 if (complex_to_real) {
495 auto dense_in =
496 distributed::make_temporary_conversion<to_complex<ValueType>>(in);
497 auto dense_out =
498 distributed::make_temporary_conversion<to_complex<ValueType>>(out);
502 // These dynamic_casts are only needed to make the code compile
503 // If ValueType is complex, this branch will never be taken
504 // If ValueType is real, the cast is a no-op
505 fn(dense_alpha.get(),
506 dynamic_cast<const Vector*>(dense_in->create_real_view().get()),
507 dense_beta.get(),
508 dynamic_cast<Vector*>(dense_out->create_real_view().get()));
509 } else {
511 distributed::make_temporary_conversion<ValueType>(in).get(),
513 distributed::make_temporary_conversion<ValueType>(out).get());
514 }
515}
516
517
518} // namespace distributed
519
520
534template <typename ValueType, typename Function>
535void precision_dispatch_real_complex_distributed(Function fn, const LinOp* in,
536 LinOp* out)
537{
538 if (dynamic_cast<const experimental::distributed::DistributedBase*>(in)) {
539 experimental::distributed::precision_dispatch_real_complex<ValueType>(
540 fn, in, out);
541 } else {
543 }
544}
545
546
551template <typename ValueType, typename Function>
552void precision_dispatch_real_complex_distributed(Function fn,
553 const LinOp* alpha,
554 const LinOp* in, LinOp* out)
555{
556 if (dynamic_cast<const experimental::distributed::DistributedBase*>(in)) {
557 experimental::distributed::precision_dispatch_real_complex<ValueType>(
558 fn, alpha, in, out);
559 } else {
561 }
562}
563
564
569template <typename ValueType, typename Function>
570void precision_dispatch_real_complex_distributed(Function fn,
571 const LinOp* alpha,
572 const LinOp* in,
573 const LinOp* beta, LinOp* out)
574{
575 if (dynamic_cast<const experimental::distributed::DistributedBase*>(in)) {
576 experimental::distributed::precision_dispatch_real_complex<ValueType>(
577 fn, alpha, in, beta, out);
578 } else {
580 out);
581 }
582}
583
584
585#else
586
587
598template <typename ValueType, typename Function, typename... Args>
599void precision_dispatch_real_complex_distributed(Function fn, Args*... args)
600{
602}
603
604
605#endif
606
607
608} // namespace experimental
609} // namespace gko
610
611
612#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:499
Definition lin_op.hpp:146
A base class for distributed objects.
Definition base.hpp:60
Vector is a format which explicitly stores (multiple) distributed column vectors in a dense storage f...
Definition vector.hpp:92
Dense is a matrix format which explicitly stores all values of the matrix.
Definition dense.hpp:136
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:427
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:363
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:411
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
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:253
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:294
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:106
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:75
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:122