Skip to content

Commit c991a4d

Browse files
committed
Introduce concepts for AccessTraits
1 parent 2784f30 commit c991a4d

9 files changed

+95
-147
lines changed

src/interpolation/ArborX_InterpMovingLeastSquares.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ template <typename MemorySpace, typename FloatingCalculationType = double>
6262
class MovingLeastSquares
6363
{
6464
public:
65-
template <typename ExecutionSpace, typename SourcePoints,
66-
typename TargetPoints, typename CRBFunc = CRBF::Wendland<0>,
65+
template <typename ExecutionSpace, Concepts::AccessTraits SourcePoints,
66+
Concepts::AccessTraits TargetPoints,
67+
typename CRBFunc = CRBF::Wendland<0>,
6768
typename PolynomialDegree = PolynomialDegree<2>>
6869
MovingLeastSquares(ExecutionSpace const &space,
6970
SourcePoints const &source_points,
@@ -80,7 +81,6 @@ class MovingLeastSquares
8081
"Memory space must be accessible from the execution space");
8182

8283
// SourcePoints is an access trait of points
83-
ArborX::Details::check_valid_access_traits(source_points);
8484
using SourceAccess = ArborX::Details::AccessValues<SourcePoints>;
8585
static_assert(
8686
KokkosExt::is_accessible_from<typename SourceAccess::memory_space,
@@ -93,7 +93,6 @@ class MovingLeastSquares
9393
static constexpr int dimension = GeometryTraits::dimension_v<SourcePoint>;
9494

9595
// TargetPoints is an access trait of points
96-
ArborX::Details::check_valid_access_traits(target_points);
9796
using TargetAccess = ArborX::Details::AccessValues<TargetPoints>;
9897
static_assert(
9998
KokkosExt::is_accessible_from<typename TargetAccess::memory_space,

src/spatial/ArborX_BruteForce.hpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class BruteForce
4848

4949
BruteForce() = default;
5050

51-
template <typename ExecutionSpace, typename Values>
51+
template <typename ExecutionSpace, Concepts::Primitives Values>
5252
BruteForce(ExecutionSpace const &space, Values const &values,
5353
IndexableGetter const &indexable_getter = IndexableGetter());
5454

@@ -61,12 +61,12 @@ class BruteForce
6161
KOKKOS_FUNCTION
6262
bounding_volume_type bounds() const noexcept { return _bounds; }
6363

64-
template <typename ExecutionSpace, typename Predicates, typename Callback,
65-
typename Ignore = int>
64+
template <typename ExecutionSpace, Concepts::Predicates Predicates,
65+
typename Callback, typename Ignore = int>
6666
void query(ExecutionSpace const &space, Predicates const &predicates,
6767
Callback const &callback, Ignore = Ignore()) const;
6868

69-
template <typename ExecutionSpace, typename UserPredicates,
69+
template <typename ExecutionSpace, Concepts::Predicates UserPredicates,
7070
typename CallbackOrView, typename View, typename... Args>
7171
std::enable_if_t<Kokkos::is_view_v<std::decay_t<View>>>
7272
query(ExecutionSpace const &space, UserPredicates const &user_predicates,
@@ -99,20 +99,21 @@ class BruteForce
9999
IndexableGetter _indexable_getter;
100100
};
101101

102-
template <typename ExecutionSpace, typename Values>
102+
template <typename ExecutionSpace, Concepts::Primitives Values>
103103
KOKKOS_DEDUCTION_GUIDE BruteForce(ExecutionSpace, Values)
104104
-> BruteForce<typename Details::AccessValues<Values>::memory_space,
105105
typename Details::AccessValues<Values>::value_type>;
106106

107-
template <typename ExecutionSpace, typename Values, typename IndexableGetter>
107+
template <typename ExecutionSpace, Concepts::Primitives Values,
108+
typename IndexableGetter>
108109
KOKKOS_DEDUCTION_GUIDE BruteForce(ExecutionSpace, Values, IndexableGetter)
109110
-> BruteForce<typename Details::AccessValues<Values>::memory_space,
110111
typename Details::AccessValues<Values>::value_type,
111112
IndexableGetter>;
112113

113114
template <typename MemorySpace, typename Value, typename IndexableGetter,
114115
typename BoundingVolume>
115-
template <typename ExecutionSpace, typename UserValues>
116+
template <typename ExecutionSpace, Concepts::Primitives UserValues>
116117
BruteForce<MemorySpace, Value, IndexableGetter, BoundingVolume>::BruteForce(
117118
ExecutionSpace const &space, UserValues const &user_values,
118119
IndexableGetter const &indexable_getter)
@@ -124,7 +125,6 @@ BruteForce<MemorySpace, Value, IndexableGetter, BoundingVolume>::BruteForce(
124125
{
125126
static_assert(Details::KokkosExt::is_accessible_from<MemorySpace,
126127
ExecutionSpace>::value);
127-
Details::check_valid_access_traits<UserValues>(user_values);
128128

129129
using Values = Details::AccessValues<UserValues>;
130130
Values values{user_values}; // NOLINT
@@ -147,17 +147,14 @@ BruteForce<MemorySpace, Value, IndexableGetter, BoundingVolume>::BruteForce(
147147

148148
template <typename MemorySpace, typename Value, typename IndexableGetter,
149149
typename BoundingVolume>
150-
template <typename ExecutionSpace, typename UserPredicates, typename Callback,
151-
typename Ignore>
150+
template <typename ExecutionSpace, Concepts::Predicates UserPredicates,
151+
typename Callback, typename Ignore>
152152
void BruteForce<MemorySpace, Value, IndexableGetter, BoundingVolume>::query(
153153
ExecutionSpace const &space, UserPredicates const &user_predicates,
154154
Callback const &callback, Ignore) const
155155
{
156156
static_assert(Details::KokkosExt::is_accessible_from<MemorySpace,
157157
ExecutionSpace>::value);
158-
Details::check_valid_access_traits(user_predicates,
159-
Details::CheckReturnTypeTag{});
160-
Details::check_valid_callback<value_type>(callback, user_predicates);
161158

162159
using Predicates = Details::AccessValues<UserPredicates>;
163160
static_assert(

src/spatial/ArborX_CrsGraphWrapper.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
#ifndef ARBORX_CRS_GRAPH_WRAPPER_HPP
1313
#define ARBORX_CRS_GRAPH_WRAPPER_HPP
1414

15+
#include <detail/ArborX_AccessTraits.hpp>
16+
1517
#include <Kokkos_Core.hpp>
1618

1719
namespace ArborX
1820
{
1921

20-
template <typename Tree, typename ExecutionSpace, typename Predicates,
21-
typename CallbackOrView, typename View, typename... Args>
22+
template <typename Tree, typename ExecutionSpace,
23+
Concepts::Predicates Predicates, typename CallbackOrView,
24+
typename View, typename... Args>
2225
inline void query(Tree const &tree, ExecutionSpace const &space,
2326
Predicates const &predicates,
2427
CallbackOrView &&callback_or_view, View &&view,

src/spatial/ArborX_LinearBVH.hpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class BoundingVolumeHierarchy
6565

6666
BoundingVolumeHierarchy() = default; // build an empty tree
6767

68-
template <typename ExecutionSpace, typename Values,
68+
template <typename ExecutionSpace, Concepts::Primitives Values,
6969
typename SpaceFillingCurve = Experimental::Morton64>
7070
BoundingVolumeHierarchy(
7171
ExecutionSpace const &space, Values const &values,
@@ -81,13 +81,14 @@ class BoundingVolumeHierarchy
8181
KOKKOS_FUNCTION
8282
bounding_volume_type bounds() const noexcept { return _bounds; }
8383

84-
template <typename ExecutionSpace, typename Predicates, typename Callback>
84+
template <typename ExecutionSpace, Concepts::Predicates Predicates,
85+
typename Callback>
8586
void query(ExecutionSpace const &space, Predicates const &predicates,
8687
Callback const &callback,
8788
Experimental::TraversalPolicy const &policy =
8889
Experimental::TraversalPolicy()) const;
8990

90-
template <typename ExecutionSpace, typename UserPredicates,
91+
template <typename ExecutionSpace, Concepts::Predicates UserPredicates,
9192
typename CallbackOrView, typename View, typename... Args>
9293
std::enable_if_t<Kokkos::is_view_v<std::decay_t<View>>>
9394
query(ExecutionSpace const &space, UserPredicates const &user_predicates,
@@ -140,13 +141,14 @@ class BoundingVolumeHierarchy
140141
IndexableGetter _indexable_getter;
141142
};
142143

143-
template <typename ExecutionSpace, typename Values>
144+
template <typename ExecutionSpace, Concepts::Primitives Values>
144145
KOKKOS_DEDUCTION_GUIDE BoundingVolumeHierarchy(ExecutionSpace, Values)
145146
-> BoundingVolumeHierarchy<
146147
typename Details::AccessValues<Values>::memory_space,
147148
typename Details::AccessValues<Values>::value_type>;
148149

149-
template <typename ExecutionSpace, typename Values, typename IndexableGetter>
150+
template <typename ExecutionSpace, Concepts::Primitives Values,
151+
typename IndexableGetter>
150152
KOKKOS_DEDUCTION_GUIDE BoundingVolumeHierarchy(ExecutionSpace, Values,
151153
IndexableGetter)
152154
-> BoundingVolumeHierarchy<
@@ -165,7 +167,7 @@ using BVH = BoundingVolumeHierarchy<MemorySpace, Value, IndexableGetter,
165167

166168
template <typename MemorySpace, typename Value, typename IndexableGetter,
167169
typename BoundingVolume>
168-
template <typename ExecutionSpace, typename UserValues,
170+
template <typename ExecutionSpace, Concepts::Primitives UserValues,
169171
typename SpaceFillingCurve>
170172
BoundingVolumeHierarchy<MemorySpace, Value, IndexableGetter, BoundingVolume>::
171173
BoundingVolumeHierarchy(ExecutionSpace const &space,
@@ -183,8 +185,6 @@ BoundingVolumeHierarchy<MemorySpace, Value, IndexableGetter, BoundingVolume>::
183185
{
184186
static_assert(Details::KokkosExt::is_accessible_from<MemorySpace,
185187
ExecutionSpace>::value);
186-
Details::check_valid_access_traits(user_values);
187-
188188
using Values = Details::AccessValues<UserValues>;
189189
Values values{user_values}; // NOLINT
190190

@@ -256,7 +256,8 @@ BoundingVolumeHierarchy<MemorySpace, Value, IndexableGetter, BoundingVolume>::
256256

257257
template <typename MemorySpace, typename Value, typename IndexableGetter,
258258
typename BoundingVolume>
259-
template <typename ExecutionSpace, typename UserPredicates, typename Callback>
259+
template <typename ExecutionSpace, Concepts::Predicates UserPredicates,
260+
typename Callback>
260261
void BoundingVolumeHierarchy<
261262
MemorySpace, Value, IndexableGetter,
262263
BoundingVolume>::query(ExecutionSpace const &space,
@@ -266,8 +267,6 @@ void BoundingVolumeHierarchy<
266267
{
267268
static_assert(Details::KokkosExt::is_accessible_from<MemorySpace,
268269
ExecutionSpace>::value);
269-
Details::check_valid_access_traits(user_predicates,
270-
Details::CheckReturnTypeTag{});
271270
Details::check_valid_callback<value_type>(callback, user_predicates);
272271

273272
using Predicates = Details::AccessValues<UserPredicates>;

src/spatial/detail/ArborX_AccessTraits.hpp

Lines changed: 31 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ struct AccessTraits
2727
using not_specialized = void; // tag to detect existence of a specialization
2828
};
2929

30-
template <typename Traits>
31-
using AccessTraitsNotSpecializedArchetypeAlias =
32-
typename Traits::not_specialized;
33-
3430
template <typename View>
3531
struct AccessTraits<
3632
View, std::enable_if_t<Kokkos::is_view<View>{} && View::rank() == 1>>
@@ -75,75 +71,45 @@ struct AccessTraits<
7571
using memory_space = typename View::memory_space;
7672
};
7773

78-
namespace Details
74+
namespace Concepts
7975
{
8076

81-
// archetypal alias for a 'memory_space' type member in access traits
82-
template <typename Traits>
83-
using AccessTraitsMemorySpaceArchetypeAlias = typename Traits::memory_space;
77+
template <class T, class U>
78+
concept not_same_as = !std::same_as<T, U>;
8479

85-
// archetypal expression for 'size()' static member function in access traits
86-
template <typename Traits, typename X>
87-
using AccessTraitsSizeArchetypeExpression =
88-
decltype(Traits::size(std::declval<X const &>()));
80+
template <typename T>
81+
concept AccessTraits = requires() {
82+
typename ArborX::AccessTraits<T>::memory_space;
83+
requires Kokkos::is_memory_space_v<
84+
typename ArborX::AccessTraits<T>::memory_space>;
85+
} && requires(T const &v) {
86+
{
87+
AccessTraits<T>::size(v)
88+
} -> std::integral;
89+
{
90+
AccessTraits<T>::get(v, 0)
91+
} -> not_same_as<void>;
92+
};
8993

90-
// archetypal expression for 'get()' static member function in access traits
91-
template <typename Traits, typename X>
92-
using AccessTraitsGetArchetypeExpression =
93-
decltype(Traits::get(std::declval<X const &>(), 0));
94+
template <typename T>
95+
concept HasTag = requires() { typename std::decay_t<T>::Tag; };
9496

95-
template <typename P>
96-
using PredicateTagArchetypeAlias = typename P::Tag;
97+
template <typename T>
98+
concept Primitives = AccessTraits<T>;
9799

98-
struct DoNotCheckReturnTypeTag
99-
{};
100+
template <typename T>
101+
concept Predicates = AccessTraits<T> && requires(T const &v) {
102+
{
103+
ArborX::AccessTraits<T>::get(v, 0)
104+
} -> HasTag;
105+
requires Details::is_valid_predicate_tag<typename std::decay_t<
106+
decltype(ArborX::AccessTraits<T>::get(v, 0))>::Tag>::value;
107+
};
100108

101-
struct CheckReturnTypeTag
102-
{};
109+
} // namespace Concepts
103110

104-
template <typename Values, typename Tag = DoNotCheckReturnTypeTag>
105-
void check_valid_access_traits(Values const &, Tag = {})
111+
namespace Details
106112
{
107-
using Access = AccessTraits<Values>;
108-
static_assert(
109-
!Kokkos::is_detected<AccessTraitsNotSpecializedArchetypeAlias, Access>{},
110-
"Must specialize 'AccessTraits<Values>'");
111-
112-
static_assert(
113-
Kokkos::is_detected<AccessTraitsMemorySpaceArchetypeAlias, Access>{},
114-
"AccessTraits<Values> must define 'memory_space' member type");
115-
static_assert(
116-
Kokkos::is_memory_space<
117-
Kokkos::detected_t<AccessTraitsMemorySpaceArchetypeAlias, Access>>{},
118-
"'memory_space' member type must be a valid Kokkos memory space");
119-
120-
static_assert(
121-
Kokkos::is_detected<AccessTraitsSizeArchetypeExpression, Access,
122-
Values>{},
123-
"AccessTraits<Values> must define 'size()' static member function");
124-
static_assert(
125-
std::is_integral<Kokkos::detected_t<AccessTraitsSizeArchetypeExpression,
126-
Access, Values>>{},
127-
"size() static member function return type is not an integral type");
128-
129-
static_assert(
130-
Kokkos::is_detected<AccessTraitsGetArchetypeExpression, Access, Values>{},
131-
"AccessTraits<Values> must define 'get()' static member function");
132-
static_assert(
133-
!std::is_void_v<Kokkos::detected_t<AccessTraitsGetArchetypeExpression,
134-
Access, Values>>,
135-
"get() static member function return type must not be void");
136-
137-
if constexpr (std::is_same_v<Tag, CheckReturnTypeTag>)
138-
{
139-
using Predicate = std::decay_t<
140-
Kokkos::detected_t<AccessTraitsGetArchetypeExpression, Access, Values>>;
141-
using PredicateTag =
142-
Kokkos::detected_t<PredicateTagArchetypeAlias, Predicate>;
143-
static_assert(is_valid_predicate_tag<PredicateTag>::value,
144-
"Invalid tag for the predicates");
145-
}
146-
}
147113

148114
template <typename Values>
149115
class AccessValuesI
@@ -157,8 +123,7 @@ class AccessValuesI
157123
: _values(std::move(values))
158124
{}
159125
using memory_space = typename Access::memory_space;
160-
using value_type = std::decay_t<
161-
Kokkos::detected_t<AccessTraitsGetArchetypeExpression, Access, Values>>;
126+
using value_type = std::decay_t<decltype(Access::get(_values, 0))>;
162127

163128
KOKKOS_FUNCTION
164129
decltype(auto) operator()(int i) const { return Access::get(_values, i); }

src/spatial/detail/ArborX_AttachIndices.hpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ namespace ArborX
2020

2121
namespace Experimental
2222
{
23-
template <typename Values, typename Index>
23+
template <Concepts::AccessTraits Values, typename Index>
2424
struct AttachIndices
2525
{
2626
Values _values;
2727
};
2828

2929
// Make sure the default Index matches the default in PairValueIndex
3030
template <typename Index = typename PairValueIndex<int>::index_type,
31-
typename Values = void>
31+
Concepts::AccessTraits Values = void>
3232
auto attach_indices(Values const &values)
3333
{
3434
return AttachIndices<Values, Index>{values};
@@ -53,18 +53,14 @@ struct ArborX::AccessTraits<ArborX::Experimental::AttachIndices<Values, Index>>
5353
}
5454
KOKKOS_FUNCTION static auto get(Self const &self, int i)
5555
{
56-
using namespace ArborX::Details;
57-
58-
using value_type = std::decay_t<
59-
Kokkos::detected_t<AccessTraitsGetArchetypeExpression, Access, Values>>;
60-
using PredicateTag =
61-
Kokkos::detected_t<PredicateTagArchetypeAlias, value_type>;
62-
63-
if constexpr (is_valid_predicate_tag<PredicateTag>::value)
56+
if constexpr (Concepts::Predicates<Values>)
6457
return attach(Access::get(self._values, i), Index(i));
6558
else
59+
{
60+
using value_type = std::decay_t<decltype(Access::get(self._values, 0))>;
6661
return PairValueIndex<value_type, Index>{Access::get(self._values, i),
6762
Index(i)};
63+
}
6864
}
6965
};
7066

0 commit comments

Comments
 (0)