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

celerity / celerity-runtime / 12009901531

25 Nov 2024 12:20PM UTC coverage: 94.92% (+0.009%) from 94.911%
12009901531

push

github

fknorr
Add missing includes and consistently order them

We can't add the misc-include-cleaner lint because it causes too many
false positives with "interface headers" such as sycl.hpp.

3190 of 3626 branches covered (87.98%)

Branch coverage included in aggregate %.

7049 of 7161 relevant lines covered (98.44%)

1242183.17 hits per line

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

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

3
#include "workaround.h"
4

5
#include <cstddef>
6
#include <stdexcept>
7
#include <type_traits>
8

9
#include <sycl/sycl.hpp>
10

11

12
namespace celerity {
13

14
// clang-format off
15
template <int Dims = 1> class range;
16
template <int Dims = 1> class id;
17
template <int Dims = 1> class nd_range;
18
template <int Dims = 1> struct subrange;
19
template <int Dims = 1> struct chunk;
20
// clang-format on
21

22
} // namespace celerity
23

24
namespace celerity::detail {
25

26
struct make_from_t {
27
} inline static constexpr make_from;
28

29
// We need a specialized storage type for coordinates to avoid generating a `size_t values[0]` array which clang interprets as dynamically-sized.
30
// 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
31
// members with [[no_unique_address]] within another struct and to actually overlap. This is required to ensure that 0-dimensional accessors are pointer-sized,
32
// and would otherwise be prohibited by strict-aliasing rules (because two identical pointers with the same type must point to the same object).
33
template <typename Interface, int Dims>
34
struct coordinate_storage {
35
        constexpr size_t operator[](int dimension) const {
1,240,729,504✔
36
                CELERITY_DETAIL_CONSTEXPR_ASSERT_ON_HOST(dimension < Dims);
1,240,729,504!
37
                return values[dimension];
1,240,729,504✔
38
        }
39

40
        constexpr size_t& operator[](int dimension) {
331,780,957✔
41
                CELERITY_DETAIL_CONSTEXPR_ASSERT_ON_HOST(dimension < Dims);
331,780,957!
42
                return values[dimension];
331,780,957✔
43
        }
44

45
        size_t values[Dims] = {};
46
};
47

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

55
// We implement range and id from scratch to allow zero-dimensional structures.
56
template <typename Interface, int Dims>
57
class coordinate {
58
  public:
59
        constexpr static int dimensions = Dims;
60

61
        coordinate() = default;
46,344,282✔
62

63
        template <typename InterfaceIn, int DimsIn>
64
        constexpr coordinate(const make_from_t /* tag */, const coordinate<InterfaceIn, DimsIn>& other, const size_t default_value) {
20,050,222✔
65
                for(int d = 0; d < Dims; ++d) {
62,354,150✔
66
                        (*this)[d] = d < DimsIn ? other[d] : default_value;
42,303,944✔
67
                }
68
        }
20,050,206✔
69

70
        template <typename InterfaceIn>
71
        constexpr coordinate(const make_from_t /* tag */, const coordinate<InterfaceIn, Dims>& other) : coordinate(make_from, other, 0) {}
435,233✔
72

73
        template <typename... Values, typename = std::enable_if_t<sizeof...(Values) + 1 == Dims && (... && std::is_convertible_v<Values, size_t>)>>
74
        constexpr coordinate(const size_t dim_0, const Values... dim_n) : m_values{{dim_0, static_cast<size_t>(dim_n)...}} {}
33,841,336✔
75

76
        constexpr size_t get(int dimension) const { return m_values[dimension]; }
10✔
77
        constexpr size_t& operator[](int dimension) { return m_values[dimension]; }
331,780,991✔
78
        constexpr size_t operator[](int dimension) const { return m_values[dimension]; }
755,852,128✔
79

80
        friend constexpr bool operator==(const Interface& lhs, const Interface& rhs) {
30,098,522✔
81
                bool equal = true;
30,098,522✔
82
                for(int d = 0; d < Dims; ++d) {
90,421,744✔
83
                        equal &= lhs[d] == rhs[d];
60,323,227✔
84
                }
85
                return equal;
30,098,517✔
86
        }
87

88
        friend constexpr bool operator!=(const Interface& lhs, const Interface& rhs) { return !(lhs == rhs); }
1,715✔
89

90
#define CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(op)                                                                                         \
91
        friend constexpr Interface operator op(const Interface& lhs, const Interface& rhs) {                                                                       \
92
                Interface result;                                                                                                                                      \
93
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
94
                        result[d] = lhs.m_values[d] op rhs.m_values[d];                                                                                                    \
95
                }                                                                                                                                                      \
96
                return result;                                                                                                                                         \
97
        }                                                                                                                                                          \
98
        friend constexpr Interface operator op(const Interface& lhs, const size_t& rhs) {                                                                          \
99
                Interface result;                                                                                                                                      \
100
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
101
                        result[d] = lhs.m_values[d] op rhs;                                                                                                                \
102
                }                                                                                                                                                      \
103
                return result;                                                                                                                                         \
104
        }
105

106
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(+)
172,227,837✔
107
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(-)
106,621,344✔
108
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(*)
78✔
109
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(/)
100,012✔
110
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(%)
104,746✔
111
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(<<)
78✔
112
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(>>)
78✔
113
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(&)
78✔
114
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(|)
78✔
115
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(^)
26✔
116
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(&&)
898✔
117
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(||)
52!
118
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(<)
100,771,952✔
119
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(>)
78✔
120
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(<=)
76,974✔
121
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR(>=)
100,772,795✔
122

123
#undef CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_LHS_OPERATOR
124

125
#define CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(op)                                                                                      \
126
        friend constexpr Interface& operator op(Interface & lhs, const Interface & rhs) {                                                                          \
127
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
128
                        lhs.m_values[d] op rhs.m_values[d];                                                                                                                \
129
                }                                                                                                                                                      \
130
                return lhs;                                                                                                                                            \
131
        }                                                                                                                                                          \
132
        friend constexpr Interface& operator op(Interface & lhs, const size_t & rhs) {                                                                             \
133
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
134
                        lhs.m_values[d] op rhs;                                                                                                                            \
135
                }                                                                                                                                                      \
136
                return lhs;                                                                                                                                            \
137
        }
138

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
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(%=)
20✔
144
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(<<=)
20✔
145
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(>>=)
20✔
146
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(&=)
20✔
147
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(|=)
20✔
148
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR(^=)
20✔
149

150
#undef CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_INPLACE_LHS_OPERATOR
151

152
#define CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(op)                                                                                         \
153
        friend constexpr Interface operator op(const size_t& lhs, const Interface& rhs) {                                                                          \
154
                Interface result;                                                                                                                                      \
155
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
156
                        result[d] = lhs op rhs.m_values[d];                                                                                                                \
157
                }                                                                                                                                                      \
158
                return result;                                                                                                                                         \
159
        }
160

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(*)
35✔
164
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(/)
26✔
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(>>)
26✔
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(^)
171
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(&&)
26!
172
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(||)
26!
173
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(<)
56✔
174
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(>)
26✔
175
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(<=)
26✔
176
        CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR(>=)
56✔
177

178
#undef CELERITY_DETAIL_DEFINE_COORDINATE_BINARY_COPY_RHS_OPERATOR
179

180
#define CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR(op)                                                                                              \
181
        friend constexpr Interface operator op(const Interface& rhs) {                                                                                             \
182
                Interface result;                                                                                                                                      \
183
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
184
                        result[d] = op rhs[d];                                                                                                                             \
185
                }                                                                                                                                                      \
186
                return result;                                                                                                                                         \
187
        }
188

189
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR(+)
26✔
190
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR(-)
26✔
191

192
#undef CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_COPY_OPERATOR
193

194
#define CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR(op)                                                                                            \
195
        friend constexpr Interface& operator op(Interface & rhs) {                                                                                                 \
196
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
197
                        op rhs[d];                                                                                                                                         \
198
                }                                                                                                                                                      \
199
                return rhs;                                                                                                                                            \
200
        }
201

202
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR(++)
20✔
203
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR(--)
20✔
204

205
#undef CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_PREFIX_OPERATOR
206

207
#define CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR(op)                                                                                           \
208
        friend constexpr Interface operator op(Interface& lhs, int) {                                                                                              \
209
                Interface result = lhs;                                                                                                                                \
210
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
211
                        lhs[d] op;                                                                                                                                         \
212
                }                                                                                                                                                      \
213
                return result;                                                                                                                                         \
214
        }
215

216
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR(++)
26✔
217
        CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR(--)
26✔
218

219
#undef CELERITY_DETAIL_DEFINE_COORDINATE_UNARY_POSTFIX_OPERATOR
220

221
  private:
222
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS coordinate_storage<Interface, Dims> m_values;
223
};
224

225
template <int DimsOut, typename InterfaceIn>
226
range<DimsOut> range_cast(const InterfaceIn& in);
227

228
template <int DimsOut, typename InterfaceIn>
229
id<DimsOut> id_cast(const InterfaceIn& in);
230

231
struct zeros_t {
232
} inline static constexpr zeros;
233
struct ones_t {
234
} inline static constexpr ones;
235

236
} // namespace celerity::detail
237

238
namespace celerity {
239

240
template <int Dims>
241
class range : public detail::coordinate<range<Dims>, Dims> {
242
  private:
243
        using coordinate = detail::coordinate<range<Dims>, Dims>;
244

245
  public:
246
        constexpr range() noexcept = default;
16✔
247

248
        template <typename... Values, typename = std::enable_if_t<sizeof...(Values) + 1 == Dims>>
249
        constexpr range(const size_t dim_0, const Values... dim_n) : coordinate(dim_0, dim_n...) {}
22,809✔
250

251
        constexpr range(const detail::zeros_t /* tag */) {}
30,956✔
252

253
        constexpr range(const detail::ones_t /* tag */) {
3,947✔
254
                for(int d = 0; d < Dims; ++d) {
14,016✔
255
                        (*this)[d] = 1;
10,069✔
256
                }
257
        }
3,947✔
258

259
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
260
        range(const sycl::range<Dims>& sycl_range) {
49,824✔
261
                for(int d = 0; d < Dims; ++d) {
196,848✔
262
                        (*this)[d] = sycl_range[d];
147,024✔
263
                }
264
        }
49,824✔
265

266
        constexpr size_t size() const {
191,921✔
267
                size_t s = 1;
191,921✔
268
                for(int d = 0; d < Dims; ++d) {
611,809✔
269
                        s *= (*this)[d];
419,888✔
270
                }
271
                return s;
191,921✔
272
        }
273

274
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
275
        operator sycl::range<Dims>() const {
450✔
276
                if constexpr(Dims == 1) {
277
                        return {(*this)[0]};
273✔
278
                } else if constexpr(Dims == 2) {
279
                        return {(*this)[0], (*this)[1]};
142✔
280
                } else {
281
                        return {(*this)[0], (*this)[1], (*this)[2]};
35✔
282
                }
283
        }
284

285
  private:
286
        template <int DimsOut, typename InterfaceIn>
287
        friend range<DimsOut> detail::range_cast(const InterfaceIn& in);
288

289
        template <typename InterfaceIn, int DimsIn>
290
        constexpr range(const detail::make_from_t /* tag */, const detail::coordinate<InterfaceIn, DimsIn>& in)
1,642,639✔
291
            : coordinate(detail::make_from, in, /* default_value= */ 1) {}
1,642,639✔
292
};
293

294
range() -> range<0>;
295
range(size_t) -> range<1>;
296
range(size_t, size_t) -> range<2>;
297
range(size_t, size_t, size_t) -> range<3>;
298

299
template <int Dims>
300
class id : public detail::coordinate<id<Dims>, Dims> {
301
  private:
302
        using coordinate = detail::coordinate<id<Dims>, Dims>;
303

304
  public:
305
        constexpr id() noexcept = default;
29,375,286✔
306

307
        template <typename... Values, typename = std::enable_if_t<sizeof...(Values) + 1 == Dims>>
308
        constexpr id(const size_t dim_0, const Values... dim_n) : coordinate(dim_0, dim_n...) {}
33,818,527✔
309

310
        constexpr id(const range<Dims>& range) : coordinate(detail::make_from, range) {}
435,233✔
311

312
        constexpr id(const detail::zeros_t /* tag */) {}
4,804✔
313

314
        constexpr id(const detail::ones_t /* tag */) {
156✔
315
                for(int d = 0; d < Dims; ++d) {
618✔
316
                        (*this)[d] = 1;
462✔
317
                }
318
        }
156✔
319

320
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
321
        id(const sycl::id<Dims>& sycl_id) {
16,904,786✔
322
                for(int d = 0; d < Dims; ++d) {
50,790,211✔
323
                        (*this)[d] = sycl_id[d];
33,885,425✔
324
                }
325
        }
16,904,786✔
326

327
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
328
        operator sycl::id<Dims>() const {
132✔
329
                if constexpr(Dims == 1) {
330
                        return {(*this)[0]};
132✔
331
                } else if constexpr(Dims == 2) {
332
                        return {(*this)[0], (*this)[1]};
×
333
                } else {
334
                        return {(*this)[0], (*this)[1], (*this)[2]};
×
335
                }
336
        }
337

338
  private:
339
        template <int DimsOut, typename InterfaceIn>
340
        friend id<DimsOut> detail::id_cast(const InterfaceIn& in);
341

342
        template <typename InterfaceIn, int DimsIn>
343
        constexpr id(const detail::make_from_t /* tag */, const detail::coordinate<InterfaceIn, DimsIn>& in)
17,972,348✔
344
            : coordinate(detail::make_from, in, /* default_value= */ 0) {}
17,972,348✔
345
};
346

347
id() -> id<0>;
348
id(size_t) -> id<1>;
349
id(size_t, size_t) -> id<2>;
350
id(size_t, size_t, size_t) -> id<3>;
351

352
// Celerity nd_range does not deprecate kernel offsets since we can support them at no additional cost in the distributed model.
353
template <int Dims>
354
class nd_range {
355
  public:
356
        template <int D = Dims, typename = std::enable_if_t<D == 0>>
357
        constexpr nd_range() noexcept {}
1✔
358

359
#pragma GCC diagnostic push
360
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
361
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
362
        nd_range(const sycl::nd_range<Dims>& s_range)
363
            : m_global_range(s_range.get_global_range()), m_local_range(s_range.get_local_range()), m_offset(s_range.get_offset()) {}
364
#pragma GCC diagnostic pop
365

366
        nd_range(const range<Dims>& global_range, const range<Dims>& local_range, const id<Dims>& offset = {})
53✔
367
            : m_global_range(global_range), m_local_range(local_range), m_offset(offset) {
53✔
368
                CELERITY_DETAIL_IF_RUNTIME_TARGET_HOST({
144✔
369
                        for(int d = 0; d < Dims; ++d) {
370
                                if(local_range[d] == 0 || global_range[d] % local_range[d] != 0) {
371
                                        throw std::invalid_argument("global_range is not divisible by local_range");
372
                                }
373
                        }
374
                })
375
        }
47✔
376

377
        template <int D = Dims, typename = std::enable_if_t<D >= 1 && D <= 3>>
378
        operator sycl::nd_range<Dims>() const {
379
                return sycl::nd_range<Dims>{m_global_range, m_local_range, m_offset};
380
        }
381

382
        const range<Dims>& get_global_range() const { return m_global_range; }
48✔
383
        const range<Dims>& get_local_range() const { return m_local_range; }
48✔
384
        const range<Dims>& get_group_range() const { return m_global_range / m_local_range; }
385
        const id<Dims>& get_offset() const { return m_offset; }
48✔
386

387
        friend bool operator==(const nd_range& lhs, const nd_range& rhs) {
388
                return lhs.m_global_range == rhs.m_global_range && lhs.m_local_range == rhs.m_local_range && lhs.m_offset == rhs.m_offset;
389
        }
390

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

393
  private:
394
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS range<Dims> m_global_range;
395
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS range<Dims> m_local_range;
396
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS id<Dims> m_offset;
397
};
398

399
// Non-templated deduction guides allow construction of nd_range from range initializer lists like so: nd_range{{1, 2}, {3, 4}}
400
nd_range(range<1> global_range, range<1> local_range, id<1> offset) -> nd_range<1>;
401
nd_range(range<1> global_range, range<1> local_range) -> nd_range<1>;
402
nd_range(range<2> global_range, range<2> local_range, id<2> offset) -> nd_range<2>;
403
nd_range(range<2> global_range, range<2> local_range) -> nd_range<2>;
404
nd_range(range<3> global_range, range<3> local_range, id<3> offset) -> nd_range<3>;
405
nd_range(range<3> global_range, range<3> local_range) -> nd_range<3>;
406

407
} // namespace celerity
408

409
namespace celerity {
410
namespace detail {
411

412
        template <int TargetDims, typename Target, int SubscriptDim = 0>
413
        class subscript_proxy;
414

415
        template <int TargetDims, typename Target, int SubscriptDim>
416
        inline decltype(auto) subscript(Target& tgt, id<TargetDims> id, const size_t index) {
1,153✔
417
                static_assert(SubscriptDim < TargetDims);
418
                id[SubscriptDim] = index;
1,153✔
419
                if constexpr(SubscriptDim == TargetDims - 1) {
420
                        return tgt[std::as_const(id)];
862✔
421
                } else {
422
                        return subscript_proxy<TargetDims, Target, SubscriptDim + 1>{tgt, id};
291✔
423
                }
424
        }
425

426
        template <int TargetDims, typename Target>
427
        inline decltype(auto) subscript(Target& tgt, const size_t index) {
862✔
428
                return subscript<TargetDims, Target, 0>(tgt, id<TargetDims>{}, index);
1,339✔
429
        }
430

431
        template <int TargetDims, typename Target, int SubscriptDim>
432
        class subscript_proxy {
433
          public:
434
                subscript_proxy(Target& tgt, const id<TargetDims> id) : m_tgt(tgt), m_id(id) {}
291✔
435

436
                inline decltype(auto) operator[](const size_t index) const { //
291✔
437
                        return subscript<TargetDims, Target, SubscriptDim>(m_tgt, m_id, index);
291✔
438
                }
439

440
          private:
441
                Target& m_tgt;
442
                id<TargetDims> m_id{};
443
        };
444

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

447
        inline size_t get_linear_index(const range<1>& range, const id<1>& index) { return index[0]; }
5,179✔
448

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

451
        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,216,730✔
452

453
#define CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(name, coord, op)                                                                                                \
454
        template <int Dims>                                                                                                                                        \
455
        coord<Dims> name(const coord<Dims>& a, const coord<Dims>& b) {                                                                                             \
456
                auto result = a;                                                                                                                                       \
457
                for(int d = 0; d < Dims; ++d) {                                                                                                                        \
458
                        result[d] = op(result[d], b[d]);                                                                                                                   \
459
                }                                                                                                                                                      \
460
                return result;                                                                                                                                         \
461
        }
462

463
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(range_min, range, std::min)
464
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(range_max, range, std::max)
465
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(id_min, id, std::min)
2,258,245✔
466
        CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN(id_max, id, std::max)
2,258,257✔
467

468
#undef CELERITY_DETAIL_MAKE_COMPONENT_WISE_FN
469

470
        template <typename Interface, int Dims>
471
        bool all_true(const coordinate<Interface, Dims>& bools) {
50,405,501✔
472
                for(int d = 0; d < Dims; ++d) {
151,282,681✔
473
                        CELERITY_DETAIL_ASSERT_ON_HOST(bools[d] == 0 || bools[d] == 1);
100,877,484✔
474
                        if(bools[d] == 0) return false;
100,877,484✔
475
                }
476
                return true;
50,405,197✔
477
        }
478

479
} // namespace detail
480

481
template <int Dims>
482
struct chunk {
483
        static constexpr int dimensions = Dims;
484

485
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS id<Dims> offset;
486
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS celerity::range<Dims> range = detail::zeros;
487
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS celerity::range<Dims> global_size = detail::zeros;
488

489
        constexpr chunk() = default;
4✔
490

491
        constexpr chunk(const id<Dims>& offset, const celerity::range<Dims>& range, const celerity::range<Dims>& global_size)
110,192✔
492
            : offset(offset), range(range), global_size(global_size) {}
110,192✔
493

494
        friend bool operator==(const chunk& lhs, const chunk& rhs) {
495
                return lhs.offset == rhs.offset && lhs.range == rhs.range && lhs.global_size == rhs.global_size;
496
        }
497
        friend bool operator!=(const chunk& lhs, const chunk& rhs) { return !operator==(lhs, rhs); }
498
};
499

500
template <int Dims>
501
struct subrange {
502
        static constexpr int dimensions = Dims;
503

504
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS id<Dims> offset;
505
        CELERITY_DETAIL_NO_UNIQUE_ADDRESS celerity::range<Dims> range = detail::zeros;
506

507
        constexpr subrange() = default;
8,056✔
508
        constexpr subrange(const id<Dims>& offset, const celerity::range<Dims>& range) : offset(offset), range(range) {}
404,898✔
509
        constexpr subrange(const chunk<Dims>& other) : offset(other.offset), range(other.range) {}
52,721✔
510

511
        friend bool operator==(const subrange& lhs, const subrange& rhs) { return lhs.offset == rhs.offset && lhs.range == rhs.range; }
1,128!
512
        friend bool operator!=(const subrange& lhs, const subrange& rhs) { return !operator==(lhs, rhs); }
513
};
514

515
} // namespace celerity
516

517
namespace celerity::detail {
518

519
/// Returns the smallest dimensionality that the range can be `range_cast` to.
520
template <int Dims>
521
int get_effective_dims(const range<Dims>& range) {
727,176✔
522
        for(int dims = Dims; dims > 0; --dims) {
1,481,228✔
523
                if(range[dims - 1] > 1) return dims;
1,238,294✔
524
        }
525
        return 0;
242,934✔
526
}
527

528
template <int DimsOut, typename InterfaceIn>
529
range<DimsOut> range_cast(const InterfaceIn& in) {
1,642,641✔
530
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(in) <= DimsOut);
1,642,641✔
531
        return range<DimsOut>(make_from, in);
1,642,639✔
532
}
533

534
/// Returns the smallest dimensionality that the id can be `id_cast` to.
535
template <int Dims>
536
int get_effective_dims(const id<Dims>& id) {
19,278,736✔
537
        for(int dims = Dims; dims > 0; --dims) {
20,337,969✔
538
                if(id[dims - 1] > 0) { return dims; }
20,077,408✔
539
        }
540
        return 0;
260,561✔
541
}
542

543
template <int DimsOut, typename InterfaceIn>
544
id<DimsOut> id_cast(const InterfaceIn& in) {
17,972,349✔
545
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(in) <= DimsOut);
17,972,349✔
546
        return id<DimsOut>(make_from, in);
17,972,348✔
547
}
548

549
/// Returns the smallest dimensionality that the chunk can be `chunk_cast` to.
550
template <int Dims>
551
int get_effective_dims(const chunk<Dims>& ck) {
45,110✔
552
        return std::max({get_effective_dims(ck.offset), get_effective_dims(ck.range), get_effective_dims(ck.global_size)});
45,110✔
553
}
554

555
/// Returns the smallest dimensionality that the subrange can be `subrange_cast` to.
556
template <int Dims>
557
int get_effective_dims(const subrange<Dims>& sr) {
202,734✔
558
        return std::max(get_effective_dims(sr.offset), get_effective_dims(sr.range));
202,734✔
559
}
560

561
template <int Dims, int OtherDims>
562
chunk<Dims> chunk_cast(const chunk<OtherDims>& other) {
45,111✔
563
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(other) <= Dims);
45,111✔
564
        return chunk{detail::id_cast<Dims>(other.offset), detail::range_cast<Dims>(other.range), detail::range_cast<Dims>(other.global_size)};
45,110✔
565
}
566

567
template <int Dims, int OtherDims>
568
subrange<Dims> subrange_cast(const subrange<OtherDims>& other) {
203,612✔
569
        CELERITY_DETAIL_ASSERT_ON_HOST(get_effective_dims(other) <= Dims);
203,612✔
570
        return subrange{detail::id_cast<Dims>(other.offset), detail::range_cast<Dims>(other.range)};
203,611✔
571
}
572

573
} // 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

© 2026 Coveralls, Inc