Skip to content

Commit 9bdba47

Browse files
authored
feat: Ranges pipe operator (#937)
Implement a simple version of the pipe operator for ranges composition. Also extended the ranges integrations tests and moved them to the other integration tests
1 parent 9566194 commit 9bdba47

File tree

14 files changed

+401
-185
lines changed

14 files changed

+401
-185
lines changed

core/include/detray/utils/concepts.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ concept same_as_cvref =
3434
template <typename T, typename U>
3535
concept same_as_no_const = std::same_as<std::remove_cv_t<T>, U>;
3636

37+
/// Index concept to access vector/matrix elements
38+
template <typename T>
39+
concept index = std::is_integral_v<T> && !std::same_as<T, bool>;
40+
3741
/// Concept that checks if a type models an interval of some value that can
3842
/// be obtained with 'get'.
3943
template <typename I>

core/include/detray/utils/ranges/cartesian_product.hpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,13 @@ struct cartesian_product : public ranges::cartesian_product_view<range_ts...> {
101101

102102
constexpr cartesian_product() = default;
103103

104-
DETRAY_HOST_DEVICE constexpr explicit cartesian_product(range_ts... ranges)
105-
: base_type(ranges...) {}
104+
template <detray::ranges::range... deduced_range_ts>
105+
DETRAY_HOST_DEVICE constexpr explicit cartesian_product(
106+
deduced_range_ts &&... ranges)
107+
: base_type(std::forward<deduced_range_ts>(ranges)...) {}
106108
};
107109

108110
// deduction guides
109-
110111
template <detray::ranges::range... ranges_ts>
111112
DETRAY_HOST_DEVICE cartesian_product(ranges_ts &&... ranges)
112113
->cartesian_product<ranges_ts...>;

core/include/detray/utils/ranges/enumerate.hpp

+40-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// Project include(s)
1111
#include "detray/definitions/detail/qualifiers.hpp"
1212
#include "detray/definitions/indexing.hpp"
13+
#include "detray/utils/ranges/empty.hpp"
1314
#include "detray/utils/ranges/ranges.hpp"
1415
#include "detray/utils/ranges/subrange.hpp"
1516

@@ -203,16 +204,15 @@ class enumerate_view : public detray::ranges::view_interface<
203204
/// Construct from a @param range that will be enumerated beginning at 0
204205
template <detray::ranges::range range_t>
205206
DETRAY_HOST_DEVICE constexpr explicit enumerate_view(range_t &&rng)
206-
: m_begin{detray::ranges::begin(std::forward<range_t>(rng))},
207-
m_end{detray::ranges::end(std::forward<range_t>(rng)),
208-
static_cast<incr_t>(rng.size())} {}
207+
: m_begin{detray::ranges::begin(rng)},
208+
m_end{detray::ranges::end(rng), static_cast<incr_t>(rng.size())} {}
209209

210210
/// Construct from a @param range that will be enumerated beginning at
211211
/// @param start.
212212
template <detray::ranges::range range_t>
213213
DETRAY_HOST_DEVICE constexpr enumerate_view(range_t &&rng, incr_t start)
214-
: m_begin{detray::ranges::begin(std::forward<range_t>(rng)), start},
215-
m_end{detray::ranges::end(std::forward<range_t>(rng)),
214+
: m_begin{detray::ranges::begin(rng), start},
215+
m_end{detray::ranges::end(rng),
216216
start + static_cast<incr_t>(rng.size())} {}
217217

218218
/// @return start position of range on container.
@@ -237,8 +237,16 @@ requires std::convertible_to<std::iter_difference_t<range_itr_t>,
237237

238238
using base_type = enumerate_view<range_itr_t, incr_t>;
239239

240+
/// Partial construction for range composition
241+
/// @{
240242
constexpr enumerate() = default;
241243

244+
DETRAY_HOST_DEVICE constexpr explicit enumerate(incr_t start)
245+
: m_incr{start} {}
246+
/// @}
247+
248+
/// Direct view construction
249+
/// @{
242250
template <detray::ranges::range range_t>
243251
DETRAY_HOST_DEVICE constexpr explicit enumerate(range_t &&rng)
244252
: base_type(std::forward<range_t>(rng)) {}
@@ -253,22 +261,46 @@ requires std::convertible_to<std::iter_difference_t<range_itr_t>,
253261
: enumerate(detray::ranges::subrange(
254262
std::forward<deduced_range_t>(range), vol),
255263
detray::detail::get<0>(vol.full_range())) {}
264+
/// @}
265+
266+
/// Call operator for range composition
267+
template <detray::ranges::range range_t>
268+
DETRAY_HOST_DEVICE constexpr auto operator()(range_t &&rng) {
269+
using itr_t = detray::ranges::const_iterator_t<std::decay_t<range_t>>;
270+
return detray::ranges::enumerate_view<itr_t, incr_t>(
271+
std::forward<range_t>(rng), m_incr);
272+
}
273+
274+
private:
275+
incr_t m_incr{0};
256276
};
257277

258278
// deduction guides
279+
DETRAY_HOST_DEVICE enumerate()
280+
->enumerate<
281+
detray::ranges::const_iterator_t<detray::ranges::views::empty<int>>,
282+
dindex>;
283+
284+
DETRAY_HOST_DEVICE enumerate(dindex start)
285+
->enumerate<
286+
detray::ranges::const_iterator_t<detray::ranges::views::empty<int>>,
287+
dindex>;
259288

260289
template <detray::ranges::range range_t>
261290
DETRAY_HOST_DEVICE enumerate(range_t &&rng)
262-
->enumerate<detray::ranges::const_iterator_t<range_t>, dindex>;
291+
->enumerate<detray::ranges::const_iterator_t<std::decay_t<range_t>>,
292+
dindex>;
263293

264294
template <detray::ranges::range range_t, typename volume_t,
265295
typename = typename std::remove_reference_t<volume_t>::volume_def>
266296
DETRAY_HOST_DEVICE enumerate(range_t &&range, const volume_t &vol)
267-
->enumerate<detray::ranges::const_iterator_t<range_t>, dindex>;
297+
->enumerate<detray::ranges::const_iterator_t<std::decay_t<range_t>>,
298+
dindex>;
268299

269300
template <detray::ranges::range range_t>
270301
DETRAY_HOST_DEVICE enumerate(range_t &&rng, dindex start)
271-
->enumerate<detray::ranges::const_iterator_t<range_t>, dindex>;
302+
->enumerate<detray::ranges::const_iterator_t<std::decay_t<range_t>>,
303+
dindex>;
272304

273305
} // namespace views
274306

core/include/detray/utils/ranges/iota.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ class iota_view : public detray::ranges::view_interface<iota_view<incr_t>> {
104104
/// Construct from an @param interval that defines start and end values.
105105
template <concepts::interval interval_t>
106106
DETRAY_HOST_DEVICE constexpr explicit iota_view(interval_t &&interval)
107-
: m_start{detray::detail::get<0>(std::forward<interval_t>(interval))},
108-
m_end{detray::detail::get<1>(std::forward<interval_t>(interval))} {}
107+
: m_start{detray::detail::get<0>(interval)},
108+
m_end{detray::detail::get<1>(interval)} {}
109109

110110
/// Construct from a @param start start and @param end value.
111111
DETRAY_HOST_DEVICE constexpr iota_view(incr_t start, incr_t end)

core/include/detray/utils/ranges/join.hpp

+13-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// Project include(s)
1111
#include "detray/definitions/containers.hpp"
1212
#include "detray/definitions/detail/qualifiers.hpp"
13+
#include "detray/utils/ranges/empty.hpp"
1314
#include "detray/utils/ranges/ranges.hpp"
1415
#include "detray/utils/type_traits.hpp"
1516

@@ -58,8 +59,8 @@ struct join_view : public detray::ranges::view_interface<join_view<range_t>> {
5859
/// Construct from a range of @param ranges.
5960
template <detray::ranges::range R>
6061
DETRAY_HOST_DEVICE constexpr explicit join_view(R &&ranges)
61-
: m_begin{detray::ranges::begin(std::forward<R>(ranges))},
62-
m_end{detray::ranges::end(std::forward<R>(ranges))} {}
62+
: m_begin{detray::ranges::begin(ranges)},
63+
m_end{detray::ranges::end(ranges)} {}
6364

6465
/// @return start position of range - const
6566
DETRAY_HOST_DEVICE
@@ -104,14 +105,21 @@ namespace views {
104105
template <detray::ranges::range range_t>
105106
struct join : public ranges::join_view<range_t> {
106107

107-
using base_type = ranges::join_view<range_t>;
108+
using base_type = detray::ranges::join_view<range_t>;
108109

109110
constexpr join() = default;
110111

111112
template <detray::ranges::range deduced_range_t>
112113
DETRAY_HOST_DEVICE constexpr explicit join(deduced_range_t &&ranges)
113114
: base_type(std::forward<deduced_range_t>(ranges)) {}
114115

116+
/// Call operator for range composition
117+
template <detray::ranges::range deduced_range_t>
118+
DETRAY_HOST_DEVICE constexpr auto operator()(deduced_range_t &&ranges) {
119+
return detray::ranges::join_view<deduced_range_t>(
120+
std::forward<deduced_range_t>(ranges));
121+
}
122+
115123
/// Copy assignment operator
116124
DETRAY_HOST_DEVICE
117125
join &operator=(const join &other) {
@@ -121,6 +129,8 @@ struct join : public ranges::join_view<range_t> {
121129
};
122130

123131
// deduction guides
132+
DETRAY_HOST_DEVICE join()->join<detray::ranges::views::empty<dvector<int>>>;
133+
124134
template <detray::ranges::range R>
125135
DETRAY_HOST_DEVICE join(R &&ranges)->join<std::remove_reference_t<R>>;
126136

core/include/detray/utils/ranges/pick.hpp

+62-11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// Project include(s)
1111
#include "detray/definitions/detail/qualifiers.hpp"
1212
#include "detray/definitions/indexing.hpp"
13+
#include "detray/utils/ranges/empty.hpp"
1314
#include "detray/utils/ranges/ranges.hpp"
1415

1516
// System include(s)
@@ -298,25 +299,75 @@ class pick_view : public detray::ranges::view_interface<
298299

299300
namespace views {
300301

301-
template <std::input_iterator range_itr_t, std::input_iterator sequence_itr_t>
302-
struct pick : public pick_view<range_itr_t, sequence_itr_t> {
302+
template <std::input_iterator range_itr_t,
303+
detray::ranges::input_range sequence_t>
304+
struct pick : public pick_view<range_itr_t, detray::ranges::const_iterator_t<
305+
std::decay_t<sequence_t>>> {
303306

307+
using sequence_itr_t =
308+
detray::ranges::const_iterator_t<std::decay_t<sequence_t>>;
304309
using base_type = pick_view<range_itr_t, sequence_itr_t>;
305310

306-
pick() = default;
311+
constexpr pick() = default;
312+
313+
template <detray::ranges::input_range deduced_sequence_t>
314+
DETRAY_HOST_DEVICE constexpr explicit pick(deduced_sequence_t &&seq)
315+
: m_seq(std::forward<deduced_sequence_t>(seq)) {}
316+
317+
template <detray::ranges::range range_t,
318+
detray::ranges::input_range deduced_sequence_t>
319+
DETRAY_HOST_DEVICE constexpr pick(range_t &&range, deduced_sequence_t &&seq)
320+
: base_type(std::forward<range_t>(range), seq),
321+
m_seq{std::forward<deduced_sequence_t>(seq)} {}
322+
323+
/// Call operator for range composition - move semantics
324+
template <detray::ranges::range range_t>
325+
requires(std::same_as<sequence_t, std::remove_cvref_t<sequence_t>> &&
326+
!std::is_pointer_v<sequence_t>) DETRAY_HOST_DEVICE constexpr auto
327+
operator()(range_t &&rng) && {
328+
using itr_t =
329+
detray::ranges::iterator_t<std::remove_reference_t<range_t>>;
330+
return detray::ranges::pick_view<itr_t, sequence_itr_t>(
331+
std::forward<range_t>(rng), std::move(m_seq));
332+
}
307333

308-
template <detray::ranges::range range_t, detray::ranges::range sequence_t>
309-
DETRAY_HOST_DEVICE constexpr pick(range_t &&range, sequence_t &&seq)
310-
: base_type(std::forward<range_t>(range),
311-
std::forward<sequence_t>(seq)) {}
334+
/// Call operator for range composition
335+
template <detray::ranges::range range_t>
336+
requires(!std::same_as<sequence_t, std::remove_cvref_t<sequence_t>> ||
337+
std::is_pointer_v<sequence_t>) DETRAY_HOST_DEVICE constexpr auto
338+
operator()(range_t &&rng) {
339+
using itr_t =
340+
detray::ranges::iterator_t<std::remove_reference_t<range_t>>;
341+
return detray::ranges::pick_view<itr_t, sequence_itr_t>(
342+
std::forward<range_t>(rng), m_seq);
343+
}
344+
345+
/// Copy assignment operator
346+
DETRAY_HOST_DEVICE
347+
pick &operator=(const pick &other) {
348+
base_type::operator=(other);
349+
m_seq = other.m_seq;
350+
return *this;
351+
}
352+
353+
private:
354+
sequence_t m_seq{};
312355
};
313356

314-
// deduction guides
357+
// deduction guides>
358+
DETRAY_HOST_DEVICE pick()
359+
->pick<detray::ranges::iterator_t<detray::ranges::views::empty<int>>,
360+
dvector<int>>;
361+
362+
template <detray::ranges::range sequence_t>
363+
DETRAY_HOST_DEVICE pick(sequence_t &&seq)
364+
->pick<detray::ranges::iterator_t<detray::ranges::views::empty<int>>,
365+
sequence_t>;
315366

316367
template <detray::ranges::range range_t, detray::ranges::range sequence_t>
317-
pick(range_t &&range, sequence_t &&seq)
318-
-> pick<detray::ranges::iterator_t<range_t>,
319-
detray::ranges::const_iterator_t<sequence_t>>;
368+
DETRAY_HOST_DEVICE pick(range_t &&range, sequence_t &&seq)
369+
->pick<detray::ranges::iterator_t<std::remove_reference_t<range_t>>,
370+
sequence_t>;
320371

321372
} // namespace views
322373

core/include/detray/utils/ranges/pointer.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ struct pointer : public detray::ranges::pointer_view<const value_t> {
109109
// deduction guides
110110

111111
template <typename deduced_value_t>
112-
pointer(deduced_value_t&) -> pointer<deduced_value_t>;
112+
DETRAY_HOST_DEVICE pointer(deduced_value_t&)->pointer<deduced_value_t>;
113113

114114
} // namespace views
115115

core/include/detray/utils/ranges/ranges.hpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
namespace detray::ranges {
2424

25-
/// @brief Provides c++17 detray iterators in a simplified std::ranges style,
25+
/// @brief Provides detray iterators in a simplified std::ranges style,
2626
/// meant to be used in device code.
2727
///
2828
/// @note Does make use of concepts and des not implement full ranges standard
@@ -66,8 +66,7 @@ template <class R>
6666
using sentinel_t = decltype(detray::ranges::end(std::declval<R&>()));
6767

6868
template <class R>
69-
using const_iterator_t = decltype(
70-
detray::ranges::begin(std::declval<const std::remove_reference_t<R>&>()));
69+
using const_iterator_t = decltype(detray::ranges::cbegin(std::declval<R&>()));
7170

7271
template <class R>
7372
using range_size_t = decltype(detray::ranges::size(std::declval<R&>()));
@@ -292,4 +291,16 @@ inline constexpr bool viewable_range = detray::ranges::range<R> &&
292291
view<std::remove_cvref_t<R>>);
293292
/// @}
294293

294+
/// Pipe operator for range composition
295+
///
296+
/// @param r range adaptor
297+
/// @param c closure
298+
///
299+
/// @returns composed range c(r)
300+
/// @TODO: Add concept for range adaptors, closures etc.
301+
template <detray::ranges::range R, detray::ranges::range C>
302+
auto operator|(R&& r, C&& c) {
303+
return std::forward<C>(c)(std::forward<R>(r));
304+
}
305+
295306
} // namespace detray::ranges

core/include/detray/utils/ranges/single.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ struct single : public detray::ranges::single_view<value_t> {
130130
// deduction guides
131131

132132
template <typename deduced_value_t>
133-
single(deduced_value_t) -> single<deduced_value_t>;
133+
DETRAY_HOST_DEVICE single(deduced_value_t)->single<deduced_value_t>;
134134

135135
} // namespace views
136136

core/include/detray/utils/ranges/static_join.hpp

+2-14
Original file line numberDiff line numberDiff line change
@@ -119,29 +119,17 @@ struct static_join : public ranges::static_join_view<I, range_itr_t> {
119119

120120
constexpr static_join() = default;
121121

122-
template <detray::ranges::range... ranges_t>
123-
DETRAY_HOST_DEVICE constexpr explicit static_join(
124-
const ranges_t &... ranges)
125-
: base_type(ranges...) {}
126-
127122
template <detray::ranges::range... ranges_t>
128123
DETRAY_HOST_DEVICE constexpr explicit static_join(ranges_t &&... ranges)
129124
: base_type(std::forward<ranges_t>(ranges)...) {}
130125
};
131126

132127
// deduction guides
133-
134-
template <detray::ranges::range... ranges_t>
135-
DETRAY_HOST_DEVICE static_join(const ranges_t &... ranges)
136-
->static_join<sizeof...(ranges_t),
137-
typename detray::ranges::const_iterator_t<
138-
detray::detail::first_t<ranges_t...>>>;
139-
140128
template <detray::ranges::range... ranges_t>
141129
DETRAY_HOST_DEVICE static_join(ranges_t &&... ranges)
142130
->static_join<sizeof...(ranges_t),
143-
typename detray::ranges::iterator_t<
144-
detray::detail::first_t<ranges_t...>>>;
131+
typename detray::ranges::iterator_t<detray::detail::first_t<
132+
std::remove_reference_t<ranges_t>...>>>;
145133

146134
} // namespace views
147135

0 commit comments

Comments
 (0)