-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathlinalg_execpolicy_mapper.hpp
More file actions
134 lines (116 loc) · 4.69 KB
/
linalg_execpolicy_mapper.hpp
File metadata and controls
134 lines (116 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//@HEADER
// ************************************************************************
//
// Kokkos v. 4.0
// Copyright (2022) National Technology & Engineering
// Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// ************************************************************************
//@HEADER
#ifdef LINALG_HAS_EXECUTION
# include <execution>
#endif
#include <type_traits>
#include <utility>
namespace MDSPAN_IMPL_STANDARD_NAMESPACE {
namespace MDSPAN_IMPL_PROPOSED_NAMESPACE {
inline namespace __p1673_version_0 {
namespace linalg {
namespace impl {
// the execution policy used for default serial inline implementations
struct inline_exec_t {};
// The execution policy used when no execution policy is provided
// It must be remapped to some other execution policy, which the default mapper does
struct default_exec_t {};
// helpers
template<class T> struct is_inline_exec : std::false_type{};
template<> struct is_inline_exec<inline_exec_t> : std::true_type{};
template<class T> inline constexpr bool is_inline_exec_v = is_inline_exec<T>::value;
// value is true if and only if T is one of the std::linalg-specific
// custom execution policies provided by this implementation.
// Specialize this to be true for any new custom execution policy.
template<class T>
inline constexpr bool is_custom_linalg_execution_policy_v =
std::is_same_v<T, default_exec_t> || std::is_same_v<T, inline_exec_t>;
// value is true if and only if T is
//
// * a Standard execution policy (like std::execution::parallel_policy),
// * one of the C++ implementation-specific execution policies, or
// * one of the std::linalg-specific custom execution policies
// (other than inline_exec).
//
// This helps disambiguate ExecutionPolicy from otherwise
// unconstrained template parameters like ScaleFactorType in
// algorithms like symmetric_matrix_rank_k_update.
template<class T>
inline constexpr bool is_linalg_execution_policy_v =
(
#ifdef LINALG_HAS_EXECUTION
std::is_execution_policy_v<T> ||
#endif
is_custom_linalg_execution_policy_v<T>
);
// value is true if and only if T is _not_ inline_exec, and if T is
//
// * a Standard execution policy (like std::execution::parallel_policy),
// * one of the C++ implementation-specific execution policies, or
// * one of the std::linalg-specific custom execution policies
// (other than inline_exec).
//
// This helps disambiguate ExecutionPolicy from otherwise
// unconstrained template parameters like ScaleFactorType in
// algorithms like symmetric_matrix_rank_k_update.
template<class T>
inline constexpr bool is_linalg_execution_policy_other_than_inline_v =
! is_inline_exec_v<T> &&
is_linalg_execution_policy_v<T>;
} // namespace impl
} // namespace linalg
} // inline namespace __p1673_version_0
} // namespace MDSPAN_IMPL_PROPOSED_NAMESPACE
} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE
#if defined(LINALG_ENABLE_KOKKOS)
#include <experimental/__p1673_bits/kokkos-kernels/exec_policy_wrapper_kk.hpp>
#endif
namespace MDSPAN_IMPL_STANDARD_NAMESPACE {
namespace MDSPAN_IMPL_PROPOSED_NAMESPACE {
inline namespace __p1673_version_0 {
namespace linalg {
// Specialize this function to map a public execution policy
// (e.g., std::execution::parallel_policy) to an internal policy.
// This function must always return a different type than its input.
template<class T>
auto execpolicy_mapper(T) { return impl::inline_exec_t(); }
namespace impl {
// std::remove_cvref_t is a C++20 feature.
#ifdef __cpp_lib_remove_cvref
using std::remove_cvref_t;
#else
template<class T>
using remove_cvref_t = std::remove_const_t<std::remove_reference_t<T>>;
#endif
// This function is not to be specialized; that's why
// it's a generic lambda instead of a function template.
inline auto map_execpolicy_with_check = [](auto&& policy) {
using input_type = remove_cvref_t<decltype(policy)>;
using return_type = remove_cvref_t<decltype(execpolicy_mapper(std::forward<decltype(policy)>(policy)))>;
// Only inline_exec_t is allowed to map to itself.
using inline_type = impl::inline_exec_t;
static_assert(std::is_same_v<input_type, inline_type> ||
! std::is_same_v<input_type, return_type>,
"Specializations of execpolicy_mapper must return "
"a different policy type than their input");
return execpolicy_mapper(std::forward<decltype(policy)>(policy));
};
} // namespace impl
} // namespace linalg
} // namespace __p1673_version_0
} // namespace experimental
} // namespace std