Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-04 09:58:26

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/cont/Array.hh
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  * Fixed-size simple array for storage.
0032  *
0033  * The Array class is primarily used for point coordinates (e.g., \c Real3) but
0034  * is also used for other fixed-size data structures.
0035  *
0036  * This is not fully compatible with std::array:
0037  * - no support for N=0
0038  * - zero-initialized by default
0039  * - assume noexcept construction/copying of data
0040  *
0041  * \note For supplementary functionality, include:
0042  * - \c corecel/math/ArrayUtils.hh for real-number vector/matrix applications
0043  * - \c corecel/math/ArrayOperators.hh for mathematical operators
0044  * - \c ArrayIO.json.hh for JSON input and output
0045  */
0046 template<class T, std::size_t N>
0047 class Array
0048 {
0049     static_assert(N > 0);
0050 
0051   public:
0052     //!@{
0053     //! \name Type aliases
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     //! Default construction initializes to zero
0068     CELER_CEF Array() noexcept : d_{T{}} {}
0069 
0070     //! Construct from an array for aggregate initialization of daughters
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     //! Construct with C-style aggregate initialization
0080     CELER_CEF Array(T first) noexcept : d_{first} {}
0081 
0082     //! Construct with the array's data
0083     template<class... Us>
0084     CELER_CEF Array(T first, Us... rest) noexcept
0085         : d_{first, static_cast<T>(rest)...}
0086     {
0087         // Protect against leaving off an entry, e.g. Array<int, 2>(1)
0088         static_assert(sizeof...(rest) + 1 == N,
0089                       "All array entries must be explicitly specified");
0090     }
0091 
0092     //// ACCESSORS ////
0093 
0094     //!@{
0095     //! \name Element access
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     //! Access for structured unpacking
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     //! \name Iterators
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     //! \name Capacity
0137     CELER_CEF bool empty() const noexcept { return N == 0; }
0138     static CELER_CEF size_type size() noexcept { return N; }
0139     //!@}
0140 
0141     //!@{
0142     //! \name  Operations
0143 
0144     //! Fill the array with a constant value
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     //// FRIENDS ////
0155 
0156     //! Test equality of two arrays
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     //! Test inequality of two arrays
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     //! Allow loading via ldg
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];  //!< Storage
0192 };
0193 
0194 //---------------------------------------------------------------------------//
0195 // DEDUCTION GUIDES
0196 //---------------------------------------------------------------------------//
0197 
0198 // Note: this differs from std::array, which deduces from T rather than the
0199 // common type
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 // INLINE DEFINITIONS
0206 
0207 #if !CELER_DEVICE_COMPILE
0208 //---------------------------------------------------------------------------//
0209 /*!
0210  * Write the elements of array \a a to stream \a os.
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 // FREE FUNCTIONS
0223 //---------------------------------------------------------------------------//
0224 /*!
0225  * Convert a C array from type \c T2 to an Array of \c T1.
0226  *
0227  * The standard library version of this function is available since C++20.
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 //! Construct an array from a fixed-size span
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 // DEPRECATED: remove in v1.0
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  * Convert an array from type \c T2 to \c T1.
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 }  // namespace celeritas
0283 
0284 //---------------------------------------------------------------------------//
0285 //! \cond
0286 namespace std
0287 {
0288 //---------------------------------------------------------------------------//
0289 //! Support structured binding: array size
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 //! Support structured binding: array element type
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 }  // namespace std
0306 //! \endcond