File indexing completed on 2026-11-04 09:58:26
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <cstddef>
0010 #include <type_traits>
0011 #include <utility>
0012
0013 #include "corecel/Macros.hh"
0014 #include "corecel/Types.hh"
0015 #include "corecel/data/Ldg.hh"
0016
0017 #if !CELER_DEVICE_COMPILE
0018 # include <ostream>
0019
0020 # include "corecel/io/StreamableContainer.hh"
0021 #endif
0022
0023 namespace celeritas
0024 {
0025
0026 template<class T, std::size_t>
0027 class Span;
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template<class T, std::size_t N>
0047 class Array
0048 {
0049 static_assert(N > 0);
0050
0051 public:
0052
0053
0054 using value_type = T;
0055 using size_type = ::celeritas::size_type;
0056 using pointer = value_type*;
0057 using const_pointer = value_type const*;
0058 using reference = value_type&;
0059 using const_reference = value_type const&;
0060 using iterator = pointer;
0061 using const_iterator = const_pointer;
0062
0063 using CArrayConstRef = T const (&)[N];
0064
0065
0066 public:
0067
0068 CELER_CEF Array() noexcept : d_{T{}} {}
0069
0070
0071 CELER_CEF Array(CArrayConstRef values) noexcept
0072 {
0073 for (size_type i = 0; i < N; ++i)
0074 {
0075 d_[i] = values[i];
0076 }
0077 }
0078
0079
0080 CELER_CEF Array(T first) noexcept : d_{first} {}
0081
0082
0083 template<class... Us>
0084 CELER_CEF Array(T first, Us... rest) noexcept
0085 : d_{first, static_cast<T>(rest)...}
0086 {
0087
0088 static_assert(sizeof...(rest) + 1 == N,
0089 "All array entries must be explicitly specified");
0090 }
0091
0092
0093
0094
0095
0096 CELER_CEF const_reference operator[](size_type i) const noexcept
0097 {
0098 return d_[i];
0099 }
0100 CELER_CEF reference operator[](size_type i) { return d_[i]; }
0101 CELER_CEF const_reference front() const { return d_[0]; }
0102 CELER_CEF reference front() { return d_[0]; }
0103 CELER_CEF const_reference back() const { return d_[N - 1]; }
0104 CELER_CEF reference back() { return d_[N - 1]; }
0105 CELER_CEF const_pointer data() const { return d_; }
0106 CELER_CEF pointer data() { return d_; }
0107
0108
0109
0110
0111 template<std::size_t I>
0112 CELER_CEF T& get() noexcept
0113 {
0114 static_assert(I < static_cast<std::size_t>(N));
0115 return d_[I];
0116 }
0117 template<std::size_t I>
0118 CELER_CEF T const& get() const noexcept
0119 {
0120 static_assert(I < static_cast<std::size_t>(N));
0121 return d_[I];
0122 }
0123
0124
0125
0126
0127 CELER_CEF iterator begin() noexcept { return d_; }
0128 CELER_CEF iterator end() noexcept { return d_ + N; }
0129 CELER_CEF const_iterator begin() const noexcept { return d_; }
0130 CELER_CEF const_iterator end() const noexcept { return d_ + N; }
0131 CELER_CEF const_iterator cbegin() const noexcept { return d_; }
0132 CELER_CEF const_iterator cend() const noexcept { return d_ + N; }
0133
0134
0135
0136
0137 CELER_CEF bool empty() const noexcept { return N == 0; }
0138 static CELER_CEF size_type size() noexcept { return N; }
0139
0140
0141
0142
0143
0144
0145 CELER_CEF void fill(const_reference value) noexcept
0146 {
0147 for (size_type i = 0; i != N; ++i)
0148 {
0149 d_[i] = value;
0150 }
0151 }
0152
0153
0154
0155
0156
0157 template<class U>
0158 CELER_CEF friend auto operator==(Array const& lhs,
0159 Array<U, N> const& rhs) noexcept
0160 -> std::enable_if_t<std::is_convertible_v<U, T>, bool>
0161 {
0162 for (size_type i = 0; i != N; ++i)
0163 {
0164 if (lhs[i] != rhs[i])
0165 return false;
0166 }
0167 return true;
0168 }
0169
0170
0171 template<class U>
0172 CELER_CEF friend auto operator!=(Array const& lhs,
0173 Array<U, N> const& rhs) noexcept
0174 -> std::enable_if_t<std::is_convertible_v<U, T>, bool>
0175 {
0176 return !(lhs == rhs);
0177 }
0178
0179
0180 CELER_CEF friend Array ldg(Array const* arr) noexcept
0181 {
0182 Array result;
0183 for (size_type i = 0; i != N; ++i)
0184 {
0185 result[i] = ldg(&arr->d_[i]);
0186 }
0187 return result;
0188 }
0189
0190 private:
0191 T d_[N];
0192 };
0193
0194
0195
0196
0197
0198
0199
0200 template<class T, class... Us>
0201 CELER_CTAD_FUNCTION Array(T, Us...)
0202 -> Array<std::common_type_t<T, Us...>, 1 + sizeof...(Us)>;
0203
0204
0205
0206
0207 #if !CELER_DEVICE_COMPILE
0208
0209
0210
0211
0212 template<class T, std::size_t N>
0213 CELER_FORCEINLINE std::ostream& operator<<(std::ostream& os,
0214 Array<T, N> const& a)
0215 {
0216 os << StreamableContainer{a.data(), a.size()};
0217 return os;
0218 }
0219 #endif
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 template<class T, std::size_t N>
0230 CELER_CONSTEXPR_FUNCTION auto to_array(T (&x)[N])
0231 {
0232 static_assert(!std::is_array_v<T>,
0233 "to_array elements cannot be multidimensional");
0234 static_assert(std::is_constructible_v<T, T&>,
0235 "to_array elements must be copy constructible");
0236
0237 Array<std::remove_cv_t<T>, N> result;
0238 for (size_type i = 0; i != N; ++i)
0239 {
0240 result[i] = x[i];
0241 }
0242 return result;
0243 }
0244
0245
0246
0247 template<class T, std::size_t N>
0248 CELER_CONSTEXPR_FUNCTION auto to_array(Span<T, N> s)
0249 {
0250 Array<std::remove_cv_t<T>, N> result{};
0251 for (std::size_t i = 0; i < N; ++i)
0252 {
0253 result[i] = s[i];
0254 }
0255 return result;
0256 }
0257
0258
0259 template<class T, std::size_t N>
0260 [[deprecated("use to_array")]] CELER_CONSTEXPR_FUNCTION auto make_array(
0261 Span<T, N> s)
0262 {
0263 return to_array(s);
0264 }
0265
0266
0267
0268
0269
0270 template<class T1, class T2, std::size_t N>
0271 CELER_CONSTEXPR_FUNCTION Array<T1, N> static_array_cast(Array<T2, N> const& x)
0272 {
0273 Array<T1, N> result;
0274 for (size_type i = 0; i != N; ++i)
0275 {
0276 result[i] = static_cast<T1>(x[i]);
0277 }
0278 return result;
0279 }
0280
0281
0282 }
0283
0284
0285
0286 namespace std
0287 {
0288
0289
0290 template<class T, std::size_t N>
0291 struct tuple_size<celeritas::Array<T, N>>
0292 {
0293 static constexpr std::size_t value = N;
0294 };
0295
0296
0297 template<std::size_t I, class T, std::size_t N>
0298 struct tuple_element<I, celeritas::Array<T, N>>
0299 {
0300 static_assert(I < std::tuple_size<celeritas::Array<T, N>>::value);
0301 using type = T;
0302 };
0303
0304
0305 }
0306