• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

celerity / celerity-runtime / 11271845693

10 Oct 2024 10:04AM UTC coverage: 94.965% (-0.09%) from 95.051%
11271845693

Pull #288

github

fknorr
Add type trait to match ReductionsAndKernel parameter lists
Pull Request #288: Disambiguate `parallel_for(Integral, ...)`

3019 of 3426 branches covered (88.12%)

Branch coverage included in aggregate %.

6 of 6 new or added lines in 1 file covered. (100.0%)

7 existing lines in 2 files now uncovered.

6657 of 6763 relevant lines covered (98.43%)

1471382.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.25
/include/ranges.h
1
#pragma once
2

3
#include "sycl_wrappers.h"
4
#include "workaround.h"
5

6
namespace celerity {
7

8
// clang-format off
9
template <int Dims = 1> class range;
10
template <int Dims = 1> class id;
11
template <int Dims = 1> class nd_range;
12
template <int Dims = 1> struct subrange;
13
template <int Dims = 1> struct chunk;
14
// clang-format on
15

16
} // namespace celerity
17

18
namespace celerity::detail {
19

20
struct make_from_t {
21
} inline static constexpr make_from;
22

23
// We need a specialized storage type for coordinates to avoid generating a `size_t values[0]` array which clang interprets as dynamically-sized.
24
// By specializing on the Interface type, id<> and range<> become distinct types "all the way down", so both an id<0> and a range<0> can be included as struct
25
// members with [[no_unique_address]] within another struct and to actually overlap. This is required to ensure that 0-dimensional accessors are pointer-sized,
26
// and would otherwise be prohibited by strict-aliasing rules (because two identical pointers with the same type must point to the same object).
27
template <typename Interface, int Dims>
28
struct coordinate_storage {
29
        constexpr size_t operator[](int dimension) const {
1,346,291,604✔
30
                CELERITY_DETAIL_ASSERT_ON_HOST(dimension < Dims);
1,346,291,604✔
31
                return values[dimension];
1,346,291,604✔
32
        }
33

34
        constexpr size_t& operator[](int dimension) {
425,839,468✔
35
                CELERITY_DETAIL_ASSERT_ON_HOST(dimension < Dims);
425,839,468✔
36
                return values[dimension];
425,839,468✔
37
        }
38

39
        size_t values[Dims] = {};
40
};
41

42
template <typename Interface>
43
struct coordinate_storage<Interface, 0> {
44
        constexpr size_t operator[](int /* dimension */) const { return 0; }
×
45
        // This is UB, but also unreachable. Unfortunately we can't call __builtin_unreachable from a constexpr function.
46
        constexpr size_t& operator[](int /* dimension */) { return *static_cast<size_t*>(static_cast<void*>(this)); }
×
47
};
48

49
// We implement range and id from scratch to allow zero-dimensional structures.
50
template <typename Interface, int Dims>
51
class coordinate {
52
  public:
53
        constexpr static int dimensions = Dims;
54

55
        coordinate() = default;
44,039,617✔
56

57
        template <typename InterfaceIn, int DimsIn>
58
        constexpr coordinate(const make_from_t /* tag */, const coordinate<InterfaceIn, DimsIn>& other, const size_t default_value) {
45,010,295✔
59
                for(int d = 0; d < Dims; ++d) {
137,112,560✔
60
                        (*this)[d] = d < DimsIn ? other[d] : default_value;
92,102,546✔
61
                }
62
        }
45,010,014✔
63

64
        template <typename InterfaceIn>
65
        constexpr coordinate(const make_from_t /* tag */, const coordinate<InterfaceIn, Dims>& other) : coordinate(make_from, other, 0) {}
25,556,572✔
66

67
        template <typename... Values, typename = std::enable_if_t<sizeof...(Values) + 1 == Dims && (... && std::is_convertible_v<Values, size_t>)>>
68
        constexpr coordinate(const size_t dim_0, const Values... dim_n) : m_values{{dim_0, static_cast<size_t>(dim_n)...}} {}
33,815,552✔
69

70
        constexpr size_t get(int dimension) const { return m_values[dimension]; }
10✔
71
        constexpr size_t& operator[](int dimension) { return m_values[dimension]; }
425,845,151✔
72
        constexpr size_t operator[](int dimension) const { return m_values[dimension]; }
761,892,022✔
73

74
        friend constexpr bool operator==(const Interface& lhs, const Interface& rhs) {
29,391,145✔
75
                bool equal = true;
29,391,145✔
76
                for(int d = 0; d < Dims; ++d) {
88,395,828✔
77
                        equal &= lhs[d] == rhs[d];
59,004,684✔
78
                }
79
                return equal;
29,391,144✔
80
        }
81

82
        friend constexpr bool operator!=(const Interface& lhs, const Interface& rhs) { return !(lhs == rhs); }
1,379✔
83

84
#define CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(op)                                                                                         \
85
        friend constexpr Interface operator op(const Interface& lhs, const Interface& rhs) {                                                                       \
86
                Interface result;                                                                                                                                      \
87
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
88
                        result[d] = lhs.m_values[d] op rhs.m_values[d];                                                                                                    \
89
                }                                                                                                                                                      \
90
                return result;                                                                                                                                         \
91
        }                                                                                                                                                          \
92
        friend constexpr Interface operator op(const Interface& lhs, const size_t& rhs) {                                                                          \
93
                Interface result;                                                                                                                                      \
94
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
95
                        result[d] = lhs.m_values[d] op rhs;                                                                                                                \
96
                }                                                                                                                                                      \
97
                return result;                                                                                                                                         \
98
        }
99

100
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(+)
272,770,568✔
101
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(-)
106,018,119✔
102
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(*)
78✔
103
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(/)
99,994✔
104
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(%)
103,681✔
105
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(<<)
78✔
106
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(>>)
78✔
107
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(&)
78✔
108
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(|)
78✔
109
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(^)
26✔
110
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(&&)
898✔
111
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(||)
52!
112
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(<)
100,771,592✔
113
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(>)
78✔
114
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(<=)
69,602✔
115
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(>=)
100,772,435✔
116

117
#undef CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR
118

119
#define CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(op)                                                                                      \
120
        friend constexpr Interface& operator op(Interface& lhs, const Interface& rhs) {                                                                            \
121
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
122
                        lhs.m_values[d] op rhs.m_values[d];                                                                                                                \
123
                }                                                                                                                                                      \
124
                return lhs;                                                                                                                                            \
125
        }                                                                                                                                                          \
126
        friend constexpr Interface& operator op(Interface& lhs, const size_t& rhs) {                                                                               \
127
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
128
                        lhs.m_values[d] op rhs;                                                                                                                            \
129
                }                                                                                                                                                      \
130
                return lhs;                                                                                                                                            \
131
        }
132

133
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(+=)
640✔
134
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(-=)
640✔
135
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(*=)
20✔
136
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(/=)
20✔
137
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(%=)
20✔
138
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(<<=)
20✔
139
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(>>=)
20✔
140
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(&=)
20✔
141
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(|=)
20✔
142
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(^=)
20✔
143

144
#undef CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR
145

146
#define CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(op)                                                                                         \
147
        friend constexpr Interface operator op(const size_t& lhs, const Interface& rhs) {                                                                          \
148
                Interface result;                                                                                                                                      \
149
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
150
                        result[d] = lhs op rhs.m_values[d];                                                                                                                \
151
                }                                                                                                                                                      \
152
                return result;                                                                                                                                         \
153
        }
154

155
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(+)
26✔
156
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(-)
26✔
157
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(*)
35✔
158
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(/)
26✔
159
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(%)
26✔
160
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(<<)
26✔
161
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(>>)
26✔
162
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(&)
26✔
163
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(|)
26✔
164
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(^)
165
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(&&)
26!
166
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(||)
26!
167
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(<)
56✔
168
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(>)
26✔
169
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(<=)
26✔
170
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(>=)
56✔
171

172
#undef CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR
173

174
#define CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR(op)                                                                                              \
175
        friend constexpr Interface operator op(const Interface& rhs) {                                                                                             \
176
                Interface result;                                                                                                                                      \
177
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
178
                        result[d] = op rhs[d];                                                                                                                             \
179
                }                                                                                                                                                      \
180
                return result;                                                                                                                                         \
181
        }
182

183
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR(+)
26✔
184
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR(-)
26✔
185

186
#undef CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR
187

188
#define CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR(op)                                                                                            \
189
        friend constexpr Interface& operator op(Interface& rhs) {                                                                                                  \
190
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
191
                        op rhs[d];                                                                                                                                         \
192
                }                                                                                                                                                      \
193
                return rhs;                                                                                                                                            \
194
        }
195

196
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR(++)
20✔
197
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR(--)
20✔
198

199
#undef CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR
200

201
#define CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR(op)                                                                                           \
202
        friend constexpr Interface operator op(Interface& lhs, int) {                                                                                              \
203
                Interface result = lhs;                                                                                                                                \
204
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
205
                        lhs[d] op;                                                                                                                                         \
206
                }                                                                                                                                                      \
207
                return result;                                                                                                                                         \
208
        }
209

210
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR(++)
26✔
211
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR(--)
26✔
212

213
#undef CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR
214

215
  private:
216
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS coordinate_storage<Interface, Dims> m_values;
217
};
218

219
template <int DimsOut, typename InterfaceIn>
220
range<DimsOut> range_cast(const InterfaceIn& in);
221

222
template <int DimsOut, typename InterfaceIn>
223
id<DimsOut> id_cast(const InterfaceIn& in);
224

225
struct zeros_t {
226
} inline static constexpr zeros;
227
struct ones_t {
228
} inline static constexpr ones;
229

230
}; // namespace celerity::detail
231

232
namespace celerity {
233

234
template <int Dims>
235
class range : public detail::coordinate<range<Dims>, Dims> {
236
  private:
237
        using coordinate = detail::coordinate<range<Dims>, Dims>;
238

239
  public:
240
        constexpr range() noexcept = default;
16✔
241

242
        template <typename... Values, typename = std::enable_if_t<sizeof...(Values) + 1 == Dims>>
243
        constexpr range(const size_t dim_0, const Values... dim_n) : coordinate(dim_0, dim_n...) {}
19,585✔
244

245
        constexpr range(const detail::zeros_t /* tag */) {}
65,456✔
246

247
        constexpr range(const detail::ones_t /* tag */) {
5,820✔
248
                for(int d = 0; d < Dims; ++d) {
21,620✔
249
                        (*this)[d] = 1;
15,800✔
250
                }
251
        }
5,820✔
252

253
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
254
        range(const sycl::range<Dims>& sycl_range) {
49,824✔
255
                for(int d = 0; d < Dims; ++d) {
196,848✔
256
                        (*this)[d] = sycl_range[d];
147,024✔
257
                }
258
        }
49,824✔
259

260
        constexpr size_t size() const {
82,005✔
261
                size_t s = 1;
82,005✔
262
                for(int d = 0; d < Dims; ++d) {
300,058✔
263
                        s *= (*this)[d];
218,053✔
264
                }
265
                return s;
82,005✔
266
        }
267

268
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
269
        operator sycl::range<Dims>() const {
388✔
270
                if constexpr(Dims == 1) {
271
                        return {(*this)[0]};
211✔
272
                } else if constexpr(Dims == 2) {
273
                        return {(*this)[0], (*this)[1]};
142✔
274
                } else {
275
                        return {(*this)[0], (*this)[1], (*this)[2]};
35✔
276
                }
277
        }
278

279
  private:
280
        template <int DimsOut, typename InterfaceIn>
281
        friend range<DimsOut> detail::range_cast(const InterfaceIn& in);
282

283
        template <typename InterfaceIn, int DimsIn>
284
        constexpr range(const detail::make_from_t /* tag */, const detail::coordinate<InterfaceIn, DimsIn>& in)
1,477,258✔
285
            : coordinate(detail::make_from, in, /* default_value= */ 1) {}
1,477,258✔
286
};
287

288
range()->range<0>;
289
range(size_t)->range<1>;
290
range(size_t, size_t)->range<2>;
291
range(size_t, size_t, size_t)->range<3>;
292

293
template <int Dims>
294
class id : public detail::coordinate<id<Dims>, Dims> {
295
  private:
296
        using coordinate = detail::coordinate<id<Dims>, Dims>;
297

298
  public:
299
        constexpr id() noexcept = default;
27,049,668✔
300

301
        template <typename... Values, typename = std::enable_if_t<sizeof...(Values) + 1 == Dims>>
302
        constexpr id(const size_t dim_0, const Values... dim_n) : coordinate(dim_0, dim_n...) {}
33,795,961✔
303

304
        constexpr id(const range<Dims>& range) : coordinate(detail::make_from, range) {}
25,556,593✔
305

306
        constexpr id(const detail::zeros_t /* tag */) {}
3,801✔
307

308
        constexpr id(const detail::ones_t /* tag */) {
140✔
309
                for(int d = 0; d < Dims; ++d) {
554✔
310
                        (*this)[d] = 1;
414✔
311
                }
312
        }
140✔
313

314
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
315
        id(const sycl::id<Dims>& sycl_id) {
16,904,718✔
316
                for(int d = 0; d < Dims; ++d) {
50,790,075✔
317
                        (*this)[d] = sycl_id[d];
33,885,357✔
318
                }
319
        }
16,904,718✔
320

321
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
322
        operator sycl::id<Dims>() const {
132✔
323
                if constexpr(Dims == 1) {
324
                        return {(*this)[0]};
132✔
325
                } else if constexpr(Dims == 2) {
326
                        return {(*this)[0], (*this)[1]};
×
327
                } else {
UNCOV
328
                        return {(*this)[0], (*this)[1], (*this)[2]};
×
329
                }
330
        }
331

332
  private:
333
        template <int DimsOut, typename InterfaceIn>
334
        friend id<DimsOut> detail::id_cast(const InterfaceIn& in);
335

336
        template <typename InterfaceIn, int DimsIn>
337
        constexpr id(const detail::make_from_t /* tag */, const detail::coordinate<InterfaceIn, DimsIn>& in)
17,976,471✔
338
            : coordinate(detail::make_from, in, /* default_value= */ 0) {}
17,976,471✔
339
};
340

341
id()->id<0>;
342
id(size_t)->id<1>;
343
id(size_t, size_t)->id<2>;
344
id(size_t, size_t, size_t)->id<3>;
345

346
// Celerity nd_range does not deprecate kernel offsets since we can support them at no additional cost in the distributed model.
347
template <int Dims>
348
class nd_range {
349
  public:
350
        template <int D = Dims, typename = std::enable_if_t<D == 0>>
351
        constexpr nd_range() noexcept {}
1✔
352

353
#pragma GCC diagnostic push
354
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
355
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
356
        nd_range(const sycl::nd_range<Dims>& s_range)
357
            : m_global_range(s_range.get_global_range()), m_local_range(s_range.get_local_range()), m_offset(s_range.get_offset()) {}
358
#pragma GCC diagnostic pop
359

360
        nd_range(const range<Dims>& global_range, const range<Dims>& local_range, const id<Dims>& offset = {})
54✔
361
            : m_global_range(global_range), m_local_range(local_range), m_offset(offset) {
54✔
362
#ifndef __SYCL_DEVICE_ONLY__
363
                for(int d = 0; d < Dims; ++d) {
146✔
364
                        if(local_range[d] == 0 || global_range[d] % local_range[d] != 0) { throw std::invalid_argument("global_range is not divisible by local_range"); }
98✔
365
                }
366
#endif
367
        }
48✔
368

369
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
370
        operator sycl::nd_range<Dims>() const {
371
                return sycl::nd_range<Dims>{m_global_range, m_local_range, m_offset};
372
        }
373

374
        const range<Dims>& get_global_range() const { return m_global_range; }
49✔
375
        const range<Dims>& get_local_range() const { return m_local_range; }
49✔
376
        const range<Dims>& get_group_range() const { return m_global_range / m_local_range; }
377
        const id<Dims>& get_offset() const { return m_offset; }
49✔
378

379
        friend bool operator==(const nd_range& lhs, const nd_range& rhs) {
380
                return lhs.m_global_range == rhs.m_global_range && lhs.m_local_range == rhs.m_local_range && lhs.m_offset == rhs.m_offset;
381
        }
382

383
        friend bool operator!=(const nd_range& lhs, const nd_range& rhs) { return !(lhs == rhs); }
384

385
  private:
386
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS range<Dims> m_global_range;
387
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS range<Dims> m_local_range;
388
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS id<Dims> m_offset;
389
};
390

391
// Non-templated deduction guides allow construction of nd_range from range initializer lists like so: nd_range{{1, 2}, {3, 4}}
392
nd_range(range<1> global_range, range<1> local_range, id<1> offset)->nd_range<1>;
393
nd_range(range<1> global_range, range<1> local_range)->nd_range<1>;
394
nd_range(range<2> global_range, range<2> local_range, id<2> offset)->nd_range<2>;
395
nd_range(range<2> global_range, range<2> local_range)->nd_range<2>;
396
nd_range(range<3> global_range, range<3> local_range, id<3> offset)->nd_range<3>;
397
nd_range(range<3> global_range, range<3> local_range)->nd_range<3>;
398

399
} // namespace celerity
400

401
namespace celerity {
402
namespace detail {
403

404
        template <int TargetDims, typename Target, int SubscriptDim = 0>
405
        class subscript_proxy;
406

407
        template <int TargetDims, typename Target, int SubscriptDim>
408
        inline decltype(auto) subscript(Target& tgt, id<TargetDims> id, const size_t index) {
916✔
409
                static_assert(SubscriptDim < TargetDims);
410
                id[SubscriptDim] = index;
916✔
411
                if constexpr(SubscriptDim == TargetDims - 1) {
412
                        return tgt[std::as_const(id)];
625✔
413
                } else {
414
                        return subscript_proxy<TargetDims, Target, SubscriptDim + 1>{tgt, id};
291✔
415
                }
416
        }
417

418
        template <int TargetDims, typename Target>
419
        inline decltype(auto) subscript(Target& tgt, const size_t index) {
625✔
420
                return subscript<TargetDims, Target, 0>(tgt, id<TargetDims>{}, index);
1,102✔
421
        }
422

423
        template <int TargetDims, typename Target, int SubscriptDim>
424
        class subscript_proxy {
425
          public:
426
                subscript_proxy(Target& tgt, const id<TargetDims> id) : m_tgt(tgt), m_id(id) {}
291✔
427

428
                inline decltype(auto) operator[](const size_t index) const { //
291✔
429
                        return subscript<TargetDims, Target, SubscriptDim>(m_tgt, m_id, index);
291✔
430
                }
431

432
          private:
433
                Target& m_tgt;
434
                id<TargetDims> m_id{};
435
        };
436

437
        inline size_t get_linear_index(const range<0>& /* range */, const id<0>& /* index */) { return 0; }
105✔
438

439
        inline size_t get_linear_index(const range<1>& range, const id<1>& index) { return index[0]; }
4,942✔
440

441
        inline size_t get_linear_index(const range<2>& range, const id<2>& index) { return index[0] * range[1] + index[1]; }
50,355,911✔
442

443
        inline size_t get_linear_index(const range<3>& range, const id<3>& index) { return index[0] * range[1] * range[2] + index[1] * range[2] + index[2]; }
1,214,888✔
444

445
#define CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(name, coord, op)                                                                                                \
446
        template <int Dims>                                                                                                                                        \
447
        coord<Dims> name(const coord<Dims>& a, const coord<Dims>& b) {                                                                                             \
448
                auto result = a;                                                                                                                                       \
449
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
450
                        result[d] = op(result[d], b[d]);                                                                                                                   \
451
                }                                                                                                                                                      \
452
                return result;                                                                                                                                         \
453
        }
454

455
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(range_min, range, std::min)
456
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(range_max, range, std::max)
457
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(id_min, id, std::min)
1,300,057✔
458
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(id_max, id, std::max)
1,300,051✔
459

460
#undef CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN
461

462
        template <typename Interface, int Dims>
463
        bool all_true(const coordinate<Interface, Dims>& bools) {
50,403,418✔
464
                for(int d = 0; d < Dims; ++d) {
151,274,829✔
465
                        CELERITY_DETAIL_ASSERT_ON_HOST(bools[d] == 0 || bools[d] == 1);
100,871,715✔
466
                        if(bools[d] == 0) return false;
100,871,715✔
467
                }
468
                return true;
50,403,114✔
469
        }
470

471
} // namespace detail
472

473
template <int Dims>
474
struct chunk {
475
        static constexpr int dimensions = Dims;
476

477
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS id<Dims> offset;
478
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS celerity::range<Dims> range = detail::zeros;
479
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS celerity::range<Dims> global_size = detail::zeros;
480

481
        constexpr chunk() = default;
4✔
482

483
        constexpr chunk(const id<Dims>& offset, const celerity::range<Dims>& range, const celerity::range<Dims>& global_size)
114,323✔
484
            : offset(offset), range(range), global_size(global_size) {}
114,323✔
485

486
        friend bool operator==(const chunk& lhs, const chunk& rhs) {
487
                return lhs.offset == rhs.offset && lhs.range == rhs.range && lhs.global_size == rhs.global_size;
488
        }
489
        friend bool operator!=(const chunk& lhs, const chunk& rhs) { return !operator==(lhs, rhs); }
490
};
491

492
template <int Dims>
493
struct subrange {
494
        static constexpr int dimensions = Dims;
495

496
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS id<Dims> offset;
497
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS celerity::range<Dims> range = detail::zeros;
498

499
        constexpr subrange() = default;
28,947✔
500
        constexpr subrange(const id<Dims>& offset, const celerity::range<Dims>& range) : offset(offset), range(range) {}
375,557✔
501
        constexpr subrange(const chunk<Dims>& other) : offset(other.offset), range(other.range) {}
40,163✔
502

503
        friend bool operator==(const subrange& lhs, const subrange& rhs) { return lhs.offset == rhs.offset && lhs.range == rhs.range; }
1,126!
504
        friend bool operator!=(const subrange& lhs, const subrange& rhs) { return !operator==(lhs, rhs); }
505
};
506

507
} // namespace celerity
508

509
namespace celerity::detail {
510

511
/// Returns the smallest dimensionality that the range can be `range_cast` to.
512
template <int Dims>
513
int get_effective_dims(const range<Dims>& range) {
738,494✔
514
        for(int dims = Dims; dims > 0; --dims) {
1,649,689✔
515
                if(range[dims - 1] > 1) return dims;
1,318,562✔
516
        }
517
        return 0;
331,127✔
518
}
519

520
template <int DimsOut, typename InterfaceIn>
521
range<DimsOut> range_cast(const InterfaceIn& in) {
1,477,277✔
522
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(in) <= DimsOut);
1,477,277✔
523
        return range<DimsOut>(make_from, in);
1,477,257✔
524
}
525

526
/// Returns the smallest dimensionality that the id can be `id_cast` to.
527
template <int Dims>
528
int get_effective_dims(const id<Dims>& id) {
19,117,826✔
529
        for(int dims = Dims; dims > 0; --dims) {
20,293,363✔
530
                if(id[dims - 1] > 0) { return dims; }
19,958,473✔
531
        }
532
        return 0;
334,890✔
533
}
534

535
template <int DimsOut, typename InterfaceIn>
536
id<DimsOut> id_cast(const InterfaceIn& in) {
17,976,478✔
537
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(in) <= DimsOut);
17,976,478✔
538
        return id<DimsOut>(make_from, in);
17,976,472✔
539
}
540

541
/// Returns the smallest dimensionality that the chunk can be `chunk_cast` to.
542
template <int Dims>
543
int get_effective_dims(const chunk<Dims>& ck) {
46,784✔
544
        return std::max({get_effective_dims(ck.offset), get_effective_dims(ck.range), get_effective_dims(ck.global_size)});
46,784✔
545
}
546

547
/// Returns the smallest dimensionality that the subrange can be `subrange_cast` to.
548
template <int Dims>
549
int get_effective_dims(const subrange<Dims>& sr) {
205,530✔
550
        return std::max(get_effective_dims(sr.offset), get_effective_dims(sr.range));
205,530✔
551
}
552

553
template <int Dims, int OtherDims>
554
chunk<Dims> chunk_cast(const chunk<OtherDims>& other) {
46,782✔
555
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(other) <= Dims);
46,782✔
556
        return chunk{detail::id_cast<Dims>(other.offset), detail::range_cast<Dims>(other.range), detail::range_cast<Dims>(other.global_size)};
46,782✔
557
}
558

559
template <int Dims, int OtherDims>
560
subrange<Dims> subrange_cast(const subrange<OtherDims>& other) {
206,440✔
561
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(other) <= Dims);
206,440✔
562
        return subrange{detail::id_cast<Dims>(other.offset), detail::range_cast<Dims>(other.range)};
206,428✔
563
}
564

565
} // namespace celerity::detail
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc